我一直听说单个退出点功能是一种糟糕的代码方式,因为你失去了可读性和效率.我从来没有听到任何人争辩对方.
我认为这与CS有关,但这个问题在cstheory stackexchange中被击落.
Jas*_*ams 106
有不同的思想流派,主要归结为个人偏好.
一个是如果只有一个出口点就不那么容易混淆了 - 你有一条通过这个方法的路径,你知道在哪里寻找出口.如果你使用缩进来表示嵌套,那么你的代码会在右侧大量缩进,并且跟随所有嵌套作用域变得非常困难.
另一个是您可以检查前提条件并在方法开始时提前退出,这样您就可以在方法体中知道某些条件为真,而不会使方法的整个主体向右缩进5英里.这通常可以最大限度地减少您需要担心的范围数量,从而使代码更容易理解.
第三是您可以随意退出.在过去,这曾经更加令人困惑,但现在我们有语法着色编辑器和编译器来检测无法访问的代码,因此处理起来要容易得多.
我正好在中间营地.执行单个退出点是一种毫无意义甚至适得其反的限制恕我直言,而随机退出一个方法有时会导致混乱难以遵循逻辑,在那里很难看出给定的代码是否会或将不会执行.但是"选通"你的方法可以显着简化方法的主体.
sup*_*cat 37
我的一般建议是,在可行的情况下,返回语句应位于具有任何副作用的第一个代码之前,或者位于具有任何副作用的最后一个代码之后.我会考虑这样的事情:
if (!argument) // Check if non-null return ERR_NULL_ARGUMENT; ... process non-null argument if (ok) return 0; else return ERR_NOT_OK;
比:更清楚:
int return_value; if (argument) // Non-null { .. process non-null argument .. set result appropriately } else result = ERR_NULL_ARGUMENT; return result;
如果某个条件应该阻止函数做任何事情,我宁愿在函数执行任何操作的点之上的某个位置提前返回函数.然而,一旦该功能采取了具有副作用的行动,我宁愿从底部返回,以明确必须处理所有副作用.
PSS*_*PSS 14
单个入口和出口点是结构化编程的原始概念与逐步的Spaghetti Coding.有一种观点认为,多个退出点函数需要更多代码,因为您必须正确清理为变量分配的内存空间.考虑一个场景,其中函数分配变量(资源)并且尽早退出函数并且没有适当的清理会导致资源泄漏.此外,在每次退出之前构建清理会产生大量冗余代码.
ssc*_*der 13
对于大多数事情,它都归结为可交付成果的需求.在"过去的日子"中,带有多个返回点的意大利面条代码会引起内存泄漏,因为喜欢该方法的编码器通常不能很好地清理.在从嵌套范围返回的情况下,当返回期间弹出堆栈时,某些编译器还"丢失"对返回变量的引用也存在问题.更普遍的问题是重入代码,它试图使函数的调用状态与其返回状态完全相同.oop的变种人违反了这一点,这个概念被搁置了.
有可交付成果,尤其是内核,需要多个出口点提供的速度.这些环境通常具有自己的内存和进程管理,因此泄漏的风险最小化.
就个人而言,我喜欢单点退出,因为我经常使用它在return语句中插入断点并执行代码检查代码如何确定该解决方案.我可以进入入口并逐步完成,我使用广泛的嵌套和递归解决方案.作为代码审阅者,函数中的多个返回需要更深入的分析 - 所以如果你这样做是为了加快实现,那么你就是在抢劫彼得以拯救保罗.代码审查需要更多时间,使有效实施的假设无效.
- 2美分
有关详细信息,请参阅此文档:NISTIR 5459
小智 6
我曾经是单出口风格的倡导者。我的推理主要来自痛苦......
单出口更容易调试。
考虑到我们今天拥有的技术和工具,这是一个不太合理的位置,因为单元测试和日志记录可以使单退出变得不必要。也就是说,当您需要在调试器中观察代码执行时,理解和处理包含多个退出点的代码要困难得多。
当您需要插入赋值以检查状态(在现代调试器中替换为监视表达式)时,这一点尤其正确。以隐藏问题或完全中断执行的方式更改控制流也太容易了。
单出口方法更容易在调试器中逐步执行,并且更容易在不破坏逻辑的情况下梳理。