我一直都听说过单个出口点函数是一种不好的编码方式,因为这样会降低可读性和效率。我从未听说过有人在争论另一面。
我认为这与CS有关,但是这个问题在cstheory stackexchange上被否决了。
我一直都听说过单个出口点函数是一种不好的编码方式,因为这样会降低可读性和效率。我从未听说过有人在争论另一面。
我认为这与CS有关,但是这个问题在cstheory stackexchange上被否决了。
Answers:
有不同的思想流派,很大程度上取决于个人喜好。
一个是如果只有一个出口点,那么它就不会那么混乱-您在方法中只有一条路径,并且知道在哪里寻找出口。在不利的一面,如果您使用缩进来表示嵌套,则您的代码最终将大量缩进到右侧,并且很难遵循所有嵌套的作用域。
另一个是您可以检查先决条件并在方法开始时提早退出,这样您就可以在方法主体中知道某些条件是正确的,而整个方法主体都不会向右缩进5英里。通常,这可以最大程度地减少您需要担心的作用域数量,从而使代码易于遵循。
第三个是您可以随心所欲地退出。在过去,这曾经更加令人困惑,但是现在我们有了语法着色的编辑器和编译器可以检测无法访问的代码,因此处理起来要容易得多。
我正好在中间营地。强制单个出口点是毫无意义甚至适得其反的限制,恕我直言,尽管整个方法中的随机出口有时会导致混乱而难以遵循的逻辑,在逻辑上很难确定给定的代码是否会被执行。但是“控制”您的方法可以显着简化方法的主体。
singe exit
通过执行go to
语句,可以避免范例中的深层嵌套。另外,有机会在函数的本地Error
标签下执行某些后处理,而对于多个return
s 是不可能的。
我的一般建议是,在可行的情况下,return语句应位于具有任何副作用的第一个代码之前,或位于具有任何副作用的最后一个代码之后。我会考虑类似:
if(!argument)//检查是否为非null 返回ERR_NULL_ARGUMENT; ...处理非空参数 如果(确定) 返回0; 其他 返回ERR_NOT_OK;
比:
int return_value; if(argument)//非null { ..处理非空参数 ..适当设置结果 } 其他 结果= ERR_NULL_ARGUMENT; 返回结果;
如果某个条件应阻止某个功能执行任何操作,则我更喜欢在该功能可以执行任何操作的位置上方的某个位置提前退出该功能。但是,一旦函数执行了带有副作用的操作,我更愿意从底层开始,以明确必须处理所有的副作用。
ok
变量,对我来说就像是单向返回方法。此外,if-else块可以简单地重写为:return ok ? 0 : ERR_NOT_OK;
return
在执行所有操作的所有代码之前都有一个开头。至于使用?:
运算符,将其写在单独的行上使许多IDE可以更轻松地将调试断点附加到不正常的情况。顺便说一句,“单个出口点” 的真正关键在于理解重要的是,对于每个对正常函数的特定调用,出口点是紧接在调用之后的点。如今的程序员认为这是理所当然的,但事情并非总是如此。在某些极少数情况下,代码可能必须没有堆栈空间才能通过,从而导致函数...
单一入口和出口点是结构化编程与分步Spaghetti编码的原始概念。人们认为,多个出口点函数需要更多代码,因为您必须适当清理分配给变量的内存空间。考虑一种情况,其中函数分配变量(资源),并且过早地退出该函数并且没有适当的清理会导致资源泄漏。另外,在每个出口之前构造清理将创建大量冗余代码。
对于大多数事情,这取决于交付成果的需求。在“过去”中,带有多个返回点的意大利面条式代码会导致内存泄漏,因为偏爱该方法的编码人员通常无法很好地清理代码。在从嵌套作用域返回的情况下,当在返回过程中弹出堆栈时,某些编译器也会“丢失”对返回变量的引用,这也存在问题。更普遍的问题是可重入代码之一,该代码试图使函数的调用状态与其返回状态完全相同。oop的更改者违反了此规定,因此该概念被搁置了。
有可交付成果,最著名的是内核,它们需要多个出口点提供的速度。这些环境通常具有自己的内存和流程管理,因此将泄漏的风险降到最低。
就个人而言,我喜欢有一个退出点,因为我经常使用它在return语句上插入一个断点,并对代码如何确定该解决方案进行代码检查。我可以直接进入入口并逐步进行,这与大量嵌套和递归的解决方案有关。作为代码审阅者,一个函数的多次返回需要更深入的分析-因此,如果这样做是为了加快实现速度,那么您就在抢Peter救了Paul。代码审查将需要更多时间,从而使有效实现的假设无效。
-2美分
请参阅此文档以获取更多详细信息:NISTIR 5459
multiple returns in a function requires a much deeper analysis
仅当功能已经非常强大(> 1个屏幕)时,否则它使分析变得更容易
答案是非常依赖于上下文的。如果要制作GUI并具有初始化API并在主程序开始处打开窗口的功能,则将充满可能会引发错误的调用,每个调用都会导致程序实例关闭。如果您使用嵌套的IF语句并缩进,则代码可能很快会向右歪斜。在每个阶段都返回一个错误可能会更好,并且实际上更具可读性,同时使用代码中的几个标志进行调试也很容易。
但是,如果您要测试不同的条件并根据方法中的结果返回不同的值,则最好使用单个出口点。我曾经在MATLAB中处理图像处理脚本,但可能会变得非常庞大。多个出口点可能会使代码极难遵循。Switch语句更合适。
最好的办法就是随手学习。如果您正在编写代码,请尝试查找其他人的代码并查看他们如何实现。确定您喜欢哪些位,不喜欢哪些位。
如果您觉得一个函数中需要多个出口点,则该函数太大且作用太大。
我建议阅读罗伯特·C·马丁(Robert C. Martin)的书《清洁代码》中有关函数的章节。
本质上,您应该尝试使用4行或更少的代码编写函数。
Mike Long博客的一些注释: