第十周学习心得
领域
每个组织都有它自己的业务范围和做事方式,这个业务范围以及在其中所进行的活动便是领域。领域是一个组织所做的事情以及其中所包含的一切。领域的范围可能很大,试图想要创建一个全功能的领域模型是非常困难的,并且容易导致失败,所以需要把这个大的业务范围拆开。如果把这个范围看成一个空间的话,那它同时存在以下两个概念:
问题空间
问题空间是从业务需求方面来看的,用子域来划分问题空间
解决方案空间
解决方案空间是从软件方面来看的,用限界上下文来划分解决方案空间
子域
子域是对领域从业务需求方面进行逻辑上的拆分,子域主要分以下几种:
核心子域
业务成功的核心竞争力,拥有最高的优先级及最优秀的团队
通用子域
不是核心,但被整个业务系统所使用
支撑子域
不是核心,不被整个系统使用,专注于业务的某个方面
统一语言
统一语言是提炼领域知识的产出物,获得统一语言就是需求分析的过程,也是团队中各个角色就系统目标、范围与具体功能达成一致的过程。使用统一语言可以帮助我们讲参与讨论的客户、领域专家与开发团队拉到同一个维度空间进行讨论,因此,在沟通需求时,团队中的每个人都应使用统一语言进行交流。
统一语言体现在两个方面:
统一的领域术语
领域行为描述
限界上下文
限界上下文是一个边界,领域模型便存在于这个边界之内。原则上,一个上下文对应一个子域,但并不是绝对,限界上下文的目的是为了更加明确领域模型的职责和范围,是从解决方案空间来考虑问题的,通常来说,一个限界上下文可以是一个微服务,或者一个模块。
统一语言也是以限界上下文为边界进行划分的。
识别限界上下文的方式如下:
从业务边界识别
明确了系统问题域和业务期望后,确定业务流程,然后确定具体的业务场景,基于业务场景识别出具体的业务活动,通过业务活动的语义相关性和功能相关性,来初步识别出限界上下文
从工作界限识别
基于团队合作划分工作边界可以帮助我们确定限界上下文合理的工作粒度
从应用边界识别
可以基于质量属性、扩展性、遗留系统等来对上下文进行划分
上下文映射
两个限界上下文之间的关系是有方向的,DDD 使用两个专门的术语表述他们, 上游(Upstream) 和 下游(Downstream) ,在上下文映射图中,以 U 代表上游, D 代表下游。
根据团队协作模式,分为以下几种:
合作关系
限界上下文的合作关系是一种反模式,这种关系存在强耦合,甚至糟糕的双向依赖,在设计中应该杜绝使用
共享内核
共享内核往往被用来解决合作关系引入的问题,是解除不必要依赖并实现重用的重要手段
客户方-供应方开发
这是团队合作中最为常见的合作模式,是上游团队满足下游团队提出的领域需求
遵奉者
当由上游团队来决定是响应还是拒绝下游团队提出的请求时,就产生了所谓的遵奉者了。遵奉者还有一层意思是下游限界上下文对上游限界上下文模型的追随,比如对接口定义的重用。
分离方式
指两个限界上下文之间没有丝毫关系,这是一种最好的方式,两者互相不影响。
根据通信集成模式,分为以下几种:
防腐层
在架构层面,通过引入一个间接的层,就可以有效隔离限界上下文之间的耦合,这个防腐层类似于适配器模式。防腐层往往属于下游限界上下文,用以隔绝上游限界上下文可能发生的变化。
开放主机服务
防腐层是下游限界上下文对抗上游变化的利器,开放主机服务就是上游服务用来吸引更多下游调用者的诱饵。设计开放主机服务,就是定义公开服务的协议,包括通信的方式、传递消息的格式,即传统意义上的接口。
发布/订阅事件
即使使用开放主机服务,任然会导致两个上下文之间存在耦合关系,采用发布/订阅事件的方式可以在解耦合方面走的更远,通过消息中间件,发布方与订阅方完全隔离了,这种基于发布/订阅事件的协作关系,已经做到了力所能及的松耦合极致了。这种模式往往用于事件驱动架构或者 CQRS 架构模式中。
识别上下文映射,可以通过以下思考角度:
协作产生的依赖
领域行为产生的依赖
领域模型产生的依赖
数据产生的依赖
代码架构
DDD 的代码架构与传统的贫血模型使用的代码架构不同,代码架构有经典分层架构(四层架构)、六边形架构(整洁架构)、微服务架构,每种都有各自的特点,下图是基于以上的架构演进出来的一种架构:
这种架构符合整洁架构的思想,将业务与技术完全分离,适配层(基础设施层)依赖应用层和领域层,突出了系统的核心。
战术设计
战术设计是通过一系列的设计原则和手段,识别出限界上下文中具体的聚合、实体、值对象等关键对象及其之间的关系。
实体
实体是指要描述事物的主体,应该具有三要素:
身份标识
身份标识是实体对象的必要标志,没有身份标识的领域对象就不是实体
属性
属性用来说明其主体的静态特征,并通过属性持有数据与状态。
行为
行为用来说明其主体的动态特征。一般分为变更状态的领域行为、自给自足的领域行为、互为协作的领域行为。
值对象
值对象与实体的根本区别在于是否拥有唯一的身份标识。值对象具有不变性,所以是线程安全的。值对象的领域行为与实体的领域行为并无区别。
聚合
聚合具有以下基本特征:
聚合是包含了实体和值对象的一个边界
聚合内包含的实体和值对象形成一棵树,只有实体才能作为这棵树的根,这个根称为聚合根
外部对象只允许持有聚合根的引用
聚合作为一个完整的领域概念整体,在其内部会维护这个领域概念的完成性,体现业务上的不变量约束
有聚合根统一对外提供履行该领域概念职责的行为方法,实现内部各个对象之间的行为协作
评论