领域驱动设计(DDD)分层架构的三种模式
模式⼀:四层架构
1.User Interface为⽤户界⾯层(或表⽰层),负责向⽤户显⽰信息和解释⽤户命令。这⾥指的⽤户可以是另⼀个计算机系统,不⼀定是使⽤⽤户界⾯的⼈。
2.Application为应⽤层,定义软件要完成的任务,并且指挥表达领域概念的对象来解决问题。这⼀层所负责的⼯作对业务来说意义重⼤,也是与其它系统的应⽤层进⾏交互的必要渠道。应⽤层要尽量简单,不包含业务规则或者知识,⽽只为下⼀层中的领域对象协调任务,分配⼯作,使它们互相协作。它没有反映业务情况的状态,但是却可以具有另外⼀种状态,为⽤户或程序显⽰某个任务的进度。
3.Domain为领域层(或模型层),负责表达业务概念,业务状态信息以及业务规则。尽管保存业务状态的技术细节是由基础设施层实现的,但是反映业务情况的状态是由本层控制并且使⽤的。领域层是业务软件的核⼼,领域模型位于这⼀层。
4.Infrastructure层为基础实施层,向其他层提供通⽤的技术能⼒:为应⽤层传递消息,为领域层提供持久化机制,为⽤户界⾯层绘制屏幕组件,等等。基础设施层还能够通过架构框架来⽀持四个层次间的交互模式。
模式⼆:五层架构
⼀、三层架构(Data、Context和Interactive)
Data层描述系统有哪些领域概念及其之间的关系,该层专注于领域对象的确⽴和这些对象的⽣命周期管理及关系,让程序员站在对象的⾓度思考系统,从⽽让“系统是什么”更容易被理解。
Context层:是尽可能薄的⼀层。Context往往被实现得⽆状态,只是到合适的role,让role交互起来完成业务逻辑即可。但是简单并不代表不重要,显⽰化context层正是为⼈去理解软件业务流程提供切⼊点和主线。
Interactive层主要体现在对role的建模,role是每个context中复杂的业务逻辑的真正执⾏者,体现“系统做什么”。role所做的是对⾏为进⾏建模,它联接了context和领域对象。由于系统的⾏为是复杂且多变的,role使得系统将稳定的领域模型层和多变的系统⾏为层进⾏了分离,由role专注于对系统⾏为进⾏建模。该层往往关注于系统的可扩展性,更加贴近于软件⼯程实践,在⾯向对象中更多的是以类的视⾓进⾏思考设计。
⼆、五层架构
1.User Interface是⽤户接⼝层,主要⽤于处理⽤户发送的Restful请求和解析⽤户输⼊的配置⽂件等,并
将信息传递给Application层的接⼝。
2.Application层是应⽤层,负责多进程管理及调度、多线程管理及调度、多协程调度和维护业务实例的状态模型。当调度层收到⽤户接⼝层的请求后,委托Context层与本次业务相关的上下⽂进⾏处理。
3.Context是环境层,以上下⽂为单位,将Domain层的领域对象cast成合适的role,让role交互起来完成业务逻辑。
4.Domain层是领域层,定义领域模型,不仅包括领域对象及其之间关系的建模,还包括对象的⾓⾊role的显式建模。
5.Infrastructure层是基础实施层,为其他层提供通⽤的技术能⼒:业务平台,编程框架,持久化机制,消息机制,第三⽅库的封装,通⽤算法,等等。
三、六层架构
1.User Interface是⽤户接⼝层,主要⽤于处理⽤户发送的Restful请求和解析⽤户输⼊的配置⽂件等,并将信息传递给Scheduler层的接⼝。
2.Scheduler是调度层,负责多进程管理及调度、多线程管理及调度、多协程调度和维护业务实例的状态模型。当调度层收到⽤户接⼝层的请求后,委托Transaction层与本次操作相关的事务进⾏处理。
restful接口设计3.Transaction是事务层,对应⼀个业务流程,⽐如UE Attach,将多个同步消息或异步消息的处理序列组合成⼀个事务,⽽且在⼤多场景下,都有选择结构。万⼀事务执⾏失败,则⽴即进⾏回滚。当事务层收到调度层的请求后,委托Context层的Action进⾏处理,常常还伴随使⽤Context层的Specification(谓词)进⾏Action的选择。
4.Context是环境层,以Action为单位,处理⼀条同步消息或异步消息,将Domain层的领域对象cast成合适的role,让role交互起来完成业务逻辑。环境层通常也包括Specification的实现,即通过Domain层的知识去完成⼀个条件判断。
5.Domain层是领域层,定义领域模型,不仅包括领域对象及其之间关系的建模,还包括对象的⾓⾊role的显式建模。
6.Infrastructure层是基础实施层,为其他层提供通⽤的技术能⼒:业务平台,编程框架,持久化机制,消息机制,第三⽅库的封装,通⽤算法,等等。
模式三:六边形架构
有⼀种⽅法可以改进分层架构,即依赖倒置原则(Dependency Inversion Principle, DIP),它通过改变不同层之间的依赖关系达到改进⽬的。根据该定义,DDD分层架构中的低层组件应该依赖于⾼层组件提供
的接⼝,即⽆论⾼层还是低层都依赖于抽象,整个分层架构好像被推平了。如果我们把分层架构推平,再向其中加⼊⼀些对称性,就会出现⼀种具有对称性特征的架构风格,即六边形架构。六边形架构是Alistair Cockburn在2005年提出的,在这种架构中,不同的客户通过“平等”的⽅式与系统交互。需要新的客户吗?不是问题。只需要添加⼀个新的适配器将客户输⼊转化成能被系统API所理解的参数就⾏。同时,对于每种特定的输出,都有⼀个新建的适配器负责完成相应的转化功能。
六边形架构也称为端⼝与适配器,如下图所⽰:
六边形每条不同的边代表了不同类型的端⼝,端⼝要么处理输⼊,要么处理输出。对于每种外界类型,都有⼀个适配器与之对应,外界通过应⽤层API与内部进⾏交互。上图中有3个客户请求均抵达相同的输⼊端⼝(适配器A、B和C),另⼀个客户请求使⽤了适配器D。假设前3个请求使⽤了HTTP协议(浏览器、REST和SOAP等),⽽后⼀个请求使⽤了AMQP协议(⽐如RabbitMQ)。端⼝并没有明确的定义,它是⼀个⾮常灵活的概念。⽆论采⽤哪种⽅式对端⼝进⾏划分,当客户请求到达时,都应该有相应的适配器对输⼊进⾏转化,然后端⼝将调⽤应⽤程序的某个操作或者向应⽤程序发送⼀个事件,控制权由此交给内部区域。
应⽤程序通过公共API接收客户请求,使⽤领域模型来处理请求。我们可以将DDD战术设计的建模元素Repository(存储库)的实现看作是持久化适配器,该适配器⽤于访问先前存储的聚合实例或者保存新
的聚合实例。正如图中的适配器E、F和G所展⽰的,我们可以通过不同的⽅式实现资源库,⽐如关系型数据库、基于⽂档的存储、分布式缓存或内存存储等。如果应⽤程序向外界发送领域事件消息,我们将使⽤适配器H进⾏处理。该适配器处理消息输出,⽽上⾯提到的处理AMQP消息的适配器则是处理消息输⼊的,因此应该使⽤不同的端⼝。
我们在实际的项⽬开发中,不同层的组件可以同时开发。当⼀个组件的功能明确后,就可以⽴即启动开发。由于该组件的⽤户有多个,并且这些⽤户的侧重点不同,所以需要提供多个不同的接⼝。同时,这些⽤户的认识也是不断深⼊的,可能会多次重构相关的接⼝。于是,组件的多个⽤户经常会组件的开发者讨论这些问题,⽆形中降低了组件的开发效率。
我们换⼀种⽅式,组件的开发者在明确了组件的功能后就专注于功能的开发,确保功能稳定和⾼效。组件的⽤户⾃⼰定义组件的接⼝(端⼝),然后基于接⼝写测试,并不断演进接⼝。在跨层集成测试时,由组件开发者或⽤户再开发⼀个适配器就可以了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论