帮助重构此C#函数

帮助重构此C#函数,c#,C#,我编写的函数如下所示: bool IsDry(bool isRaining, bool isWithUmbrella) { if (isRaining) { if (isWithUmbrella) return true; else return false; } else return true; } 我需要检查一下,如果下雨,那么这个人需要带伞以保持干燥(不要笑,这只是一

我编写的函数如下所示:

bool IsDry(bool isRaining, bool isWithUmbrella) {
    if (isRaining) {
        if (isWithUmbrella)
            return true;
        else
            return false;
    }
    else
        return true;
}
我需要检查一下,如果下雨,那么这个人需要带伞以保持干燥(不要笑,这只是一个例子,我们的实际业务规则比这更严肃)

我如何重构它,因为现在它看起来很笨拙


谢谢你们的帮助,伙计们!=)

看起来您试图实施的业务规则是:

P IMPLIES Q
这在逻辑上等同于:

(NOT P) OR Q
因此,您可以简单地编写:

bool IsDry(bool isRaining, bool isWithUmbrella) {
    return !isRaining || isWithUmbrella;
}

论(非)消极思维 根据谓词的不同,首先考虑否定也可能更简单

NOT (P IMPLIES Q)
我们现在替换上面的标识:

NOT ((NOT P) OR Q)
现在我们可以申请:

既然这是否定的,我们必须否定它才能回到积极的一面。一开始,双重否定似乎令人困惑,但回到示例,我们有:

bool IsDry(bool isRaining, bool isWithUmbrella) {
    bool isWet = (isRaining && !isWithUmbrella);
    return !isWet;
}

附加提示 下面是一些常见的
布尔
表达式重写示例:

BEFORE                                  | AFTER
________________________________________|________________________________________
                                        |
if (condition == true) ...              | if (condition) ...
________________________________________|________________________________________
                                        |
if (condition == false) ...             | if (!condition) ...
________________________________________|________________________________________
                                        |
if (condition) {                        | return condition;
    return true;                        |
} else {                                |
    return false;                       |
}                                       |
________________________________________|________________________________________
                                        |
if (condition1) {                       | return (condition1 && condition2
   if (condition2) {                    |             && condition3);
      if (condition3) {                 |
         return true;                   |
      } else {                          |
         return false;                  |
      }                                 |
   } else {                             |
      return false;                     |
   }                                    |
} else {                                |
   return false;                        |
}                                       |
________________________________________|________________________________________
                                        |
return (condition1 && !condition2) ||   | return condition1 != condition2;
   (condition2 && !condition1);         | // or  condition1 ^ condition2;
请注意,C#中预定义的
^
即使对于整数类型(即,它不是一个求幂运算符)也是相同的。预定义的和用于执行“短路”评估的

另见
    • 这是一个真值表:

      isRaining    isWithUmbrella    isWet    isDry 
      true         true              false    true
      true         false             true     false
      false        true              false    true
      false        false             false    true
      
      有一个答案可能是:

      var isWet = isRaining && !isWithUmbrella;
      return !isWet;
      

      我通常采用的方法是逐步细化。e、 g.如果出现以下情况,则首先消除内部缺陷:

      bool IsDry(bool isRaining, bool isWithUmbrella) {
          if (isRaining)
              return isWithUmbrella;
          else
              return true;
      }
      
      然后将if崩溃

      bool IsDry(bool isRaining, bool isWithUmbrella) {
          return isRaining ? isWithUmbrella : true;
      }
      
      这是非常明显的

      布尔没有训练{带伞返回}

      :-)

      只需单击六下,即可将代码简化为一行

      前三次点击将变形

       if (isWithUmbrella)
                          return true;
                      else
                          return false;
      
      进入

      接下来的三次点击会改变

          if (isRaining)
          {
              return isWithUmbrella;
          }
          else
              return true;
      
      进入

      瞧,你完了

      我如何重构这个

      使用单元测试

      真的。有两个布尔输入,所以您只需要四个单元测试就可以完全覆盖此方法

      然后,由于已经有了完整的分支覆盖,您就可以对实现进行操作了。尝试一些似乎正确的方法(我发现在这种情况下编写一个真值表非常有帮助),测试将告诉您是否有错误的细节

      作为进一步的好处,您可以将测试作为方法实际功能的文档永久保存。如果你选择了一个聪明的实现,比如奇特的布尔表达式,这尤其有用——如果你在努力遵循流程,你可以看看测试,然后看到“哦,我明白了——如果我通过了这个和这个,我就得到了这个。”

      首先从“else return…”语句中删除“else”,这样你就得到了:

      if (isRaining) {
          if (isWithUmbrella)
              return true;
          return false;
      }
      return true;
      
      只要一点逻辑工作

      if (isRaining) {
      //    return (isWithUmbrella) ?
      //        true :
      //        false;
          return isWithUmbrella;
      }
      return true;
      
      然后,您可以快速将其放入一个简单的return语句中

      //return (isRaining) ? isWithUmbrella : true;
      //return (!isRaining) ? true : isWithUmbrella;
      return (!isRaining) || isWithUmbrella;
      

      +1.再加上,
      !(isRaining&!IsWithumber)
      相当于DeMorgan的
      (!isRaining | | IsWithumber)
      。可能有助于获得您的答案投票。如果你解释p意味着q是描述数学。。。哦,55票不要紧:)哦,天哪,太糟糕了,OP没有注册。你应该多获得一枚大师徽章!虽然您的代码过于冗长,但我要提醒您不要在一行中使用两个以上的变量来编写逻辑表达式。随着单行逻辑表达式变得越来越复杂,重构它们变得越来越容易出错,因为它们可读性较差。例如,尝试添加ISindor作为另一个变量。请注意,对于人类来说,一行代码在飞行中解析变得更加困难。当重构简洁并不意味着可读性时,请记住这一点;否则返回false反模式@米奇:多亏了那次投票,我想我在代表系统上发现了一个潜在的漏洞。现在在meta上发布。@Null,这是一场人气竞赛,你不知道吗+1对你来说无效。开发软件和缺乏幽默感是造成痛苦的一个必然原因。如果你解释了为什么ReSharper会有帮助,这个答案可能会很有用。我已经添加了一个解释。感谢您的反馈。为什么不只是:
      return(!(isRaining&&!iswithumbrane))?我试图通过给内部布尔表达式一个明确的含义来表示意图。希望它能让后来带着isAlreadyWetAnyway旗帜的人更容易地把它放在正确的位置。+1!这还将从调用方的角度显示用法,这有助于设计。if(IsDry(true,false))在客户机代码中很难解释-布尔值代表什么?也许这可能是一个具有IsRaining和HasUmbrella属性的类的实例方法。
      
      return isWithUmbrella;
      
          if (isRaining)
          {
              return isWithUmbrella;
          }
          else
              return true;
      
          return !isRaining || isWithUmbrella;
      
      if (isRaining) {
          if (isWithUmbrella)
              return true;
          return false;
      }
      return true;
      
      if (isRaining) {
      //    return (isWithUmbrella) ?
      //        true :
      //        false;
          return isWithUmbrella;
      }
      return true;
      
      //return (isRaining) ? isWithUmbrella : true;
      //return (!isRaining) ? true : isWithUmbrella;
      return (!isRaining) || isWithUmbrella;