COLA 是 Clean Object-Oriented and Layered Architecture的缩写,代表“整洁面向对象分层架构”。由阿里大佬张建飞所提出的一种基于DDD和代码整洁理论所诞生的实践理论框架,详细内容可阅读《程序员的底层思维》和相关git代码去了解
项目地址:GitHub - alibaba/COLA: 🥤 COLA: Clean Object-oriented & Layered Architecture
框架整体结构
面把COLA框架的主要架构梳理一下,这里的框架图采用COLA4.0版本(当前作者认为的最优形态)
COLA整体上由两部分组成,代码架构和通用组件,两者并非强绑定,代码架构是一套基于maven的代码模板,通用组件则是可选项,可以理解为Common组件包。
Adapter层(适配层)
负责对前端展示(Web、Wireless、WAP)的路由和适配。对于传统B/S系统而言,Adapter层就相当于MVC中的Controller。
App层(应用层)
主要负责获取输入、组装上下文、参数校验、调用领域层做业务处理,以及发送消息通知(如有需要)等。层次是开放的,应用层也可以绕过领域层,直接访问基础设施层。
Domain层(领域层)
用于封装核心业务逻辑,并利用领域服务(Domain Service)和领域对象(Domain Entity)的方法对App层提供业务实体和业务逻辑计算。领域层是应用的核心,不依赖任何其他层次。
Infrastructure层(基础设施层)
主要负责技术细节问题的处理,比如数据库的CRUD、搜索引擎、文件系统、分布式服务的RPC等。此外,Infrastructure层还肩负着领域防腐的重任,外部依赖需要通过Gateway的转义处理,才能被App层和Domain层使用。
Commpont(外挂Cola扩展组件)
非业务相关的功能组件包
对象类型概念统一
使用COLA,首先就是要明确各类对象的概念以及所处位置,统一认知并且严格执行。
DO(Data Object):数据对象
DO应该跟其名字一样,仅作为数据库中表的1:1映射,不参与到业务逻辑操作中,仅仅负责Infrastructure层的数据持久化以及读取的实体对象
Entity:实体对象
对应业务模型中的业务对象,字段及方法应该与业务语言抱持一致,原则上Entity和Do应该是包含嵌套的关系,且Entity的生命周期仅存在在系统的内存中,不需要序列化以及持久化,业务流程结束,Entity也应该跟随消亡
DTO(Data Transfer Object): 数据传输对象
主要作为和系统外部交互的对象,DTO主要是数据传输的载体,期间可以承载一部分领域能力(业务相关的判定职责等);
VO(view Object):展示层对象
性质和DTO相差不多,也是数据传输载体,主要是作为对外交付数据的载体,承载部分数据隐藏、数据保护、数据结构化展示的作用。
代码组织结构及层次间关系
Cola本身是以一个maven Archetypes模板,基于该模板进行项目搭建,细看模板结构能发现COLA整体采用maven module的结构来构建代码,划分原则是结合技术维度和领域维度综合划分:
相应的分层则对应到不同的module中(技术维度划分),每一层对应一个maven的module
<modules>
<module>eden-demo-cola-adapter</module>
<module>eden-demo-cola-app</module>
<module>eden-demo-cola-domain</module>
<module>eden-demo-cola-infrastructure</module>
<module>start</module>
</modules>
模板生成后的代码结构如下:
然后就是关于每个module的代码目录划分原则(基于领域维度进行划分),即每个module中对应的概念都划分到具体某一功能领域包中:
而每个module(层)之间的依赖关系如下图:
Comm本身作为公共内容被所有module依赖,Adapter作为系统唯一外部输出仅依赖APP,App本身除了依赖领域层外还因为CQRS相关内容依赖Infras;Domain层巧妙地使用依赖倒置让Infras层反向依赖它,以保证了Domain的独立和完整。整体是按照技术维度进行划分的。
其中Domian层中的gateway仅仅定义interface,而在infrast层中进行gateway的Impl类,由此完成了巧妙地依赖倒置(大佬在书中提到的防腐层概念,也是DDD设计思想中的存储库概念的实践),解耦了Domain,让Domain地module作为一个内聚的个体,聚焦核心业务开发,并且此处的设计,gateway作为与Infras层的防腐层,很灵活的将业务和数据进行隔开。
框架运行逻辑
场景1(包含业务诉求):
由客户端发起请求,首先Adapter层接收请求,进行相关的校验后进行数据封装(Coverter操作:由请求参数封装为App层所需要的DTO结构),根据预设的逻辑去调用App的内容;DTO数据进入App后, App根据业务诉求,然后调用Domain的ability和module进行业务组装(Converter操作:将DTO转换为Entity对象);被调用的Domian在进行业务处理过程中调用Infras层去进行相关持久化和查询;Infras在被Domain调用时,需要把传入的Entity转换为内部对应数据的DO对象。最后逐层返回,相应的在Adapter层将DTO转为VO
场景2(CQRS诉求):
由外部客户端发起的不携带业务处理的查询操作,例如:某某数据列表查看、某某内容统计,则由Adapter接收请求后,封装参数对象后,调用相关App内容,App内部进行DTO和DO的相互coverter操作后,直接调用Infras层进行数据的查询操作。