有关"保护声明"与"单一功能退出点"范例的可维护性的研究是否可用?

jba*_*all 10 language-agnostic paradigms

我想知道是否有任何关于使用"守卫声明"范式与"单一功能退出点"范例的项目的可维护性的研究(包括随意和强大)?

Guard语句示例(在C#中):

string GetSomeString()
{
    if(necessaryConditionFails) { return null; }
    if(!FunctionWithBoolReturn(someAttribute)) { return null; }
    //all necessary conditions have been met
    //do regular processing...
    return finalStringValue;
}
Run Code Online (Sandbox Code Playgroud)

单个函数退出点示例(在C#中):

string GetSomeString()
{
    string valueToReturn = null;
    if(necessaryConditionPasses && FunctionWithBoolReturn(someAttribute)) 
    { 
        //all necessary conditions have been met
        //do regular processing...
        valueToReturn = finalStringValue;
    }
    return valueToReturn;
}
Run Code Online (Sandbox Code Playgroud)

我知道两者的优点和缺点都在SO上无休止地争论,但我正在寻找对每种范例的可维护性的实际研究*.这可能是未知的,但我想如果信息在那里,SO上的某个人就会知道它在哪里.到目前为止,我的网络搜索还没有成功.

**我也知道许多程序员(包括我)在整个代码中使用这两个原则,具体取决于具体情况.我只是希望发现哪一个具有更高可维护性的可靠记录,可以作为首选范例使用.*

Pat*_*ick 10

强迫单个退出点有一些问题.

第一个是它可能导致复杂的结构.映像一个函数,您必须在其中打开文件,读取一行,将行转换为数字并返回该数字,如果出错则返回零.使用单个出口点,最终会使用大量嵌套if(如果文件存在打开它,如果打开成功读取行,如果读取成功将值转换为整数),这将使您的代码不可读.其中一些可以通过在函数末尾添加标签并使用goto来解决(我们过去必须使用它,因为我们还使用了单个出口点和首选可读性)但它并不理想.

其次,如果您使用例外,如果您想再次使用单个退出点,则必须抓住所有内容.

所以,就个人而言,我更喜欢在函数的开头和执行期间进行大量的检查(和断言),并在出现问题时首先退出函数.

  • +1"单一退出点"的拥护者似乎很少意识到每个可以抛出异常的地方都是潜在的退出点.推荐的起源似乎来​​自于析构函数,auto_ptr,垃圾收集之前的糟糕时期,以及"最终"使得确保代码自行清理变得容易得多. (13认同)
  • 我认为开放文件阅读器正是人们想要做一个退出点的场景:在文件的顶部你定义一个变量来保存返回值,然后你有许多嵌套块.最外层的是打开文件.如果打开失败,则将状态代码设置为返回值,否则使用打开的文件,最后关闭文件并释放内存.由于通过块的每个路径都将触及关闭文件代码,因此确保没有泄漏(相反,必须在每个出口点释放资源并冒泄漏风险). (2认同)
  • Martin Fowler 的 [Guard Clauses](http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html) 是一个很好的经验法则,我这适用于在代码的第一行抛出异常。 (2认同)
  • 与支持子例程调用的语言之前常见的宽松方法相比,还值得注意“单一退出点”的真正含义。在支持函数调用的语言中,除非程序员使用类似 setjmp/longjmp 的东西,否则调用“foo”的退出点将是*紧随调用之后的代码*。每个函数调用应该返回到调用后的位置的概念可能看起来很明显,不需要提及,但是...... (2认同)