如果函数中的语句是最好的方法

时间:2009-06-23 14:56:20

标签: coding-style conditional-statements

如果我有大量条件的功能,那么组织它的最佳方法是什么?

我担心的是其他人进入代码并了解正在发生的事情。即使示例很简单,也可以想象条件非常复杂。

举个例子:

public void function(string value, string value2)
{
    if (value == null)
        return;

    if (value2 == value)
        DoSomething();
}

public void function(string value, string value2)
{
    if (value != null)
    {
        if (value2 == value)
            DoSomething();
    }
}

public void function(string value, string value2)
{
    if (value != null && value2 == value)
        DoSomething();
}

11 个答案:

答案 0 :(得分:8)

我更喜欢第一个选项 - fail fast更清晰,更清晰,更易于阅读和理解。

我知道这不是失败,但这个概念仍然适用。我真的不喜欢嵌套的if语句。

答案 1 :(得分:8)

您可以查看防御性编程,以确保可以实现方法功能的合同。

public void function(string value, string value2)
{
    if (string.IsNullOrEmpty(value1)) throw new ArgumentNullException("value1", "value 1 was not set");
    if (string.IsNullOrEmpty(value2)) throw new ArgumentNullException("value2", "value 2 was not set");

    DoSomething();
}

答案 2 :(得分:8)

组织条件并将它们放入方法中。

例如

替换它:

 if( a& & n || c  && ( ! d || e ) && f > 1 && ! e < xyz ) { 
      // good! planets are aligned.
      buyLotteryTicket();
 } else if( ..... oh my ... ) { 
 }

进入这个:

if( arePlanetsAligned() ) { 
    buyLotteryTicket(); 
} else if( otherMethodHere() ) { 
   somethingElse();
}  

这样,你使用什么样的风格(1,2或3)并不重要,因为if语句将清楚地描述被测试的条件。不需要额外的构造。

重点是使代码更清晰,自我记录。如果您使用的是OO编程语言,则可以使用对象来存储状态(变量),并避免创建需要5-10个参数的方法。

这些是类似的问题:

Best way to get rid of nested ifs

Is there an alternative to this hyperidented code

第二个链接显示了一个更加完整和复杂的方法,将可怕的每个维护者噩梦转变为自我记录的代码。

它显示了如何转换它:

public String myFunc(SomeClass input)
{
    Object output = null;

    if(input != null)
    {
        SomeClass2 obj2 = input.getSomeClass2();
        if(obj2 != null)
        {
            SomeClass3 obj3 = obj2.getSomeClass3();
            if(obj3 != null && !BAD_OBJECT.equals(obj3.getSomeProperty()))
            {
                SomeClass4 = obj3.getSomeClass4();
                if(obj4 != null)
                {
                    int myVal = obj4.getSomeValue();
                    if(BAD_VALUE != myVal)
                    {
                        String message = this.getMessage(myVal);
                        if(MIN_VALUE <= message.length() &&
                           message.length() <= MAX_VALUE)
                        {
                            //now actually do stuff!
                            message = result_of_stuff_actually_done;
                        }
                    }
                }
            }
        }
    }
    return output;
}

进入这个:

if ( isValidInput() && 
    isRuleTwoReady() &&
    isRuleTreeDifferentOf( BAD_OBJECT ) &&
    isRuleFourDifferentOf( BAD_VALUE ) && 
    isMessageLengthInRenge( MIN_VALUE , MAX_VALUE ) ) { 
            message = resultOfStuffActuallyDone();
}

答案 3 :(得分:2)

重新构建它自己的功能。读取描述性函数名称比使用一堆布尔表达式更好。

// leave complex conditional code out, so that we can focus on the larger problem in the function
public void function(string value, string value2)
{
    if (MyDescriptiveTestName)
    {
        DoSomething();
    }
}

// encapsulate complex conditional code so that we can focus solely on it.
private bool MyDescriptiveTestName(string value, string value2)
{
    if (value != null && value2 == value)
    {
        return true;
    }
    return false;
}

答案 4 :(得分:2)

我可以推荐Robert C. Martin的书Clean Code,它提供了一套很好的启发式方法来编写可读和可维护的代码。

现在另一种选择是将条件提取到另一个私有函数中并命名它以便它描述你的意图。它与提供的代码不能很好地工作,因为它是通用的,但它看起来像:

public void function(string value, string value2)
{
    if (valuesAreValidAndEqual(value, value2))
    {
        DoSomething();
    }
}

private void valuesAreValidAndEqual(string value, string value2)
{
    return value != null && value2 == value;
}

显然,如果变量名称和函数名称与您的域相关,这将更有用。

答案 5 :(得分:1)

如果你有一个包含很多条件的函数,我会使用switch语句 - 而不是ifs。如果可能的话,我也可能将细节分解为几个函数(甚至是类)。

相关的堆栈溢出文章

答案 6 :(得分:0)

我喜欢第三种选择,但这实际上取决于语言。您假设在第三个语句的第一部分将失败而不执行第二部分。这取决于语言。我知道大多数基于C的语言都是这样做的,但是因为你没有指定一个潜在的问题。可能有一个我不知道没有短路概念的那个。

答案 7 :(得分:0)

您事先考虑代码可读性的事实只有一半。

至于哪些示例最具可读性,这是非常主观的。

我对给出的例子的想法:

  • 就个人而言,我认为第一个例子最简单 跟随。
  • 最小化嵌套级别和/或 通常的条件数 增强可读性。
  • 有些人会反对多重 从一个方法退出点(比如 例1),但我认为只是 当方法成为一个问题 真的很长这不是真的 如果你只是,这么大的交易 检查输入并快速失败。

答案 8 :(得分:0)

我的偏好是第二种选择。就个人而言,当我阅读这样的代码时,我会记住进入每个嵌套级别的条件。在第一个例子中,我可能会忘记第一个条件(value == null为false)继续保持。第三个也不错,但我更喜欢第二个。

答案 9 :(得分:0)

你在函数中有那么多语句的事实表明函数应该被分成更小的函数。

没有最好的方式来放置if语句,我认为答案是主观的。

答案 10 :(得分:0)

清晰度通常很难判断。当你编写一段代码时,对你来说很清楚,对其他人来说可能是完全愚蠢的 - 甚至在经过足够的时间之后对你自己也是如此。

在构建具有许多条件检查的函数时,以下是我个人的经验法则:

  1. 在可能的情况下将条件分组为逻辑单元
  2. 使用明确命名的中间值来简化可读性和调试。
  3. 避免多次重复使用相同的逻辑结构(参见上文)。
  4. 如果可能,将复杂或昂贵的条件重构为单独的函数。
  5. 如果可能,请使用方法顶部的提前退出条件退出,但是......
  6. 避免在整个方法中使用返回语句。
  7. 不要依赖运算符优先级,请使用括号对语句进行分组。
  8. 避免依赖缩进,使用块({...}),即使只有一个语句,这有助于维护。