Design patterns 模式:函数退出时做某事的优雅方式?
我有一个逻辑函数,如下所示:Design patterns 模式:函数退出时做某事的优雅方式?,design-patterns,language-agnostic,coding-style,Design Patterns,Language Agnostic,Coding Style,我有一个逻辑函数,如下所示: doStuff1() try: doStuff2() except type1: error1() return endstuff() except type2: error2() return endstuff() except: error3() return endstuff() if doStuff3(): error4() return endstuff() doStuff4()
doStuff1()
try:
doStuff2()
except type1:
error1()
return endstuff()
except type2:
error2()
return endstuff()
except:
error3()
return endstuff()
if doStuff3():
error4()
return endstuff()
doStuff4()
return endstuff()
正如您所看到的,
endstuff()
在函数的每个可能的出口上都完成。现在,endstuff()
实际上是两行代码,我最近不得不在所有可能的出口中添加第三行代码。有没有更优雅的方式来组织这段代码?我不能只使用finally
,因为抛出异常并不总是这样 即使没有抛出异常,也可以使用finally,而且这是实现所需操作的最优雅的方法。调用finally
块时不需要抛出异常。块的全部要点是它总是被可靠地调用。您可以使用它。无论是否引发异常,都将执行finally
子句,因此您可以将代码包装在try/catch/finally的多个级别中。。。(这是C#,因为您没有指定语言)
由于每次都会返回endstuff(),因此不必中断返回调用。无论发生什么情况,函数都将返回endstuff(),为什么每次检查都要使用该代码?除非您不想在出现错误时执行doStuff4()
更优雅的方法可能是在finally块中执行endstuff(),并将该值赋给一个变量,然后在末尾返回该变量。根据语言的不同,这是RAII的最佳候选。例如,在堆栈上分配一个对象,并在其析构函数中执行“endstuff()”;这样,它就会在作用域的末尾被调用
class something
def ~something()
darkside()
endstuff()
// in the function
def somefunc()
something s
doStuff1()
try:
doStuff2()
except type1:
error1()
return
except type2:
error2()
return
except:
error3()
return
if doStuff3():
error4()
return
doStuff4()
return
我赞成
最后
块,但作为替代方案,您可以在时使用块,例如:
while(true)
doStuff1()
try:
doStuff2()
except type1:
error1()
break
except type2:
error2()
break
except:
error3()
break
if doStuff3():
error4()
break
doStuff4()
end while
return endstuff()
如果您使用的语言不支持异常,这将非常有用。在这种情况下,除了类型外,您的将只是检查上次返回结果的错误值。关于'finally'子句的其他注释是正确的,但当我没有可用的'finally'子句时(并非所有语言都有),我将多出口代码分解为一个子函数。这不仅对try/catch很有用,而且对任何需要检查许多条件并希望避免深入嵌套的“if”子句的代码都很有用。此示例显示了以下两个方面:
ThingOne() {
var foo;
foo.open();
if (ThingTwo(foo))
ThingThree(foo);
foo.close();
}
ThingTwo(var x) {
try
{
...normal case...
return true
catch x1
handlex1();
catch x2
handlex2();
}
return false;
}
ThingThree(var x) {
if (x.conditionOne == false) return;
if (x.conditionTwo == true) return;
...etc...
x.GoForIt();
}
我知道,但这仍然会有3次重复——最后一次,如果一次,和函数末尾的一次。我能把这3个变成一个例子吗?如果endstuff()是5-6行代码,那么仍然需要大量重复。你是说我把所有的代码都打包在一个单独的try…finally块中吗?呵呵,我太傻了。你的意思是一个finally,不是作为我的“try”的一个补充,而是围绕整个代码。我还忘了,即使函数退出,最终也会被调用。
ThingOne() {
var foo;
foo.open();
if (ThingTwo(foo))
ThingThree(foo);
foo.close();
}
ThingTwo(var x) {
try
{
...normal case...
return true
catch x1
handlex1();
catch x2
handlex2();
}
return false;
}
ThingThree(var x) {
if (x.conditionOne == false) return;
if (x.conditionTwo == true) return;
...etc...
x.GoForIt();
}