Coding style 如果在函数中使用语句,最好的方法是什么

Coding style 如果在函数中使用语句,最好的方法是什么,coding-style,conditional-statements,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)
        return;

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


我更喜欢第一种选择——更清晰,更容易阅读和理解


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

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

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();
}

我喜欢第三种选择,但这取决于语言。您假设在第三个语句中,语句的第一部分将失败,而不会执行第二部分。这取决于语言。我知道大多数基于C的语言都可以做到这一点,但由于您没有指定一种,这是一个潜在的问题。可能有一个我不知道的没有短路概念的函数。

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

相关堆栈溢出文章


您提前考虑代码可读性的事实是成功的一半

至于你的例子中哪一个最具可读性,这是相当主观的

我对以下例子的看法:

  • 我个人认为第一个例子最容易理解 跟着
  • 最小化嵌套级别和/或 条件句的数量通常为 提高可读性
  • 有些人会反对多重选择 方法的退出点(如 例1),但我认为 当该方法 变得很长。这不是真的 如果你只是 检查输入并快速失败

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

将这些东西重构成它自己的函数。读取一个描述性函数名比读取一堆布尔表达式要好得多

// 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;
}

组织条件并将其转化为一种方法

例如:

 if( a& & n || c  && ( ! d || e ) && f > 1 && ! e < xyz ) { 
      // good! planets are aligned.
      buyLotteryTicket();
 } else if( ..... oh my ... ) { 
 }
这样,使用什么样式(1、2或3)并不重要,因为if语句将清楚地描述测试的条件。不需要额外的构造

关键是要使代码更清晰,并且能够自我记录。如果您使用的是OO编程语言,那么您可以使用对象来存储状态(变量),并避免创建包含5-10个参数的方法

这些都是类似的问题:

第二个链接显示了一种更完整、更复杂的方法,可以将可怕的“每个人维护者”噩梦转换为自文档代码

它显示了如何转换此项:

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;
}
我可以推荐Robert C.Martin的书,它为编写可读和可维护的代码提供了一套很好的启发式方法

现在,另一个选项是将条件提取到另一个私有函数中,并命名它,以便它描述您的意图。它与提供的代码不太兼容,因为它是泛型的,但它看起来像:

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

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

显然,如果变量名和函数名与您的域相关,则这一点更为有用。

一个函数中有这么多语句,这表明该函数应该划分为更小的语句


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

清晰性通常很难判断。当你在写一段代码时,对你来说很清楚的事情可能对其他人来说是完全迟钝的——或者在足够长的时间之后对你自己来说也是如此

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

  • 如果可能,将条件分组为逻辑单元
  • 使用名称明确的中间值简化可读性和调试
  • 避免多次重复相同的逻辑结构(参见上文)
  • 如果可能,将复杂或昂贵的条件重构为单独的函数
  • 如果可能,使用方法顶部的早期退出条件退出,但是
  • 避免在整个方法体中使用尖刻的返回语句
  • 不要依赖运算符优先级,使用括号将语句分组
  • 避免依赖缩进,即使只有一条语句也使用块({…}),这有助于提高可维护性

  • 这三个示例实际上都失败得很快,它们执行相同的null测试,如果value==null,则立即返回如果您必须释放任何资源呢?然后,您需要在每个return语句之前复制此清理代码。我想说第二个和第三个选项要好得多。@SpaceghostAli:是的,你是对的,但这是一个很小的例子,而且大多数情况下并不简单@msvcyc:如果你需要释放资源,那么你真的应该使用try/finally块或using语句(如果适用)。这一点很好。很多嵌套条件可能是一个方法试图做得太多(内聚性低)的症状。在处理失败时,此选项还为您提供了更大的灵活性,这可以通过断言更好地实现。值得注意的是,上面代码的行为与原始问题中的行为不同。扔掉if语句。。。“return value!=null&&value2==value”这是一个很好的调用,当时我甚至没有考虑过它,但我相信我会在重构中捕捉到它
    if( arePlanetsAligned() ) { 
        buyLotteryTicket(); 
    } else if( otherMethodHere() ) { 
       somethingElse();
    }  
    
    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();
    }
    
    public void function(string value, string value2)
    {
        if (valuesAreValidAndEqual(value, value2))
        {
            DoSomething();
        }
    }
    
    private void valuesAreValidAndEqual(string value, string value2)
    {
        return value != null && value2 == value;
    }