【博客分享】新来个技术总监,给公司项目引入了全新的业务架构,堪称最佳实践!

您所在的位置:网站首页 济南遥墙机场到客运站多远啊 【博客分享】新来个技术总监,给公司项目引入了全新的业务架构,堪称最佳实践!

【博客分享】新来个技术总监,给公司项目引入了全新的业务架构,堪称最佳实践!

2022-11-27 18:21| 来源: 网络整理| 查看: 265

本文开始前,问大家一个问题,你觉得一份业务代码,尤其是互联网业务代码,都有哪些特点?

我能想到的有这几点:

互联网业务迭代快,工期紧,导致代码结构混乱,几乎没有代码注释和文档。 互联网人员变动频繁,很容易接手别人的老项目,新人根本没时间吃透代码结构,紧迫的工期又只能让屎山越堆越大。 多人一起开发,每个人的编码习惯不同,工具类代码各用个的,业务命名也经常冲突,影响效率。 大部分团队几乎没有时间做代码重构,任由代码腐烂。

每当我们新启动一个代码仓库,都是信心满满,结构整洁。但是时间越往后,代码就变得腐败不堪,技术债务越来越庞大。

这种情况有解决方案吗?也是有的:

小组内定期做代码重构,解决技术债务。 组内设计完善的应用架构,让代码的腐烂来得慢一些。 (当然很难做到完全不腐烂) 设计尽量简单,让不同层级的开发都能快速看懂并上手开发,而不是在一堆复杂的没人看懂的代码上堆更多的屎山。

而COLA,我们今天的主角,就是为了提供一个可落地的业务代码结构规范,让你的代码腐烂的尽可能慢一些,让团队的开发效率尽可能快一些。

COLA是什么

COLA是由阿里大佬张建飞所提出的一种业务代码架构的最佳实践,并且已经在阿里云脚手架代码生成器中作为一个可选项,可见其已经拥有了一定影响力。

图片

COLA 是 Clean Object-Oriented and Layered Architecture的缩写,代表“整洁面向对象分层架构”。

在COLA 4.0,也就是目前最新的版本中,作者将COLA拆分为COLA架构(Archetype)和COLA组件(Components)两个部分:

COLA架构:COLA应用的代码模板。 COLA组件:提供一些非常有用的通用组件,这些组件可以帮助我们提升研发效率。

两者互不干扰,可以独立使用。

COLA整体架构

首先主要谈谈COLA架构,COLA的官方博文中是这么介绍的:

在平时我们的业务开发中,大部分的系统都需要:

接收request,响应response; 做业务逻辑处理,像校验参数,状态流转,业务计算等等; 和外部系统有联动,像数据库,微服务,搜索引擎等;

正是有这样的共性存在,才会有很多普适的架构思想出现,比如分层架构、六边形架构、洋葱圈架构、整洁架构(Clean Architecture)、DDD架构等等。

这些应用架构思想虽然很好,但我们很多同学还是“不讲Co德,明白了很多道理,可还是过不好这一生”。问题就在于缺乏实践和指导。COLA的意义就在于,他不仅是思想,还提供了可落地的实践。应该是为数不多的应用架构层面的开源软件。

COLA提供了一整套代码架构,拿来即用。  其中包含了很多架构设计思想,包括讨论度很高的领域驱动设计DDD等。

注意:每个人对于架构设计都有着自己的理解。所以对于COLA的架构,本篇文章也仅仅只是我自己对于COLA的粗浅理解,大家可以批判看待。

COLA分层架构

先来看两张官方介绍图

图片

图片

其次,还有一个官方的表格,介绍了COLA中每个层的命名和含义:

层次包名功能必选Adapter层web处理页面请求的Controller否Adapter层wireless处理无线端的适配否Adapter层wap处理wap端的适配否App层executor处理request,包括command和query是App层consumer处理外部message否App层scheduler处理定时任务否Domain层model领域模型否Domain层ability领域能力,包括DomainService否Domain层gateway领域网关,解耦利器是Infra层gatewayimpl网关实现是Infra层mapperibatis数据库映射否Infra层config配置信息否Client SDKapi服务对外透出的API是Client SDKdto服务对外的DTO是

