DDD系列 - 第0讲 DDD中常提到的应用架构总结(六边形、洋葱、整洁、清晰)_整洁架构 六边形架构-程序员宅基地

技术标签: DDD(领域驱动设计)  DDD  清晰架构  洋葱架构  六边形架构  整洁架构  

一、引言

最近在学习DDD应用架构设计时,接触到了不同的应用架构设计概念,如六边形架构、洋葱架构、整洁架构、清晰架构…,起初是一头雾水,在不断学习过程中也算对此有了些理解,故在本文中对这些架构进行了简单的介绍和总结。

这些架构随时间的演进可参见下图:

名词替换
提出端口、适配器概念
将应用分为内层核心业务逻辑、外层适配器实现
内层添加DDD分层
整合六边形、洋葱等架构
整合上述全部架构
更清晰、具体
EIC
Entity-Interface-Control)
1992 Ivar Jacobson
EBI
Entity-Boundary-Interacter
Robert C. Martin
Clean Architecture
端口和适配器架构(六边形架构)
Ports & Adapters Artchitechture
Hexagonal Architecture
2005 Alistair Cockburn
整洁架构
Clean Architechure
2012 Robert C. Martin (AKA Uncle Bob)
洋葱架构
Onion Architecture
2008 Jeffrey Palermo
清晰架构
Explicit Architecture
2017 Herberto Graca

接下来依次介绍各架构。

二、EIC(Entity-Interface-Control) & EBI(Entity-Boundary-Interactor)

1992年由Ivar Jacobson提出EIC(Entity-Interface-Control) 架构,
之后Robert C. Martin在一次关于整洁架构Clean Architecture的演讲中将其调整为EBI(Entity-Boundary-Interactor),即:

  • Entity => Entity: 维持不变
  • Interface => Boundary: 避免和编程语言中的interface相混淆
  • Control => Interactor: 避免和MVC Controller相混淆

Ivar Jacobson 1992, pp. 171

注: 参考上图EBI架构,图片中的矩形边数或边界在这里插入图片描述数量为4,
若将其修改为6边型,即可演进为2005年(13年后)提出的六边形架构(见下文),
即可以将其视为六边形架构(端口、适配器架构)思想的前身。

EBI对象类型说明如下:

  • Entity: 实体对象,包含数据、行为(避免贫血模型anaemic entities)
  • Boundary(Interface): 系统与外界交互的边界,即对应bounday object,如controller实现(主动)、持久化实现(被动)、消息通知(被动)等。
  • Interactor(Control): 所有不适合放在Entity和Boundary的行为都需要放在Interactor对象中,等价于DDD中的:
    • Application Services(who orchestrate(编排) use cases) - DDD架构中的应用服务层
    • Domain Services (who contain Domain behaviour but are not entities) - DDD架构中的领域服务层

类比MVC(Model View Controller)模式,

  • 模型层Model即表示整个后端back-end,包括services、entities等
  • 表现层Presentation即包含View层、Controller层
  • View层、Controller层即为Boundary,
  • Entity即为实体数据及其关联的行为操作(充血模型)
  • Interactor(Application Services, Domain Services)即为表现层(View、Controller)和Entity的连接,
  • 将MVC和EBI模式组合起来类似:View-Controller-Interactor-Entity

三、端口和适配器架构Ports & Adapters Architecture(又称六边形架构Hexagonal Architecture)

2005年,Alistair Cockburn提出了端口和适配器架构Ports & Adapters Architecture(又称六边形架构Hexagonal Architecture)。

分层架构(上下) -> 左右 -> 多边 -> 主被动适配器

端口和适配器架构中的相关概念:

  • 工具Tools: 应用application使用的工具Tools(WebSerevr, Cli, DB, SearchEngine, MQ)

  • 端口Port: 在application core层定义的工具交互规范(即定义 工具Tools如何使用application core的规范 或 工具Tools如何被application core使用的规范),对应编程语言的interface定义,且端口定义应该符合应用层逻辑(不可简单模仿或者直接使用底层工具的API)

  • 适配器Adapter: 连接工具Tools(WebSerevr, Cli, DB, SearchEngine, MQ)和应用核心application core的代码单元

    • 适配器依赖port(调用port 或 实现port)和工具,但是application core仅依赖port。
  • 主动适配器(Primary/Driving Adapters ) - 主动调用应用核心Application Core,触发应用执行某项活动

    • 主动适配器 -> 依赖端口 -> 注入端口实现
    • 例如主动适配器Controller -> 依赖端口ServiceInterface -> 注入端口实现ServiceImpl
  • 被动适配器(Secondary/Driven Adapters) - 被应用核心Application Core调用来执行动作,实现应用定义的端口

    • 端口 -->被动适配器实现端口逻辑-> 包装系统外部工具,
    • 例如端口RespositoryInterface -> 被动适配器Mysql实现MysqlRepositoryImpl -> 调用Mysql数据库

