应用程序中层之间的通信
-
22-09-2019 - |
题
假设我们在业务层中有以下方法。告诉UI层出现问题并给出错误消息的最佳实践是什么?该方法在确定时是否应该返回一个空字符串,否则错误消息,还是应该在包裹捕获的异常的捕获代码中抛出另一个异常?如果我们选择第二个变体,那么UI应该再次尝试,捕捉太多,也许可以捕捉。这是第一个变体的伪代码。
public String updateSomething()
{
try
{
//Begin transaction here
dataLayer.do1();
dataLayer.do2();
dataLayer.doN();
//Commit transaction code here
}
catch(Exception exc)
{
//Rollback transaction code here
return exc.message;
}
return "";
}
这是一个好习惯,还是我应该在捕获量中抛出另一个例外(那么方法将是无效的)?
解决方案
返回这样的字符串有点不寻常(但是没有 真实的 原因不太理由)。更常见的方法是:
返回布尔值,并具有一些方法来设置错误消息,要么通过记录它,设置一些全局“最后一个错误”值,要么将指向错误构造的指针传递到您更新的方法中;
有一个无效方法,该方法对故障产生异常,并在调用代码中处理(如您所建议)
我已经广泛看到上述两个。很难说哪个是“最好的”。尝试与您正在使用的语言和/或您正在使用的现有代码集/库的习语和约定保持一致。
其他提示
我喜欢从我的业务层将标准合同归还我的UI层。
看起来像这样:
public class ServiceOperationResult<T>
{
public bool Successful
{
get;
set;
}
public ServiceErrorType ErrorType
{
get;
set;
}
public string ErrorMessage
{
get;
set;
}
public T ReturnData
{
get;
set;
}
}
我使用仿制药,以便每个服务都可以定义其发送的内容,并且标准错误标志告诉客户端应用程序发生了哪种类型的错误(这些是元型,例如“内部错误”,“外部派对错误”,“业务”规则验证错误”),然后该应用程序可以以标准方式对这些错误类型进行反应。
例如,业务错误以红色错误标签显示,而内部错误将重定向到错误页面(在Web应用程序中)或关闭表单(在Windows应用中)
我的宠物讨厌是在网站上看到一个红色标签(我希望在其中看到验证错误),并看到类似“数据库服务器拒绝您的连接”之类的东西,这是您仅使用字符串来返回错误数据而运行的风险。
最好的方法是在一些更通用的类型中包装异常并重新恢复它。因此,更新()必须声明它可以抛出某种异常(例如:updateFaileDexception),在捕获块中,您应该包装异常。
public String updateSomething() {
try {
[...]
} catch ( SQLException e ) {
// rollback;
throw new UpdateFailedException(e);
}
}
但是捕捉抽象异常类型不是一个好主意。您应该只包裹那些您知道的语义。例如:sqlexception,dataAccessException(spring dao)等。
如果包装异常,则可以轻松包装NullPoInterException的InterruptedException。这可能会破坏您的申请。
最好的方法可能是拥有一个特定于层的自定义异常类,一旦您在特定层中捕获了异常,将自定义异常扔到了调用层,那么它将具有以下优势。
- 您将获得更好的模块化方法来处理异常。
- 当您的代码复杂性增加时,代码的维护将很容易
- 您将在异常方案中获得更多控制
例如,您在业务层中捕获异常,并想告知演示层
public string DummyFunction
{
try
{
}
catch(Exception ex)
{
throw new businessException();
}
}