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();
}