几边形不重要,可以N多边,重点是Port & Adapter思想,关于端口和适配器架构的优势:

  • 核心业务在最中心(最重要),
  • 核心业务依赖Port,Adapter依赖Port(主动) 或 Adapter为Port的具体实现(被动),
  • 核心业务逻辑与实现细节(技术框架、底层存储、工具、传输通信机制等)相隔离,
  • 保持核心业务逻辑的可重用性,
  • 可通过(注入)不同Adapter实现来切换技术实现,避免技术框架、工具、供应商锁定,
  • 且基于mock Port的形式更易于测试。

四、洋葱架构Onion Architecture

洋葱架构(Onion Architecture) 在2008年由Jeffrey Palermo提出。

在这里插入图片描述
洋葱架构 构建在Port & Adapter架构(又称六边形架构)之上,在Port & Adapter架构中仅提到2层:
1)外层 - 表示传输(通信)机制和基础设施infrastructure
2)内层 - 业务逻辑

洋葱架构在DDD的基础上,将内层(业务逻辑层,Business Logic)进一步划分,最终为:

  • Adapters,即六边形架构中的适配器Adapter层
    • User Interface、Infrastructure、Tests
  • Application Core,应用核心层,也即原来的六边形架构中心的Business Logic层
    • Application Services - 应用服务册层
    • Domain Services - 领域服务层
    • Domain Model - 领域模型层

明确了依赖方向

  • 外层依赖内层
  • 内层不知道外层
  • 且在不破坏依赖方向的前提下,外层亦可以直接调用任一内层(不一定是相邻接的2层),参考CQRS中Query实现(Application Services直接调用DAO)

五、整洁架构Clean Architecture

2012年Robert C. Martin (又名Uncle Bob) 提出了整洁架构Clean Architecture,整洁架构将EBI、六边形架构Hexagonal、洋葱架构Onoin等整合成一个可以实际落地的架构。
在这里插入图片描述
与洋葱架构相比,整洁架构调整如下:

  • Application Services调整为Use Cases
  • Domain Services, Domain Model调整为Entities

整洁架构并没有带来突破性的概念或模式,但是:

  • 它发掘了某种程度上被遗忘了的概念、规则和模式;
  • 它澄清了一些实用且重要的概念、规则和模式;
  • 它告诉我们如何把所有的概念、规则和模式整合起来,形成一种构建复杂应用并保持可维护性的标准套路

六、清晰架构Explicit Architecture

2017年Herberto Graca在其软件架构编年史系列文章中提出清晰架构Explicit Architecture,即将DDD, Hexagonal, Onion, Clean, CQRS等进行融合后的架构。
在这里插入图片描述

  • 最中心的红色多边形Application Core即表示业务逻辑实现,即应用核心
    • 红色多边形的边界即表示端口Port,即应用核心的入口/出口定义
    • Application Layer - 应用层,包括:
      • Application Services,业务用例的编排服务即及其interface定义,应用服务的作用通常如下:
        • 使用 Repostitory 查找一个或多个实体;
        • 让这些实体执行一些领域逻辑;
        • 再次使用 Repostitory 让这些实体持久化,有效地保存数据变化;
        • 触发应用事件(如发送邮件、调用第三方API、发送MQ消息等)。
      • CQRS命令/查询处理器
      • Event Listener事件监听器
      • Port端口定义,如ORM 接口Repostitory、搜索引擎接口、消息接口等等
    • Domain Layer - 领域层,这一层含了数据和操作数据的逻辑,它们只和领域本身有关,独立于调用这些逻辑的业务过程。它们完全独立,对应用层完全无感知。
      • Domain Services - 领域服务,封装涉及多实体(相同或不同实体类型)的领域逻辑,且领域服务间可以相互调用。
      • Domain Models - 领域模型,在架构的正中心,完全不依赖外部任何层次的领域模型。它包含了那些表示领域中某个概念的业务对象,如实体、值对象、枚举以及其它领域模型种用到的任何对象(如领域事件Domain Events,简单理解为MQ消息)。
  • 红色多边形的外侧左半圆部分即为主/主动适配器(用户界面User Interface实现)
    • 如Spring MVC中的Controller实现
    • Command Query Bus 命令查询总线
  • 红色多边形的外侧右半圆部分即次/被动适配器(基础设置Infrastructure实现)
    • 如数据持久化实现Mysql、短信通知实现、MQ通知、搜索引擎ES实现等
    • Event Bus 事件总线
  • 依赖方向由外到内,且内层不知道外层(参见之前洋葱架构)

