服务层的必要性

时间:2023-01-11 21:32:06

捕获异常

调试某个项目,搭建好环境,打开首页,然后是一个大黄页(500),错误信息是NullReferenceException。然后Debug了一下代码,原来数据库连接字符串错误,作者在DBHelper中捕获了异常,这样DBHelper里的方法的返回值就是一个null。对于这样的try...catch...我也是醉了,我表达的意思在这种情况下,不捕获异常要比捕获异常好很多。捕获了异常引发了其他的错误,更浪费开发人员的时间。我敢肯定我绝对不是第一个被这样的代码坑的,也不会是最后一个。
既然在DBHelper捕获异常不正确,那么应该在哪里捕获异常呢?我的建议是统一捕获,数据访问层不适合捕获异常,因为数据访问层的定位是专注于数据访问,业务逻辑层亦不适合捕获异常,因为业务逻辑层专注于领域逻辑和应用逻辑的处理。数据访问层和业务逻辑层只要专注于能够正确的执行就好。 这个时候就需要在业务逻辑层之上再搭建一层,这层就是服务层,如图

服务层的必要性

(图片来源 http://www.cnblogs.com/DotCpp/p/4291113.html)

将捕获异常和处理错误的代码放在服务层中。

并不是所有抛出的异常都在service中去捕获,主要还是看异常场景,

  1. 异常已经造成了当前执行流程的阻断就需要在service层捕获。
  2. 异常引发流程控制,并不需要阻断当前流程。举个例子先请求A,若A异常了,则在请求B。这样的情况就可以在当前代码捕获异常。

.NET异常模型,对于开发者是友好的,但是对于用户来说并不友好,比如出现了异常,就展现一个大黄页,用户会不知所措。用户希望看到的是友好的提示信息,而不是错误编码和堆栈信息。这个时候我们就需要对错误模型转换,由Exception转化为错误编码。在UI层通过错误编码以合理的方式将信息展现给用户。

业务逻辑协调

对于交易这种复杂的业务流程来说,完成这样的一个流程需要若干个子业务流程协同完成。举个例子,假设最初买一件衣服需要两个流程

  1. 将钱充值账户,写充值记录;
  2. 使用账号购买衣服,写消费记录;

这两个流程是分别进行的,即向买件衣服之前必须向账号内充值。有一天,PM意识到这个事情对用户太不友好了,所以就需要这两个流程一气呵成,但是想一气呵成需要解决一系列的问题,如充值流程不成功、衣服下架,需要退款。这就出现了很多协调这两个流程的业务逻辑,甚至会衍生出新的业务逻辑比如退款。那么协调这部分业务逻辑的代码应该放哪儿? 放UI层不合理的,因为UI层主要负责表现业务逻辑处理,用户参数校验等。所以我们需要新添加一个层,这个层就是业务外观层,来做业务流程协调。