这里提出的Trinity Architecture是后端企业应用程序的架构模式。它源于采用依赖性倒置原理(DIP)的典型4层架构。它非常适合(但不限于)领域驱动设计(DDD)应用程序。
三位一体的三大支柱是:
所述领域模型(DOMAIN)
公共应用程序编程接口(API)
辅助服务(AUX)
Trinity强调平衡不受控制的灵活性和一致性。它提供了八个顶级模块的具体实施指南。
依赖规则是:
圆圈内的圆圈:外圈取决于内圈。
圆圈外的圆圈:外圆使用(客户端)或实现(细节)内部圆。
流行架构模式的简要概述
一开始,当计算机科学出现在50年代/ 60年代时,就没有我们今天所知的架构。开发人员通过优化算法和数据结构来解决问题。
软件架构一词在20世纪90年代初才开始流行。原因是客户端 - 服务器系统的兴起。使用客户端 - 服务器系统,出现了多层体系结构的模式。
后来,在同一个十年中,出现了分层架构。分层的系统将系统分解为逻辑层而不是物理层。
在2000年代,基于依赖性倒置原则出现了新的架构模式。他们的主要目标是解决分层架构的紧耦合问题。
1. 多层架构
有史以来最流行的架构是多层架构。该模式不指定层数,而是一个简单的规则:一层可以与其下面的任何层耦合,但从不与高于它的层耦合。
许多团队可能会争论分层架构中合适的层数。
Martin Fowler(2002)建议三层。(1)表现,(2)领域,和(3)数据源。
Eric Evans(2003)建议四层。(1)用户界面,(2)应用,(3)领域,以及(4)基础设施。
分层架构的好处
简单
一致性
关注点分离
分层架构的缺点
缺乏内置的可扩展性
隐藏的用例
业务逻辑可能从UI扩展到数据库
交换框架和技术很麻烦,如果不是禁止的话
复杂的测试过程
存在太多,不必要的层次的风险
2. 依赖倒置原则
Robert C. Martin 于1996年制定了依赖性倒置原则(DIP)。它代表“ SOLID ”原则中的字母“ D ” 。今天,它是面向对象编程中最着名的原则之一。
DIP的正式定义是:
A.高级模块不应该依赖于低级模块。两者都应该依赖于抽象(接口)。
B.抽象不应该依赖于细节。细节(类)应该取决于抽象。
Vaughn Vernon(2013)演示了如何在典型的4层架构中应用DIP:
通过这种简单的反转,领域层是所有其他层依赖的域层。这种方法消除了与基础设施层的直接耦合。
3基于DIP的架构
在2000年代中期之后,应用程序架构出现了一系列想法。
端口和适配器(六角形),Alistair Cockburn,2005年
洋葱杰弗里巴勒莫,2008年
罗伯特C.马丁的清洁建筑,2012/2017年
虽然它们的细节各不相同,但它们的目标是相同的。它们都旨在通过DIP 更好地分离关注点。我们可以称这个系列的架构模式同心Concentric。
根据Robert C. Martin的说法,他们背后的依赖规则是:
源代码依赖项必须指向内部,指向更高级别的策略。
基于DIP的架构的好处
独立于UI
独立于数据库和其他外部系统
独立于技术特定的库和框架
可互换的基础设施模块
任意数量和类型的客户端
可测试
基于DIP的架构的缺点
复杂
缺少模板(洋葱除外)
前几十年的模糊术语
易受错误依赖和模块结构的影响(如果做得不对)
如何选择模式?
三位一体的形成
Trinity的目标是解决基于DIP的架构的缺点。在本节中,将形成它的形式。所需的步骤是:
从典型的4层开始,定义通用与特定层
定义严格和轻松的依赖关系
应用DIP
包括应用程序模块并构成Trinity体系结构
1.定义通用和特定层
Trinity的起点是典型的4层,正如埃文斯在2003年所提出的那样。当时,诸如REST之类的技术对IT社区来说是未知的。我们现在将术语调整为最新标准:
客户端、
API、
领域层
辅助层
看看上面Vaughn Vernon(2013)转换到这四个层的映射过程:
用户界面层 - >客户端:今天应用程序不仅限于单个用户界面客户端。相反,可以有许多客户端。它们可以存在很多形式(即REST客户端,Web MVC客户端等)
应用层 - >(公共)API:应用层本身不区分公共和内部服务。在这里,我们将它强制为一个特定的层,通过将其重命名为(Public)API来表示其目的。
领域层 - >领域层:领域层是应用程序的核心,已经是一个非常特殊的层,它仍然保持原样。
基础设施层 - >辅助:基础设施可能令人困惑,特别是对于初级开发人员。人们可能只考虑物理服务器,例如数据库或消息服务器。但这不是唯一的例子。例如,基础设施也是实现复杂加密算法的服务。因此,我们用术语辅助替换术语基础设施。辅助程序更好地描述了有助于应用程序目的的任何内容。
2. 定义严格和宽松的依赖关系
在分层体系结构中,层之间有两种类型的耦合:
严格:只允许耦合到它下面的一层。
相关:任何更高级别的层都可以耦合到它下面的任何层。
应用DIP
在下一步中,我们将DIP应用于除了第一个以外下面的所有层,即API客户端。这是最关键的一步。
API只定义了DTO的和抽象。
Domain领域层定义的模型,它需要所有的抽象。因此,我们删除了与AUX层的耦合。
AUX层定义了应用程序所需的DTO和抽象。
API细节: 实现的API抽象使用的领域和AUX抽象。
DOMAIN详细: 实施的DOMAIN抽象
AUX细节: 落实的AUX抽象
API客户端使用的API抽象,不是API详细信息。
由于前三个模块仅定义抽象,因此它们与框架无关。
包括应用程序(APP)模块的实战图
接下来,我们包括应用程序模块,它是引导应用程序所必需的。它还负责配置APP,横切关注点等。
通过旋转和重新组织块,我们现在可以形成三位一体架构。
最下面一行是Trinity Core,它们与框架/技术无关。上排是三位一体组合。它提供实现和使用Trinity Core。
另一种观点是圆形的,在文章的顶部描绘。
三位一体架构
1. 核心
三位一体建筑的三大支柱是:
域:域模型
API:公共应用程序编程接口
AUX:辅助服务
这些模块中的每一个都不依赖于其余任何一个。他们的作用是仅定义DTO,模型和抽象。他们也应该不会有任何关于框架相关的库的依赖关系。唯一可接受的例外是如果需要,使用框架特定注释。
2 API详细信息
该API详细是连接三个独立的组件的API,AUX和DOMAIN的。
它的作用是通过使用Domain和Auxiliary模型以及抽象来实现API。除了特定于框架的注释之外,API Detail仍然是框架不可知的。
3 API客户端
该体系结构支持添加任意数量的API客户端。该API客户端只依赖于抽象API和不域模型或辅助服务。通过这种方式,我们确保每个用例始终都有一个应用程序入口点。
4 AUX详细信息
该AUX细节提供应用程序所需的实现。您应该根据角色将细节分成不同的模块。例如:
文档存储
短信服务
SMTP服务
等等
5 域详细信息
该层详细提供了应用程序所需的实现。您应该根据角色将细节分成不同的模块。例如:
持久保存数据库
领域服务
支付网关
模板引擎
等等
6 APP
Bootstraps并配置应用程序。
相关工具和工作
一个三位一体的架构的演示 for Java是可在Github上。
模块的名称与Trinity Architecture图中使用的模块名称相比为1:1。
Java的Trinity Scaffolder
trinity4J
trinity4J是一组面向Java应用程序的域驱动设计库。它非常适合Trinity Architecture。
PolyGenesis
Trinity Architecture是一个名为PolyGenesis的更大项目的一部分。
PolyGenesis是跨语言自动代码生成的开源平台。它侧重于 DDD和 UI。
结论
Trinity Architecture的特点是:
清晰的术语和明确定义的模块结构
框架独立核心(API,AUX,DOMAIN)
任意数量的API客户端,域详细信息和辅助详细信息
可互换的技术和框架
可测试
更好地分配团队成员
学习曲线低
支持工具和库