当前位置: 首页 > 科技观察

阿里的最终面孔:优秀的代码是如何分层的?

时间:2023-03-22 14:48:07 科技观察

说到应用分层,大部分人会觉得这不是很简单,只有三层:Controller,Service,Mapper。图片来自Pexels。看似简单,但很多人并没有分工负责。在很多代码中,Controller做的逻辑比Service多,Service往往被认为是透传。其实很多人在开发代码的时候都没有注意到的地方,反正函数是可以用的,放在哪里都无所谓。这往往会导致后面的代码无法复用,层次关系混乱,后续代码的维护非常麻烦。的确,在这些人眼里,层叠只是一种形式。前辈们的代码都是这样写的,其他项目的代码也是这样写的,我就照着做。但是在真正的团队开发中,每个人的习惯都不一样,写出来的代码一定要有自己的标签。有些人习惯在Controller中写很多业务逻辑,有些人习惯在服务之间调用远程服务。这就导致了每个人完全不同的开发代码风格。等到后面其他人修改的时候,乍一看,我这个人写的代码和我平时的习惯完全不一样。修改的时候,我是按照自己以前的习惯改的,还是按照前人的。这又是一个艰难的选择。一旦选择有偏差,你的后辈维护你的代码的时候,怕是要被骂。因此,一个好的应用分层需要具备以下几点:便于后续代码维护。延伸层次的效果需要让整个团队接受每一层的责任边界。如下图所示:①开放接口层:可以直接封装Service方法,暴露为RPC接口;可以通过Web封装成http接口;可以进行网关安全控制、流量控制等。②终端展示层:各终端的模板渲染展示层。目前主要是velocity渲染、JS渲染、JSP渲染、移动端展示等。③Web层:主要是访问控制的转发,各种基础参数的验证,或者对不可重用服务的简单处理等。④服务层:相对具体的业务逻辑服务层。⑤管理者层:综合业务处理层。具有以下特点:一层封装第三方平台,对返回结果进行预处理,转换异常信息。Service层通用能力的下沉,比如缓存方案和中间件的通用处理。与DAO层交互,复用多个DAO的组合。⑥DAO层:数据访问层,与底层MySQL、Oracle、Hbase进行数据交互。Alibaba协议中的层比较清晰简单,但是描述的还是太简单了,很多同学还不清楚Service层和Manager层的关系,导致没有Manager层在很多项目中。存在。下面介绍在具体业务中如何实现分层。优化分层从我们的业务发展中总结出一个比较理想的模型。这里先说明一下,因为我们的RPC框架使用的是Thrift,所以可能比其他一些RPC框架比如Dubbo多了一层。功能层和控制器层是相似的。最顶层的Controller和TService是我们阿里巴巴分层规范的第一层:轻业务逻辑、参数校验、异常覆盖。通常这种接口很容易改变接口类型,所以业务逻辑一定要轻,甚至不做具体逻辑。①Service:业务层,复用性低。建议每个Controller方法必须对应一个Service。不要将业务编排放在Controller中。为什么?如果我们把业务编排放在Controller层,以后如果要访问Thrift,就需要在这里重新进行业务编排,这样就会导致我们每次访问一个入口层都要拷贝这段代码。如下图所示:如此大量的重复性工作肯定会导致我们的开发效率下降,所以我们需要将所有的业务编排逻辑都放到Service中:②Mannager:可复用逻辑层。这里的Manager可以是单个服务,比如我们的Cache、MQ等,当然也可以是复合的。当需要调用多个Mannager时,这个可以组合成一个Mannager,比如逻辑表连接查询等,如果是httpMannager或者rpcMannager,需要在这一层做一些数据转换。③DAO:数据库访问层。它主要负责“操作数据库中的某个表,并将其映射到某个Java对象”。DAO应该只允许自己的Service访问,其他Service必须通过对应的Service访问我的数据。层次领域模型的改造在阿里巴巴编码规范中列出了如下领域模型规范:DO(DataObject):与数据库表结构一一对应,通过DAO层向上传输数据源对象。DTO(DataTransferObject):数据传输对象,Service或Manager传出的对象。BO(BusinessObject):业务对象。封装Service层输出的业务逻辑的对象。AO(ApplicationObject):应用对象。Web层和Service层之间的抽象复用对象模型与表现层很接近,复用度不高。VO(ViewObject):显示层对象,通常是从Web传输到模板渲染引擎层的对象。Query:数据查询对象,每一层接收来自上层的查询请求。注意超过2个参数的查询封装禁止使用Map类传输。每一层基本上都有自己对应的领域模型,这就导致有些人过于追求每一层都使用自己的领域模型。这就导致一个对象在一次请求中可能会出现3次甚至4次转换,返回时也会发生3-4次转换,所以很可能一次完整的请求-返回会有多次对象转换。如果真的按照这种方式开发,恐怕不应该再写其他东西了,把这种重复无用的逻辑写一天算了。所以我们不得不采用一个折衷方案:让Service/Manager来操作数据域模型。对于这一层,我们原来做的工作是业务逻辑处理和数据组装。Controller/TService层的领域模型不允许传递给DAO层,不符合职责划分。同样,DAO层的数据也不允许传递给Controller/TService。小结总的来说,业务分层对代码规范更为重要,它决定了以后的代码是否可复用,职责是否清晰,边界是否清晰。当然,对于这种分层,不同的人有不同的看法,团队中每个人的分层习惯也不同,所以很难权衡一个标准的准则。一般来说,只要职责逻辑清晰,后续维护容易,就是很好的分层。最后,如果你的团队有更好的层次感,或者上面的描述有不对的地方,欢迎大家留言指正。作者:CafeLatte编辑:陶佳龙来源:转载自公众号CafeLatte(ID:close_3092860495)