关闭。这个问题是基于意见的。它目前不接受答案。
**想改进这个问题吗?**更新这个问题,这样就可以通过编辑这篇文章用事实和引文来回答。
上个月关门了。
改进这个问题
注意这个问题是基于观点的,所以我在这里用更实际的方法来回答
因此,正如标题所说,我不确定是应该尝试实现可恢复的错误类,还是继续尝试在 catch
阻止。
一些psuedo代码演示:
// 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
而不是运行相同的恢复代码)。这将允许我捕获可以恢复的异常,但仍然抛出不可恢复的异常,或者在无法恢复时抛出异常。
不过,我看到了一个问题:
当中间层 Runnable
从恢复调用不返回数据?假设我正在从服务器读取而不是写入,并获得一个可恢复的异常(如networkdrop)并成功恢复。由于执行是通过recover方法上的runnable恢复的,而且runnable不返回任何内容,那么调用read的函数如何从runnable中获取数据呢?
那么,这个系统会比 catch
是谁?或者仅仅抓住可恢复的异常所带来的可读性和简洁性是一把双刃剑?
如果权衡有利于可恢复类,我将如何解决从已恢复异常获取返回值的问题?
1条答案
按热度按时间bejyjqdl1#
异常意味着在调用堆栈上进行故障通信。抛出异常特别支持这样一个方面,即在某个嵌套调用失败后,调用方通常不想继续,而是在堆栈的更高层发出失败信号。
因此,在接收到异常后,调用方跳过其方法体的其余部分,并向其调用方发出失败信号,这种情况在所有调用堆栈中都会发生,直到找到一个具有适当
catch
阻止。瑕疵
你的
Recoverable
例外会破坏这个系统。如果我理解正确的话,恢复是一个双重过程:异常包含如何(例如)重新建立连接的代码,而runnable由catch块提供,负责修复由于异常而跳过的代码行。但是由于跳过的代码将来自多个嵌套调用层,我认为您不能可靠地提供有效的恢复代码。
当然,如果您准备在每一个软件层上用try/catch来包围每一行业务代码,这会变得更容易,但这与异常处理的精神相矛盾。
为了确立您的概念,您无论如何都需要确定可能发生可恢复故障的所有地方—您必须抛出
Recoverable
异常,通常 Package 一些原始的异常。这是另一种方法的关键。建议
我建议使用不同的方法:
在所有抛出可恢复异常的地方,都知道可以从失败中恢复。因此,我将在那里实现这些知识,而不是让方法失败,而是立即应用恢复策略,这样您就可以成功地返回。
如果您担心在恢复失败时浪费太多的尝试,请查看“断路器”模式。