如果(条件)继续;或者if(!condition){...}? (风格偏好)

时间:2008-12-24 14:18:47

标签: coding-style

我知道这是一个风格问题,因此是主观标签。我有一小段代码,有两个嵌套条件。我可以用两种方式对它进行编码,我希望看到更有经验的开发人员认为应该是这样的。

样式1

while (!String.IsNullOrEmpty(msg = reader.readMsg()))
{
    RaiseMessageReceived();
    if (parseMsg)
    {
        ParsedMsg parsedMsg = parser.parseMsg(msg);
        RaiseMessageParsed();
        if (processMsg)
        {
            process(parsedMsg);
            RaiseMessageProcessed();
        }
    }
}

样式2:

while (!String.IsNullOrEmpty(msg = reader.readMsg()))
{
    RaiseMessageReceived();
    if (!parseMsg) continue;

    ParsedMsg parsedMsg = parser.parseMsg(msg);
    RaiseMessageParsed();
    if (!processMsg) continue;

    process(parsedMsg);
    RaiseMessageProcessed();
}

(旁边的问题:如何在源代码示例中添加空行?)

23 个答案:

答案 0 :(得分:22)

我更喜欢Style 1 - 带缩进。

答案 1 :(得分:13)

我更喜欢Style 2 - 使用continue语句。

答案 2 :(得分:8)

原则上我同意大多数喜欢风格1的人。这就是Steve Mcconnell在“代码完成”中所赞同的 - 说出你的意思,即你是否对条件是真实的更感兴趣,而虚假状态是罕见的或不首选,然后说明首选版本。

在实践中虽然我经常发现自己使用样式2,因为我喜欢先清除所有可能的错误/无效状态。在我摆脱了我不感兴趣的所有可能性之后,我可以将心脏代码编写到例程的末尾,而不必经常想知道我是否需要防范某些条件或其他条件。基本上,态度是,摆脱糠,,然后平静地做真正的工作。

答案 3 :(得分:5)

这两个都是虚假的。不要将赋值放在条件表达式中。

(!String.IsNullOrEmpty(msg = reader.readMsg()))

你只是这样做是因为读者的行为不稳定 - 为什么读者会给你一条非信息表明读完了?这是一个有更好设计的读者的替代方案:

while (reader.HasMessage())
{
  string msg = reader.GetMessage();
  HandleMessage(msg);
}

答案 4 :(得分:4)

我绝对更喜欢第一个版本。当过度使用时,continue语句非常好。

我将这与多个return语句一样对待。它们适用于防护条款,并且在提高清晰度时具有良好的实用性,但不应过度使用。

此外,一行中的两个空格应该在代码块中为您插入换行符。

答案 5 :(得分:3)

我更喜欢Style2。此外,在Refactoring.com上描述了相同的样本 Replace Nested Conditions

答案 6 :(得分:3)

我想以不同的方向重构此代码。你的代码做了太多事情!

  1. 阅读输入
  2. 迭代
  3. 提高通知
  4. 解析(有条件!(通知!!))
  5. 处理(有条件!(通知!!))
  6. 我认为我们需要在这里进行一些分离。我想探索:

    • 将读数输入移至迭代器(yield return)。
    • 将条件移至Strategy Pattern

答案 7 :(得分:2)

在所示的示例中,我将使用样式1.如果我的方法足够大以至于嵌套成为问题(并且没有更好的方法来重构代码),那么我会考虑样式2但是对于所显示的两个小巧的案例,肯定是风格1。

答案 8 :(得分:2)

风格1简直就是CLEARER,恕我直言。没有什么可以反对继续本身,但正如人们之前所说的,缩进使得更容易追随。

答案 9 :(得分:2)

样式2让人类读者专注于重要的代码,甚至不看任何不相关的东西 - 你会看到continue语句,下面的任何内容都无关紧要。

样式2管理复杂性,因此可以扩展到更复杂的方法,样式1很快变得难以管理。

答案 10 :(得分:2)

出于多种原因,我个人更喜欢风格2;

  • 你可以点击一个潜在的错误,你在if之后缩进但忘记了大括号。

  • 您遇到浮动的其他问题的风险较小,例如,如果有其他属于的话,您可能会混淆多个嵌套ifs。

  • 您可以避免过多的缩进,从而导致代码离开页面

当我编码时,我倾向于将继续分开;

if (!parseMsg) 
    continue;

由于它使其更加明显的原因,并且更容易为其分配断点。

答案 11 :(得分:1)

我发现继续语句使代码更难以遵循(因此调试)。有些情况下你可能会使用它们,但我认为你的例子不是其中之一。

答案 12 :(得分:1)

虽然我更喜欢样式1.我发现有时使用样式2很有用,因为它有助于降低缩进级别并使代码更容易阅读。

任何一种风格都是诚实的,这完全取决于个人选择。

答案 13 :(得分:0)

两种选择都很尴尬。从样式2 开始,将while循环的内部提取到新方法中,并将continue语句更改为return语句。它仍然需要更多的重构。

continue关键字很笨拙,但很容易理解return语句。此选项几乎没有嵌套缩进。

答案 14 :(得分:0)

尽可能避免使用continue语句。

我们尽量避免使用goto,不要我们 - 它是否也有意义避免它的堂兄continue

答案 15 :(得分:0)

我发现风格1更容易理解。所以我更喜欢风格1。

答案 16 :(得分:0)

Guard子句适用于条件函数返回,因为它创建了一个完整的语句。在一个地方,你知道发生了什么(我们在这里完成)。

continue语句通常需要更多考虑。我个人觉得如果你在一个循环中使用多个continue语句,那你就做错了。

我认为第一种类型是自我记录和标准方式。当你违反标准方式时,你需要添加评论。

答案 17 :(得分:0)

如果某人以后必须维护此代码以在msg上添加可能或可能不依赖于消息是否已被解析和/或处理的进一步操作,那么如果代码的格式为1,则更简单。在风格2中,因此我更喜欢风格1.

答案 18 :(得分:0)

我的偏好是样式1,但如果!parseMsg或!processMsg经常发生,我会在心跳中使用样式2。总是把最可能的情景放在第一位 - 对吧?

答案 19 :(得分:0)

在担心化妆品不相关之前,我会删除使用全局变量来在函数之间进行通信。据推测,您的语言支持函数的返回值。使用这些

  • 表示每个步骤的成功或失败,或
  • 让每个转换函数返回下一个状态

哪个更清楚。

答案 20 :(得分:0)

我更喜欢样式1并将continue语句等同于goto语句。我承认它在执行过程中可能不如另一个有效,但我发现代码理解效率几乎总是比代码执行效率更重要。

答案 21 :(得分:0)

第一种风格肯定更清晰 - 它表示你(显然)意味着什么,即获取消息,如果设置了parseMsg标志,则尝试解析它;如果成功,请处理它。另一方面,第二个版本将处理明显更少的指令,尤其是在设置parseMsg的情况下。我很想走到两者之间:

while (!String.IsNullOrEmpty(msg = reader.readMsg())){
    RaiseMessageReceived();

    if (!parseMsg) continue ;

    ParsedMsg parsedMsg = parser.parseMsg(msg);
    RaiseMessageParsed();
    if (processMsg){
       process(parsedMsg);
       RaiseMessageProcessed();
    }
}

...关于你在解析被关闭的特殊情况下跳过所有解析的理论。

答案 22 :(得分:0)

我更喜欢带有缩进的样式1,它更清晰,更容易理解只是通过查看它我可以看到代码的布局。