创建可恢复的错误接口比处理"catch"中的恢复更有效 [英] Would creating a recoverable error interface be more effecient than handling recovery in 'catch'

查看:54
本文介绍了创建可恢复的错误接口比处理"catch"中的恢复更有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:该问题由于基于意见而被关闭,因此我以更加实际的方法

Note This question was closed as being opinion based, so I re-asked with a more factual approach here

因此,正如标题所述,我不确定我应该尝试实现可恢复的错误类,还是只是坚持尝试在 catch 块中进行恢复.

So, as the title says, I'm unsure if I should try to implement recoverable error classes or just stick with trying to recover in a catch block.

一些伪代码来演示:

// more or less what I have now
postToServer(data) {
    try {
        socket.write(data)
    }
    //Interrupted being a custom exception
    catch(Interrupted ex) {
        //happened twice is a common static method on all custom exceptions that returns a boolean indicating if the last thrown error is the same as this one
        if(Interrupted.happenedTwice(ex)) throw ex;
        else postToServer(data);
    } 
    //another custom exception indicating that the network is unreachable
    catch(NetworkDrop ex) {
        if(!NetworkDrop.happenedTwice(ex) && !reconnectToServer()) throw ex;
        else postToServer(data);
    }
}
//What I would like to implement
interface Recoverable {
    public void recover(Runnable) throws Exception;
}
class NetworkDrop extends Exception implements Recoverable {
    ...
    public void recover(Runnable resume) {
        if(!NetworkDrop.happenedTwice(this) && reconnectToServer()) resume.run();
        else throw this;
    } 
}
class Interrupted extends Exception implements Recoverable {
    ...
    public void recover(Runnable resume) {
        if(!Interrupted.happenedTwice(this)) resume.run();
        else throw this;
    }     
}
postToServer(data) throws Exception {
    try {
        socket.write(data)
    }
    catch(Recoverable ex) {
        ex.recover(() -> postToServer(data));
    }
}

作为示例,我想将所有恢复代码都包含在异常中(减少重复代码,因为现在说5种不同的方法可以只调用 recover 而不是运行相同的恢复代码).这将允许我捕获可以恢复的异常,但是仍然抛出不可恢复的异常,或者如果无法完成恢复则抛出该异常.

As the example, I'd like to have all the recovery code in the exception (reduces duplicate code, as now say 5 different methods can just call recover instead of running the same recovery code). This would allow me to catch exceptions that can be recovered, but still throw unrecoverable ones, or throw if recovery can't be done.

虽然我看到了一个问题:

I see an issue with this though:

当从恢复调用的中间 Runnable 不返回数据时,如何在期望返回数据的方法内恢复?假设说我是从服务器读取而不是从服务器读取,并得到可恢复的异常(例如NetworkDrop)并成功恢复.由于执行是通过Runnable的restore方法恢复的,并且Runnable不返回任何内容,所以调用read的函数如何从Runnable中获取数据?

How would I recover inside a method that is expected to return data, when the intermediate Runnable called from recovery doesn't return data? Say hypothetically I'm reading from the server instead of writing, and get a recoverable exception (such as NetworkDrop) and successfully recover. Since execution is resumed through the Runnable on the recover method, and Runnable doesn't return anything, so how would the function that called the read get the data out of the Runnable?

那么,该系统是否比多个 catch 的效率更高?还是仅从捕获可恢复异常中获得的可读性和简单性就是一把双刃剑?

So, would this system be more efficient that multiple catch's? Or is the readability and simplicity I get from only catching recoverable exceptions a double edged sword?

如果权衡利于Recoverable类,我该如何解决从已恢复的异常中获取返回值的问题?

And if the tradeoff favors Recoverable classes, how would I address the issue of getting a return value from a recovered exception?

推荐答案

异常是为了在调用堆栈上传递故障.引发异常特别支持以下方面:在某些嵌套调用中失败之后,调用者通常不希望继续,而是在堆栈中进一步发出失败的信号.

Exceptions are meant to communicate failure up the call stack. Throwing an exception especially supports the aspect that, after a failure in some nested call, the caller typically doesn't want to continue, but signal its failure further up the stack.

因此,在收到异常之后,您的调用方将跳过其方法主体的其余部分,并向其调用方发出失败信号,这会在所有调用堆栈中发生,直到您使用适当的 catch 阻止.

So, after receiving an exception, your caller skips the rest of its method body, and signals failure to its caller, and this happens up all the call stack until you hit a place with an appropriate catch block.

您的 Recoverable 异常将破坏该系统.如果我理解正确,恢复是一个双重过程:异常包含如何进行编码的代码.重新建立连接,并且catch块提供了Runnable,由于异常,跳过了修复代码行的责任.

Your Recoverable exceptions will break that system. If I understand correctly, recovery is a two-fold process: the exception contains the code how to e.g. re-establish a connection, and the Runnable is provided by the catch block, with the responsibility to repair the code lines skipped because of the exception.

但是由于跳过的代码将来自多个嵌套的调用层,所以我认为您不能可靠地提供有效的恢复代码.

But as the code skipped will come from multiple nested call layers, I don't think you can reliably provide valid recovery code.

如果您准备好在每个软件层上用try/catch包围每一行业务代码,那么这样做当然会更容易,但这与异常处理的精神背道而驰.

Of course this can be made easier if you are ready to surround each and every line of business code with try/catch, on each and every software layer, but this contradicts the spirit of exception handling.

要确立您的概念,无论如何,您都需要确定可能发生可恢复故障的所有位置-您必须抛出 Recoverable 异常,通常包装一些原始异常.这是采用另一种方法的关键.

To establish your concept, you anyway need to identify all the places where a recoverable failure might happen - you have to throw Recoverable exceptions, typically wrapping some original one. And this is the key to a different approach.

我建议使用其他方法:

在所有引发可恢复异常的地方,您都知道可以从故障中恢复.因此,我会在那个地方实现这些知识,而不是使方法失败,而是立即应用恢复策略,这样您就可以成功返回.

In all the places where you'd throw recoverable exceptions, you know that you can recover from the failure. So, I'd implement that knowledge in that place, and instead of having the method fail, immediately apply the recovery strategy, so you can return successfully.

如果您担心如果恢复失败会浪费过多的尝试,请查看断路器".模式.

If you're worried about wasting too many attempts if recovery fails, have a look at the "circuit breaker" pattern.

这篇关于创建可恢复的错误接口比处理"catch"中的恢复更有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