应用架构区别
好的应用架构,都遵循一些共同模式,不管是六边形架构、洋葱圈架构、整洁架构、还是COLA架构,都提倡以业务为核心,解耦外部依赖,分离业务复杂度和技术复杂度。
分层架构(Layered Architecture)
分层架构就是将业务应用划分为对应的层级模块。每个层职责不同。
四层结构定义:
-
接口层: 统一处理系统对外的服务接口,可以是直接查询,也可以是三方系统对接。
-
应用层: 调用各个领域完成一个具体的业务流程应用,不需要关心具体的业务实现。
-
领域层: 实际完成业务逻辑处理的地方,包含领域模型和领域服务,无须关心显示及存储等相关问题。
-
基础设施层: 提供底层支撑功能,包括持久化、序列化与反序列化、消息中间件等。
优点:
-
可降低层级之间依赖;
-
利于层级模块复用;
-
安全性高,外部系统只从接口层访问,统一入口点;
-
项目结构清晰,简单。
常见两种分层架构图:
图一:四层
图二:五层
六边形架构(Hexagonal Architecture)
六边形架构可以理解为“去结构化”的架构,系统内部与外界的交互过程通过适配器来完成,没有层次,所有交互双方只知道适配器的存在,不用知晓对方的存在。
六边形又称为端口适配器模式。六边形架构将系统分为内部和外部,内部代表具体的业务逻辑,也就是DDD中强调的领域模型(其中包含领域服务,对业务概念建立的模型等);外部代表基础设施和应用等,类似RESTful API, SOAP, AMQP, 或者数据库,内存,文件系统,以及自动化测试。 内部和外部之间通过端口通信。端口代表协议,通常是以API呈现。端口的具体实现是适配器,负责对接具体的外部系统或内部逻辑。该架构可以非常容易的实现外部替换、依赖倒置、自动测试等功能。
一个端口对应多个适配器,是对一类外部系统的归纳。
适配器分为主适配器和次适配器:
-
主适配器(Driving Adapter):代表接收用户输入,调用端口并返回数据。
-
次适配器(Driven Adapter):实现应用的出口端口,向外部工具执行操作。
六边形架构优点:
-
业务领域的边界更加清晰。
-
更好的可扩展性。(比如需要新增一种协议(数据库、MQ...)的支持,那么只需要定义一组端口-适配器即可。对原有端口-适配器不影响)
-
对测试的友好支持。
-
更容易实施DDD。
整洁架构(Clean Architecture)
整洁架构(又名洋葱架构 Onion Architecture),六边形架构的变种。
整洁架构是Robot C.Martin在《整洁架构之道》一书中提出来的架构设计思想。它以圆环的形式把系统分成了几个不同的层次,因此又被称为洋葱架构。
在整洁架构里,同心圆代表应用软件的不同部分,从里到外依次是领域模型、领域服务、应用服务、最外围是容易变化的内容,如界面和基础设施(如数据存储等)。整洁架构是以领域为中心,不是以数据为中心。
整洁架构最主要原则是依赖原则,它定义了各层的依赖关系,越往里,依赖越低,代码级别越高。外圆代码依赖只能指向内圆,内圆不知道外圆的任何事情。一般来说,外圆的声明(包括方法、类、变量)不能被内圆引用。同样的,外圆使用的数据格式也不能被内圆使用。
各层职责:
-
Domain Model:业务模型,对应DDD中的Entity、值对象等。
-
Domain Services:核心业务逻辑。
-
Application Services:应用的输入输出层。
-
User Interface/Tests/Infrastructure:适配器层(例如数据库、用户界面及外部服务)。
优点:
-
各层职责清晰,提高了大型复杂项目的可维护性。
-
结合DDD,使项目以领域模型为主。
-
保证内部核心领域的独立和无依赖,外部技术细节可以通过接口和适配器随时更换,在不丢失任何业务逻辑的情况下替换掉整个技术实现,从而增加系统的灵活性和可测性。
DDD架构(Domain Driven Design Architecture)
准确地说,DDD不是架构,而是一种开发思想。 DDD带来的最大改变是让我们得以从 “数据驱动”转向“领域驱动”,让我们知道领域是应用的核心,其它都是技术细节,随时可以被替换。
DDD四层架构见分层架构图一。
DDD采用统一语言,避免组件划分过程中的边界错位。 让业务架构和系统架构形成绑定关系,从而建立针对业务变化的高响应力架构。
-
战略层面:针对业务问题分析和分解,通过识别核心问题域来降低分析的复杂度。
-
战术层面:识别问题域里的不同业务上下文来进行面向业务需求的组件化。
DDD基本概念:
-
通用语言:通过画领域模型图、类图来建立一种沟通关系。
-
实体 Entity:从属于某个聚合根。实体具有id,有生命周期。
-
值对象 Value Object:无生命周期,归属具体的实体。
-
聚合 Aggregate:领域模型最底层的边界。逻辑边界。一个聚合只有一个聚合根。
-
聚合根 Aggregate Root:最抽象、最普遍的特征。也叫做根实体。
-
工厂 Factory:隐藏对象的复杂创建逻辑。
-
仓库 Repository:封装获取对象的逻辑。
-
限界上下文 Bounded Context:定义了每个模型的应用范围,可理解为一个子域对应一个上下文。一个上下文可能包含多个聚合,每个聚合都有一个根实体,叫做聚合根。
COLA架构 (Clean Object-oriented & Layered Architecture)
一方面COLA是一种架构思想,是整合了洋葱圈架构、适配器架构、DDD、整洁架构、TMF等架构思想的一种应用架构。
基于扩展点+元数据+CQRS+DDD的应用架构:扩展性好,贯彻了OO思想,有一套完整的规范标准,并采用CQRS和领域建模技术,很大程度可降低应用的复杂度。
层级职责:
-
cola-adapter:负责对前端展示的路由和适配。
-
cola-app:负责获取输入,组装context,做输入校验,调用领域层做业务处理。
-
cola-client:二方库组件,提供应用对外的接口。
-
cola-domain:领域层,封装核心业务逻辑。
-
cola-infrastructure:基础设施层,处理技术细节加领域防腐。
-
start:spring boot启动层。
图来源:https://blog.csdn.net/significantfrank/article/details/110934799
CQRS架构
命令查询职责分离(CQRS)是指读取和写入分别拥有单独的数据结构。 使用CQRS理由是,在复杂领域中,使用单一模型处理读取和写入过于复杂,我们可以通过分离模型来简化设计和实现。
其基本思想在于任何一个对象的方法可以分为以下两类:
-
命令(Command):不返回任何结果(void),但会改变对象的状态。
-
查询(Query):返回结果,但是不会改变对象的状态,对系统没有副作用。
CQRS查询和更新数据(命令)模型不一样,CQRS强调的是command和query访问的数据模型不同,分别根据command与query需求的不同特性设计数据模型。 命令模型数据变更后,需同步给查询模型。
在很多系统业务设计上,数据库里数据模型很难和业务领域模型一致,所以DDD中有领域模型(Domain model)的概念,在领域层转换成对应的数据库DO(Data Object)实体。
优点:
-
读写逻辑高度解耦,符合单一职责(模型分离,可独立设计)
-
独立部署有更好的伸缩性
缺点:
-
带来了复杂性,传统过程式编程直接用一个模型搞定,现在变成两个模型,还要结合一些DDD的思想才能更好的实现;
-
数据非强一致性,是最终一致性。(个人理解:如果同步实现保证强一致性的话,命令端写成功之后还需要往查询端写,会降低系统可用性)
参考资料
-
<中台落地手记: 业务服务化与数据资产化>
-
代码精进之路: 从码农到工匠
-
领域驱动设计(Thoughtworks洞见)