采用按组件分包Package By Component,即整合传统按层分包Package By Layer和按特性分包Package By Feature,组件Component可以理解为专属于特定一个领域内的业务逻辑服务和数据访问逻辑的组合,也可以理解为特定领域,如账单、用户、评论或帐号等。

A “component” in this sense is a combination of the business and data access logic related to a specific thing (e.g. domain concept, bounded context, etc).

在清晰架构中可以理解为:

  • 先按照层次进行分包
    • 表现层Presentation
    • 业务核心层Application Core
    • 基础设施层Infrastructure
  • 之后每一层次再按照特性分包

在这里插入图片描述

正如Herberto Graca在DDD, Hexagonal, Onion, Clean, CQRS, … How I put it all together中写到:

清晰架构只是一份指南!
应用才是疆域,现实情况和具体用例才是运用这些知识的地方,它们才能勾勒出实际架构的轮廓!
我们需要理解所有这些模式,
但我们还时常需要思考和理解我们的应用需要什么,我们应该在追求解耦和内聚的道路上走多远。
这个决定可能受到许多因素的影响,
包括项目的功能需求,也包括构建应用的时间期限,应用寿命,开发团队的经验等等因素。


附国内大神翻译的清晰架构中文版:

在这里插入图片描述

关于传统分层、六边形、洋葱、整洁、清晰架构的演进可参见下图:
在这里插入图片描述

七、汇总

综合以上架构,给出我认为合理的、可以落地的架构如下图(后续会根据实际的使用体验进行完善):

注:
D3S(DDD with SpringBoot)为本作者使用DDD过程中开发的框架,
源码地址:https://gitee.com/luoex/d3s

在这里插入图片描述

八、后续…

  • 清晰架构中跨组件通信
  • CQRS处理
  • 共享内核等
  • Event Driven
  • 限界上线文、上下文映射

参考:

EBI:
https://herbertograca.com/2017/08/24/ebi-architecture/

端口和适配器架构:
11.端口和适配器架构(译) - https://www.jianshu.com/p/f39f4537857e
https://herbertograca.com/2017/09/14/ports-adapters-architecture/

洋葱架构:
https://herbertograca.com/2017/09/21/onion-architecture/
https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/

整洁架构:
https://herbertograca.com/2017/09/28/clean-architecture-standing-on-the-shoulders-of-giants/
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

清晰架构:
https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/
17.清晰架构(01): 融合 DDD、洋葱架构、整洁架构、CQRS…(译) - https://www.jianshu.com/p/d3e8b9ac097b

DDD:
https://herbertograca.com/2017/09/07/domain-driven-design/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/luo15242208310/article/details/124708008

智能推荐

WCE Windows hash抓取工具 教程_wce.exe -s aaa:win-9r7tfgsiqkf:0000000000000000000-程序员宅基地

文章浏览阅读6.9k次。WCE 下载地址:链接:https://share.weiyun.com/5MqXW47 密码:bdpqku工具界面_wce.exe -s aaa:win-9r7tfgsiqkf:00000000000000000000000000000000:a658974b892e

各种“网络地球仪”-程序员宅基地

