代码之家  ›  专栏  ›  技术社区  ›  John Topley

编程风格:如果一个守卫条件不满足,你应该早点回来吗?

  •  30
  • John Topley  · 技术社区  · 16 年前

    // Style 1
    public SomeType aMethod() {
      SomeType result = null;
    
      if (!guardCondition()) {
        return result;
      }
    
      doStuffToResult(result);
      doMoreStuffToResult(result);
    
      return result;
    }
    
    // Style 2
    public SomeType aMethod() {
      SomeType result = null;
    
      if (guardCondition()) {
        doStuffToResult(result);
        doMoreStuffToResult(result);
      }
    
      return result;
    }
    
    12 回复  |  直到 14 年前
        1
  •  39
  •   unbeli    16 年前

    我更喜欢第一种样式,只是在不需要变量时我不会创建它。我会这么做:

    // Style 3
    public SomeType aMethod() {
    
      if (!guardCondition()) {
        return null;
      }
    
      SomeType result = new SomeType();
      doStuffToResult(result);
      doMoreStuffToResult(result);
    
      return result;
    }
    
        2
  •  29
  •   Eight-Bit Guru    16 年前

    我在80年代末接受过Jackson结构化编程的培训,我根深蒂固的理念是“函数应该有一个入口点和一个出口点”;这意味着我按照样式2编写代码。

    在过去的几年里,我逐渐意识到用这种风格编写的代码往往过于复杂,而且很难阅读/维护,我已经改用了风格1。

    谁说老狗学不了新把戏

        3
  •  16
  •   Mike DeSimone    16 年前

    风格1是Linux内核间接推荐的。

    http://www.kernel.org/doc/Documentation/CodingStyle

    现在,有些人会说有8个字符的缩进 代码向右移动得太远,使得在屏幕上很难阅读 80字符终端屏幕。答案是 如果你需要的话

    样式2增加了缩进的层次,因此不鼓励这样做。

    就我个人而言,我也喜欢风格1。样式2使得在具有多个保护测试的函数中更难匹配右大括号。

        4
  •  6
  •   tanascius    16 年前

    我不知道 在这里是正确的词。通常,不满意的保护会导致异常或断言。
    但除此之外 我会选择风格一 ,因为在我看来,它使代码更干净。你有一个简单的例子,只有一个条件。但是在很多条件和样式2中会发生什么呢?它会导致很多嵌套的 if s或巨大if条件(带 || , &&
    但这肯定是非常主观的^^

        5
  •  5
  •   OlimilOops    16 年前

    如果您使用.net Reflector深入研究.net框架,您将看到.net程序员使用样式1(或者unbeli已经提到的样式3)。 上面的答案已经提到了原因。也许还有一个原因是为了让代码更可读、更简洁、更清晰。 这种样式最常用的是在检查输入参数时,如果您编写了一种frawework/library/dll,则必须这样做。 首先检查所有输入参数,然后再使用它们。

        6
  •  5
  •   bugdayci    11 年前

    "Replace Nested Conditional with Guard Clauses"

    If/else语句也带来了圈复杂度。因此更难测试用例。为了测试所有if/else块,您可能需要输入许多选项。

    如果有任何保护子句,可以首先测试它们,并以更清晰的方式处理if/else子句中的真实逻辑。

        7
  •  4
  •   Daniel Trebbien    16 年前

    它有时取决于语言和您使用的“资源”类型(例如,打开的文件句柄)。

    return 直到函数的最后一步或限制函数的出口数时,程序员才能更容易地确保正确地清理,从而有助于防止内存泄漏、处理泄漏、死锁和其他问题。

    在C++中使用 RAII -样式编程,两种样式都是同样安全的,所以您可以选择一种更方便的样式。个人而言,我使用样式1与RAII风格C++。没有RAII的C++就像C,所以,在这种情况下,样式2可能更好。

    在像Java这样带有垃圾收集的语言中,运行时有助于消除这两种样式之间的差异,因为它会在自身之后进行清理。但是,如果不显式地“关闭”某些类型的对象,这些语言也可能存在一些微妙的问题。例如,如果你构造一个新的 java.io.FileOutputStream 别这样 close 在返回之前,关联的操作系统句柄将保持打开状态,直到运行时垃圾收集 FileOutputStream 实例已超出范围。这可能意味着需要打开文件进行写入的另一个进程或线程在 实例已收集。

        8
  •  3
  •   Adam Driscoll    16 年前

    尽管这与我所学的最佳实践背道而驰,但当我遇到这样的情况时,我发现减少if语句的嵌套要好得多。我认为它更容易阅读,虽然它存在于多个地方,但仍然很容易调试。

        9
  •  1
  •   raisercostin    14 年前

    当你有大方法的时候,Style2看起来是一个更好的解决方案。当你拥有它们的时候。。。无论如何退出,您都有一些想要执行的公共代码。但正确的解决办法不是强迫一个单一的退出点,而是使方法变小。

    例如,如果你想从一个大方法中提取一系列代码,而这个方法有两个退出点,你就开始有问题,很难自动完成。当我有一个用style1编写的大方法时,我通常在style2中转换它,然后我提取方法,然后在每个方法中我都应该有style1代码。

    所以Style1是最好的,但是与小方法兼容。 Style2不是很好,但是如果你有不想要的大方法,建议你有时间来拆分。

        10
  •  0
  •   aCuria    16 年前

    此外,大多数情况下,您都希望返回一个逻辑上不可能的结果(ie-1)值,以向调用函数的用户指示函数未能正确执行并采取适当的操作。这也更适合于方法1。

        11
  •  0
  •   BenMorel Manish Pradhan    12 年前

    如果在离开函数/方法之前必须执行多于2或3行的清理序列,我更喜欢样式2,因为清理序列只需编写和修改一次。这意味着可维护性更容易。

    在所有其他情况下,我更喜欢样式1。

        12
  •  -2
  •   Khorkrak    16 年前

    第一个是典型的简单,懒惰和马虎的方式。数字2清晰地表达了逻辑。其他人指出的是,是的,它可能会变得麻烦。不过,这种趋势有一个重要的好处。样式#1可以隐藏您的函数可能做得太多。它并不能很好地从视觉上展示正在发生的事情的复杂性。也就是说,它可以防止代码对你说“嘿,这对于这个函数来说有点太复杂了”。这也使得其他不了解您的代码的开发人员更容易错过那些到处散播的返回,不管怎样,乍一看。

    推荐文章