抛出异常以控制流-代码有异味吗?
问题内容:
考虑以下代码(特别是Java):
public int doSomething()
{
doA();
try {
doB();
} catch (MyException e) {
return ERROR;
}
doC();
return SUCCESS;
}
其中doB()
定义为:
private void doB() throws MyException
基本上,MyException
仅在doB()
满足某些条件(不是灾难性的,但确实需要以某种方式提高条件)的情况下存在,这样doSomething()
才会知道会错误退出。
在这种情况下,您是否发现可以使用例外来控制流程?还是这是代码气味?如果是这样,您将如何重构呢?
问题答案:
这完全取决于错误条件是什么,以及方法的工作是什么。如果返回ERROR
是为调用函数处理该错误的有效方法,那为什么会出错呢?
但是,通常这 是 一种气味。考虑一下:
bool isDouble(string someString) {
try {
double d = Convert.ParseInt32(someString);
} catch(FormatException e) {
return false;
}
return true;
}
这是一个很大的代码异味,因为您不希望出现双重值。您只想知道字符串是否包含双精度型。
有时,您使用的框架没有其他方式来完成您想要的事情。对于上述情况,有更好的方法:
bool isDouble(string someString) {
bool success;
Convert.TryParseInt32(someString, ref success);
return success;
}
这类异常有一个特殊的名称,该名称是由我最近读过博客的人创造的,但可悲的是,我忘记了它的名字。如果您知道,请发表评论。最后但并非最不重要的一点是,上面是伪代码。我确定,我不是C#开发人员,因此上述内容无法编译,但是TryParseInt32
/
ParseInt32
我很好地证明了这一点,因此我将继续使用C#。
现在,到您的代码。让我们检查两个功能。一种闻起来,而另一种闻不到:
1.气味
public int setupSystem() {
doA();
try { doB(); }
catch (MyException e)
{ return ERROR; }
doC();
return SUCCESS;
}
那是 代码的味道 ,因为当您要设置系统时,您不希望它失败。无法设置系统意味着您无法继续处理该错误。
2.好
public int pingWorkstation() {
doA();
try { doB(); }
catch (MyException e)
{ return ERROR; }
doC();
return SUCCESS;
}
可以,因为该方法的目的是测试工作站是否仍然可以访问。如果不是,则这是该方法结果的一部分,而不是需要备用返回路径的特殊情况。