阅读文本大约需要3分钟。
- 1、背景
- 2、如何分层?
- 2.1、阿里规范
- 2.2、优化分层
- 3、分层模型的转换
- 4、总结
说到应用分层,大多数人会认为这不是很简单 controller,service, 三层mapper。看似简单,其实很多人并没有把自己的职责分开。在很多代码中,controller做的逻辑比service多,service往往被视为传播。这其实是很多人开发代码时没有注意到的地方。反正功能也可以用。放在哪里没关系。这往往导致后代码无法重用,层次关系混乱,后续代码的维护非常麻烦。
的确,在这些人眼里,分层只是一种形式,前辈的代码是这样写的,其他项目的代码是这样写的,所以我也是这样写的。然而,在真正的团队开发中,每个人都有不同的习惯。编写的代码必须有自己的标签。有些人习惯于编写大量的业务逻辑,有些人习惯于在service之间呼叫远程服务,这导致每个人的开发代码风格完全不同。当其他人随后修改时,我看到这个人写的代码与我通常的习惯完全不同,这是一个困难的选择,无论你是按照你以前的习惯改变还是跟随你的前任。一旦选择有偏差,你的年轻一代就会维护你的代码,恐怕你会责骂。
因此,一个好的应用分层需要具备以下几点:
- 维护和扩展后续代码方便;
- 整个团队都需要接受分层效果;
- 各级职责边界清晰。
阿里编码规范中约束的分层如下:
开放式接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行 网关安全控制、流量控制等。
终端显示层:模板渲染和执行各端显示层。目前主要是 velocity 渲染,JS 渲染, JSP 渲染、移动终端显示等。
Web 层:主要转发访问控制,验证各种基本参数,或简单处理不再用的业务。
Service 层:相对具体的业务逻辑服务层。
Manager 层:一般业务处理层,具有以下特点:1. 对于第三方平台封装层,预处理返回结果和异常转换信息;2. 缓存方案、中间件通用处理等Service层通用能力下沉;3. 与DAO层交互,重用多个DAO的组合。
DAO 层:数据访问层和底层 MySQL、Oracle、Hbase 数据交互。
阿里巴巴规定中的分层相对清晰、简单、清晰,但描述仍然过于简单。此外,许多学生仍然不知道service层和manager层之间的关系,这导致许多项目中没有manager层。以下是如何在具体业务中实现分层。
2.2、优化分层从我们的业务发展中总结出一个理想的模型。在这里,我们应该首先解释一下,由于我们的RPC框架选择thrift,它可能比其他RPC框架多一层,如dubbo,其功能类似于controller层
上层controller和TService是我们阿里分层规范的第一层:轻业务逻辑、参数验证、异常底部。通常这个接口很容易更换接口类型,所以业务逻辑一定要轻,甚至不做具体的逻辑。
Service:业务层复用性低。建议每个controller方法都要对应一个service,不要把业务安排放在controller中。为什么?如果我们把业务安排放在controller层,如果我们将来想访问thrift,我们需要在这里再次安排业务,这将导致我们必须复制每个访问入口层的代码,如下图所示:
如此大量的重复工作必然会降低我们的发展效率,因此我们需要将业务安排逻辑放入service中:
Mannager:逻辑层可重复使用。这里的Mannager可以是单一的服务,如我们的cache、mq等,当然也可以是复合的,当你需要调用多个Manager时,这可以合并为Mannager,如逻辑连表查询等。如果是httpmannager或rpcmannager,则需要在这一层进行一些数据转换
DAO:数据库访问层。主要负责“操作数据库的表,映射到java对象”。dao应该只允许自己的Service访问,其他Service必须通过相应的Service访问我的数据。
3、分层模型的转换在阿里巴巴编码规则中列出了以下几个领域的模型规则:
- DO(Data Object):数据源对象通过DAO层向上传输,与数据库表结构一一对应。
- DTO(Data Transfer Object):Service或Manager向外传输数据传输对象。
- BO(Business Object):业务对象。包装业务逻辑的对象由Service层输出。
- AO(Application Object):应用对象。在Web层和Service层之间抽象的复用对象模型,非常接近显示层,复用度不高。
- VO(View Object):显示层对象通常是Web传输到模板渲染引擎层的对象。
- Query:数据查询对象,各层接收上层查询请求。注意查询包装超过2个参数,禁止使用Map类传输。
每个层基本上都有自己相应的领域模型,这导致一些人过于追求每个层都使用自己的领域模型,从而导致对象可能出现三次甚至四次转换在请求中,当返回也会出现3-4次转换时,所以可能有一个完整的请求——返回将出现多个对象转换。如果在开发中真的遵循这一点,恐怕就不要写别的了,一天就写这个重复无用的逻辑吧。
因此,我们必须采取一个妥协计划:
1、允许Service/Manager操作数据领域的模型。在这个层面上,我自己的工作也是业务逻辑处理和数据组装。
2、Controller/TService层的领域模型不允许进入DAO层,因此不符合职责划分。
3、同样,DAO层的数据也不允许传输到Controller/TService。
4、总结一般来说,业务分层对代码规范更为重要,这决定了未来的代码是否可以重用,责任是否明确,边界是否明确。
当然,这种分层其实是见仁见智的, 团队中的每个人都有不同的分层习惯,所以很难权衡一个标准标准。一般来说,只要职责逻辑清晰,后续维护容易,就是一个很好的分层。
最后,如果你的团队有更好的分层,或者上面描述的错误,请留言纠正。