应用架构区别

好的应用架构,都遵循一些共同模式,不管是六边形架构、洋葱圈架构、整洁架构、还是COLA架构,都提倡以业务为核心,解耦外部依赖,分离业务复杂度和技术复杂度。

分层架构(Layered Architecture)

分层架构就是将业务应用划分为对应的层级模块。每个层职责不同。

四层结构定义:

  • 接口层: 统一处理系统对外的服务接口,可以是直接查询,也可以是三方系统对接。
  • 应用层: 调用各个领域完成一个具体的业务流程应用,不需要关心具体的业务实现。
  • 领域层: 实际完成业务逻辑处理的地方,包含领域模型和领域服务,无须关心显示及存储等相关问题。
  • 基础设施层: 提供底层支撑功能,包括持久化、序列化与反序列化、消息中间件等。

优点:

  1. 可降低层级之间依赖;
  2. 利于层级模块复用;
  3. 安全性高,外部系统只从接口层访问,统一入口点;
  4. 项目结构清晰,简单。

常见两种分层架构图:

应用层 架构 应用架构分层_领域模型

图一:四层


应用层 架构 应用架构分层_系统架构_02

图二:五层

六边形架构(Hexagonal Architecture)

六边形架构可以理解为“去结构化”的架构,系统内部与外界的交互过程通过适配器来完成,没有层次,所有交互双方只知道适配器的存在,不用知晓对方的存在。

六边形又称为端口适配器模式。六边形架构将系统分为内部和外部,内部代表具体的业务逻辑,也就是DDD中强调的领域模型(其中包含领域服务,对业务概念建立的模型等);外部代表基础设施和应用等,类似RESTful API, SOAP, AMQP, 或者数据库,内存,文件系统,以及自动化测试。 内部和外部之间通过端口通信。端口代表协议,通常是以API呈现。端口的具体实现是适配器,负责对接具体的外部系统或内部逻辑。该架构可以非常容易的实现外部替换、依赖倒置、自动测试等功能。

一个端口对应多个适配器,是对一类外部系统的归纳。

适配器分为主适配器和次适配器:

  • 主适配器(Driving Adapter):代表接收用户输入,调用端口并返回数据。
  • 次适配器(Driven Adapter):实现应用的出口端口,向外部工具执行操作。

六边形架构优点:

  • 业务领域的边界更加清晰。
  • 更好的可扩展性。(比如需要新增一种协议(数据库、MQ...)的支持,那么只需要定义一组端口-适配器即可。对原有端口-适配器不影响)
  • 对测试的友好支持。
  • 更容易实施DDD。

应用层 架构 应用架构分层_系统架构_03

整洁架构(Clean Architecture)

整洁架构(又名洋葱架构 Onion Architecture),六边形架构的变种。

整洁架构是Robot C.Martin在《整洁架构之道》一书中提出来的架构设计思想。它以圆环的形式把系统分成了几个不同的层次,因此又被称为洋葱架构。

在整洁架构里,同心圆代表应用软件的不同部分,从里到外依次是领域模型、领域服务、应用服务、最外围是容易变化的内容,如界面和基础设施(如数据存储等)。整洁架构是以领域为中心,不是以数据为中心。

整洁架构最主要原则是依赖原则,它定义了各层的依赖关系,越往里,依赖越低,代码级别越高。外圆代码依赖只能指向内圆,内圆不知道外圆的任何事情。一般来说,外圆的声明(包括方法、类、变量)不能被内圆引用。同样的,外圆使用的数据格式也不能被内圆使用。

应用层 架构 应用架构分层_系统架构_04

各层职责:

  • 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启动层。

图来源:

应用层 架构 应用架构分层_应用层 架构_05

CQRS架构

命令查询职责分离(CQRS)是指读取和写入分别拥有单独的数据结构。 使用CQRS理由是,在复杂领域中,使用单一模型处理读取和写入过于复杂,我们可以通过分离模型来简化设计和实现。

其基本思想在于任何一个对象的方法可以分为以下两类:

  • 命令(Command):不返回任何结果(void),但会改变对象的状态。
  • 查询(Query):返回结果,但是不会改变对象的状态,对系统没有副作用。

CQRS查询和更新数据(命令)模型不一样,CQRS强调的是command和query访问的数据模型不同,分别根据command与query需求的不同特性设计数据模型。 命令模型数据变更后,需同步给查询模型。

在很多系统业务设计上,数据库里数据模型很难和业务领域模型一致,所以DDD中有领域模型(Domain model)的概念,在领域层转换成对应的数据库DO(Data Object)实体。

优点:

  • 读写逻辑高度解耦,符合单一职责(模型分离,可独立设计)
  • 独立部署有更好的伸缩性

缺点:

  • 带来了复杂性,传统过程式编程直接用一个模型搞定,现在变成两个模型,还要结合一些DDD的思想才能更好的实现;
  • 数据非强一致性,是最终一致性。(个人理解:如果同步实现保证强一致性的话,命令端写成功之后还需要往查询端写,会降低系统可用性)

应用层 架构 应用架构分层_应用层 架构_06

参考资料

  1. <中台落地手记: 业务服务化与数据资产化>
  2. 代码精进之路: 从码农到工匠
  3. 领域驱动设计(Thoughtworks洞见)