文章浏览阅读4.5k次。Weather Globe(Mackiev)Google Earth(Google)Virtual Earth(Microsoft)World Wind(NASA)Skyline Globe(Skylinesoft)ArcGISExplorer(ESRI)国内LTEarth(灵图)、GeoGlobe(吉奥)、EV-Globe(国遥新天地) 软件名称: 3D Weather Globe(http:/_网络地球仪

程序员的办公桌上,都出现过哪些神奇的玩意儿 ~_程序员展示刀,产品经理展示枪-程序员宅基地

文章浏览阅读1.9w次,点赞113次,收藏57次。我要买这些东西,然后震惊整个办公室_程序员展示刀,产品经理展示枪

霍尔信号、编码器信号与电机转向-程序员宅基地

文章浏览阅读1.6w次,点赞7次,收藏63次。霍尔信号、编码器信号与电机转向从电机出轴方向看去,电机轴逆时针转动,霍尔信号的序列为编码器信号的序列为将霍尔信号按照H3 H2 H1的顺序组成三位二进制数,则霍尔信号翻译成状态为以120°放置霍尔为例如不给电机加电,使用示波器测量三个霍尔信号和电机三相反电动势,按照上面所说的方向用手转动电机得到下图① H1的上升沿对应电机q轴与H1位置电角度夹角为0°,..._霍尔信号

个人微信淘宝客返利机器人搭建教程_怎么自己制作返利机器人-程序员宅基地

文章浏览阅读7.1k次,点赞5次,收藏36次。个人微信淘宝客返利机器人搭建一篇教程全搞定天猫淘宝有优惠券和返利,仅天猫淘宝每年返利几十亿,你知道么?技巧分享:在天猫淘宝京东拼多多上挑选好产品后,按住标题文字后“复制链接”,把复制的淘口令或链接发给机器人,复制机器人返回优惠券口令或链接,再打开天猫或淘宝就能领取优惠券啦下面教你如何搭建一个类似阿可查券返利机器人搭建查券返利机器人前提条件1、注册微信公众号(订阅号、服务号皆可)2、开通阿里妈妈、京东联盟、拼多多联盟一、注册微信公众号https://mp.weixin.qq.com/cgi-b_怎么自己制作返利机器人

【团队技术知识分享 一】技术分享规范指南-程序员宅基地

文章浏览阅读2.1k次,点赞2次,收藏5次。技术分享时应秉持的基本原则:应有团队和个人、奉献者(统筹人)的概念,同时匹配团队激励、个人激励和最佳奉献者激励;团队应该打开工作内容边界,成员应该来自各内容方向;评分标准不应该过于模糊,否则没有意义,应由客观的基础分值以及分团队的主观综合结论得出。应有心愿单激励机制,促进大家共同聚焦到感兴趣的事情上;选题应有规范和框架,具体到某个小类,这样收获才有目标性,发布分享主题时大家才能快速判断是否是自己感兴趣的;流程和分享的模版应该有固定范式,避免随意的格式导致随意的内容,评分也应该部分参考于此;参会原则,应有_技术分享

随便推点

O2OA开源企业办公开发平台:使用Vue-CLI开发O2应用_vue2 oa-程序员宅基地

文章浏览阅读1k次。在模板中,我们使用了标签,将由o2-view组件负责渲染,给o2-view传入了两个参数:app="内容管理数据"和name="所有信息",我们将在o2-view组件中使用这两个参数,用于展现“内容管理数据”这个数据应用下的“所有信息”视图。在o2-view组件中,我们主要做的事是,在vue组件挂载后,将o2的视图组件,再挂载到o2-view组件的根Dom对象。当然,这里我们要在我们的O2服务器上创建好数据应用和视图,对应本例中,就是“内容管理数据”应用下的“所有信息”视图。..._vue2 oa

[Lua]table使用随笔-程序员宅基地

文章浏览阅读222次。table是lua中非常重要的一种类型,有必要对其多了解一些。

JAVA反射机制原理及应用和类加载详解-程序员宅基地

文章浏览阅读549次,点赞30次,收藏9次。我们前面学习都有一个概念,被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。反射就像一面镜子,它可以清楚看到类的完整结构信息,可以在运行时动态获取类的信息,创建对象以及调用对象的属性和方法。

Linux-LVM与磁盘配额-程序员宅基地

文章浏览阅读1.1k次,点赞35次,收藏12次。Logical Volume Manager,逻辑卷管理能够在保持现有数据不变的情况下动态调整磁盘容量,从而提高磁盘管理的灵活性/boot分区用于存放引导文件,不能基于LVM创建PV(物理卷):基于硬盘或分区设备创建而来,生成N多个PE,PE默认大小4M物理卷是LVM机制的基本存储设备,通常对应为一个普通分区或整个硬盘。创建物理卷时,会在分区或硬盘的头部创建一个保留区块,用于记录 LVM 的属性,并把存储空间分割成默认大小为 4MB 的基本单元(PE),从而构成物理卷。

车充产品UL2089安规测试项目介绍-程序员宅基地

文章浏览阅读379次,点赞7次,收藏10次。4、Dielecteic voltage-withstand test 介电耐压试验。1、Maximum output voltage test 输出电压试验。6、Resistance to crushing test 抗压碎试验。8、Push-back relief test 阻力缓解试验。7、Strain relief test 应变消除试验。2、Power input test 功率输入试验。3、Temperature test 高低温试验。5、Abnormal test 故障试验。

IMX6ULL系统移植篇-系统烧写原理说明_正点原子 imx6ull nand 烧录-程序员宅基地

文章浏览阅读535次。镜像烧写说明_正点原子 imx6ull nand 烧录