这两张图和一个表格已经把整个COLA架构的绝大部分内容展现给了大家,但是一下子这么多信息量可能很难消化。

既然整个示例架构项目是一个Maven父子结构,那我们就从父模块一个个好好过一遍。

首先父模块的pom.xml包含了如下子模块:

  demo-web-client   demo-web-adapter   demo-web-app   demo-web-domain   demo-web-infrastructure   start 复制代码 start层

该模块作为整个应用的启动模块(通常是一个SpringBoot应用),只承担启动项目和全局相关配置项的存放职责。代码目录如下:

图片

将启动独立出来,好处是清晰简洁,也能让新人一眼就看出如何运行项目,以及项目的一些基础依赖。

adapter层

接下来我们按照之前架构图从上到下的顺序,一个个看。

首先是demo-web-adapter模块,这名字是不是很新鲜?但其实,可以理解为平时我们用的controller层(对于Web应用来说),换汤不换药。

在COLA官方博客中,也能找到如下的描述:

Controller这个名字主要是来自于MVC,因为是MVC,所以自带了Web应用的烙印。然而,随着mobile的兴起,现在很少有应用仅仅只支持Web端,通常的标配是Web,Mobile,WAP三端都要支持。

图片

cilent层

有了我们说的“controller”层,接下来有的小伙伴肯定就会想,是不是service层啦。

是,也不是。

传统的Web应用中,完全可以只有一个service层给controller层调用,但是作为一个业务应用,除非你真的只是个前端页面的无情吐数据机器,否则很大可能性你的应用会有很多其他上下游调用方,并且你需要提供接口给他们。

这时候你给他们的不应该是一个Web接口,应该是RPC调用的服务层接口,至于原因不是本文的重点,具体就不展开了。

所以在COLA中,你的adapter层,调用了client层,client层中就是你服务接口的定义。

图片

从上图中可以看到,client包里有:

api文件夹:存放服务接口定义 dto文件夹:存放传输实体

注意,这里只是服务接口定义,而不是服务层的具体实现,所以在adapter层中,调用的其实是client层的接口:

@RestController public class CustomerController {     @Autowired     private CustomerServiceI customerService;     @GetMapping(value = "/customer")     public MultiResponse listCustomerByName(@RequestParam(required = false) String name){         CustomerListByNameQry customerListByNameQry = new CustomerListByNameQry();         customerListByNameQry.setName(name);         return customerService.listByName(customerListByNameQry);     } } 复制代码

而最终接口的具体实现逻辑放到了app层。

@Service @CatchAndLog public class CustomerServiceImpl implements CustomerServiceI {     @Resource     private CustomerListByNameQryExe customerListByNameQryExe;     @Override     public MultiResponse listByName(CustomerListByNameQry customerListByNameQry) {         return customerListByNameQryExe.execute(customerListByNameQry);     } } 复制代码 app层

接着上面说的,我们的app模块作为服务的实现,存放了各个业务的实现类,并且严格按照业务分包,这里划重点,是先按照业务分包,再按照功能分包的,为何要这么做,文章后面还会多说两句,先看图:

图片

customer和order分别对应了消费着和订单两个业务子领域。里面是COLA定义app层下面三种功能:

App层executor处理request,包括command和query是App层consumer处理外部message否App层scheduler处理定时任务否

可以看到,消息队列的消费者和定时任务,这类平时我们业务开发经常会遇到的场景,也放在app层。

domain层

接下来便是domain,也就是领域层,先看一下领域层整体结构:

图片

可以看到,首先是按照不同的领域(customer和order)分包,里面则是三种主要的文件类型:

领域实体:实体模型可以是充血模型(请自行了解),例如官方示例里的Customer.java如下: @Data @Entity public class Customer{     private String customerId;     private String memberId;     private String globalId;     private long registeredCapital;     private String companyName;     private SourceType sourceType;     private CompanyType companyType;     public Customer() {     }     public boolean isBigCompany() {         return registeredCapital > 10000000; //注册资金大于1000万的是大企业     }     public boolean isSME() {         return registeredCapital > 10000 && registeredCapital 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3