代码之家  ›  专栏  ›  技术社区  ›  rudnev

C中丑陋嵌套if-else树的简化方法#

  •  5
  • rudnev  · 技术社区  · 15 年前

    有时,我在C 3.5中编写了难看的if-else语句;我知道通过表驱动的开发、类层次结构、异常方法以及其他一些方法来简化这一点的一些不同方法。 问题是,与写传统的丑陋的if-else语句相比,其他选项的传播范围仍然比较小,因为没有这样的约定。

    如果C 3.5正常,嵌套深度是多少?如果第一个方法不是嵌套的,您希望看到什么方法?第二个?

    如果我有10个输入参数,每个参数有3个状态,我应该将函数映射到每个参数的每个状态的组合(实际上更少,因为不是所有状态都有效,但有时仍然很多)。我可以将这些状态表示为哈希表键和处理程序(lambda),如果键匹配,将调用它。

    它仍然混合了表驱动、数据驱动的开发思想和模式匹配。

    我要寻找的是扩展到C这样的脚本编写方法(C 3.5相当于脚本编写) http://blogs.msdn.com/ericlippert/archive/2004/02/24/79292.aspx

    11 回复  |  直到 15 年前
        1
  •  4
  •   BillW    15 年前

    有一些非常古老的“形式主义”试图封装极其复杂的表达式,这些表达式计算许多可能独立的变量,例如“决策表”:

    http://en.wikipedia.org/wiki/Decision_table

    但是,我将加入唱诗班,在这里提出第二个想法,如果可能的话,明智地使用三元运算符,确定最不可能的条件,如果满足,允许您通过首先排除它们来终止评估的其余部分,并添加…与之相反…试图找出最可能的条件和状态,使您可以继续进行而不测试“边缘”情况。

    米里亚姆(上面)的建议是迷人的,甚至是优雅的,作为“概念艺术”;我实际上将尝试它,试图“括号”我的怀疑,它将导致代码难以维护。

    我的语用观点认为,如果没有一个非常具体的代码示例,以及对条件及其交互的完整描述,这里就没有“一刀切”的答案。

    我是“标志设置”的粉丝:这意味着每当我的应用程序进入一些不太常见的“模式”或“状态”时,我都会设置一个布尔标志(这对于类来说可能是静态的):对于我来说,这简化了以后编写复杂的if/then-else计算。

    最好的,比尔

        2
  •  8
  •   Ewan Todd    15 年前

    好问题。”条件复杂性”是一种代码味道。 Polymorphism 是你的朋友。

    条件逻辑在其幼年时期是无辜的,当时它很容易理解并包含在 几行代码。不幸的是,它很少老化。您实现了几个新功能和 突然你的条件逻辑变得复杂和扩展。[Joshua Kerevsky:模式重构]

    要避免嵌套if块,可以做的最简单的事情之一是学会使用 Guard Clauses .

    double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired) return retiredAmount();
    return normalPayAmount();
    };  
    

    我发现的另一件事可以很好地简化事情,使代码能够自我记录,那就是 Consolidating conditionals .

    double disabilityAmount() {
        if (isNotEligableForDisability()) return 0;
        // compute the disability amount
    

    其他有价值的 refactoring 与条件表达式相关联的技术包括 Decompose Conditional ,请 Replace Conditional with Visitor , Specification Pattern ,和 Reverse Conditional .

        3
  •  4
  •   aviraldg Ortiga    15 年前

    简单。把国际单项体育联合会的机构,并制定出一个方法。

    这是因为大多数if语句的形式是:

    if (condition):
       action()
    

    在其他情况下,更具体地说:

    if (condition1):
       if (condition2):
          action()
    

    简化为:

    if (condition1 && condition2):
       action()
    
        4
  •  2
  •   gargantuan    15 年前

    我是三元运算符的忠实拥趸,它被很多人忽视了。它非常适合根据条件为变量赋值。这样地

    foobarString = (foo == bar) ? "foo equals bar" : "foo does not equal bar";
    

    尝试 this article 更多信息。

    它不能解决你所有的问题,但它是非常经济的。

        5
  •  2
  •   Ed Swangren    15 年前

    我知道这不是你要找的答案,但是没有上下文,你的问题很难回答。问题是,重构这样一个东西的方法实际上取决于您的代码、它在做什么以及您试图完成什么。如果你说你在检查 类型 对于这些条件中的对象,我们可以抛出一个类似“使用多态性”的答案,但有时实际上您只需要一些if语句,有时这些语句可以重构为更简单的语句。如果没有代码示例,很难确定您属于哪个类别。

        6
  •  2
  •   jac    15 年前

    几年前一位老师告诉我3是一个神奇的数字。当他应用它时,他建议如果我需要更多的3个if,那么我应该使用case语句来代替。

       switch (testValue)
       {
          case = 1:
             // do something
             break;
          case = 2:
             // do something else
             break;
          case = 3:
             // do something more
             break;
          case = 4
             // do what?
             break;
          default:
             throw new Exception("I didn't do anything");
       }
    

    如果您嵌套的if语句超过3个深度,那么您可能应该将其作为一个信号,表明存在更好的方法。可能像Avirdlg建议的那样,将嵌套的if语句分离为1个或多个方法。如果你觉得你完全被多个if-else语句困住了,那么我将把所有if-else语句包装成一个方法,这样它就不会使其他代码变得丑陋。

        7
  •  1
  •   Charles Bretana    15 年前

    如果整个目的是根据各种条件的状态为某个变量分配不同的值,那么我使用ternery运算符。

    如果if else子句正在执行单独的功能块。条件很复杂,通过创建临时布尔变量来保存复杂布尔表达式的真/假值,从而简化了条件。这些变量应该适当命名,以表示复杂表达式正在计算的业务意义。然后使用if-else synatx中的布尔变量,而不是复杂的布尔表达式。

        8
  •  1
  •   Ðаn    15 年前

    我发现自己有时会做的一件事是改变情况,然后 return ;连续进行几次这样的测试有助于减少 if else .

        9
  •  1
  •   MichaelGG    15 年前

    不是C答案,但您可能希望模式匹配。通过模式匹配,您可以接受多个输入,并对所有输入进行同时匹配。例如(f):

    let x=
      match cond1, cond2, name with
      | _, _, "Bob"     -> 9000 // Bob gets 9000, regardless of cond1 or 2
      | false, false, _ -> 0 
      | true, false, _  -> 1
      | false, true, _  -> 2
      | true, true, ""  -> 0 // Both conds but no name gets 0
      | true, true, _   -> 3 // Cond1&2 give 3
    

    你可以表达任何组合来创建一个匹配(这只是擦伤表面)。但是,C不支持这一点,我怀疑很快会出现这种情况。同时,也有一些尝试在C中尝试此方法,例如: http://codebetter.com/blogs/matthew.podwysocki/archive/2008/09/16/functional-c-pattern-matching.aspx . 谷歌可以出现更多,也许其中一个适合你。

        10
  •  0
  •   Ilya Khaprov    15 年前

    尝试使用策略或命令之类的模式

        11
  •  0
  •   Andriy Volkov    15 年前

    在简单的情况下,您应该能够绕过基本的功能分解。对于更复杂的场景,我使用 Specification Pattern 非常成功。