走向卓越,领域驱动设计的思维方式

软件系统是以特定的代码解决现实世界的复杂问题。软件开发的最大困难就是应对复杂度,复杂度可能来源于各个方面。领域驱动设计的概念是 2004 年 Evic Evans 提出的 Domain-Driven Design,简称 DDD。随着软件技术发展,大家逐渐意识到领域驱动设计的重要性。

 领域驱动设计是一套方法论,是从业务视角对需求的分析,指导我们将复杂问题进行拆分,帮助我们解决大型复杂系统在落地中遇到的问题。领域驱动设计,要从繁杂的需求中找出确定的领域模型。基于统一明确的领域模型,在需求、产品、开发、测试等团队之间能够形成【统一语言】,降低需求对焦的成本。

 

领域驱动的核心概念

领域驱动设计提出的核心概念包括:域、子域、限界上下文、领域实体、值对象、领域服务、领域事件、聚合、工厂、资源库等。

领域实体是指我们使用唯一的标识符跟踪具有重要业务意义的对象。实体代表的业务对象不变,但是会产生状态和业务属性的变更。实体一般和主要的业务/领域对象有一个直接的关系。一个实体的基本概念是一个持续抽象的生命,可以变化不同的状态和情形,但总是有相同的标识。

值对象用来描述特征。值对象不需要唯一标识,通常只关心具体的属性。值对象用来表示临时的事物,或者实体的属性。如果两个对象的所有的属性值都相同,可以认为它们是同一个对象的话,那么我们就可以把这种对象设计为值对象。

领域服务代表的是一些商业逻辑或业务处理过程,并不和领域对象相关,涉及的领域概念通常不属于一个实体或者值对象。领域服务是无状态的,在领域服务中实现领域逻辑的调用。它存在的意义就是协调领域对象共同完成某个操作,所有的状态还是都保存在相应的领域对象中。

领域事件代表的是系统中发生了什么,是一种特殊的值对象。领域事件由实体触发,通过事件解耦领域模型内部的一些依赖,会对领域模型中的其他部分产生业务影响。并不是所有的事件都是领域事件,领域事件必须对业务有价值,有助于形成完整的业务闭环,将导致进一步的业务操作。

image.png

根据业务需要可以聚合实体和值对象,并围绕聚合定义边界。聚合作为一个整体来定义属性,选择一个实体作为聚合的根对象,只允许外部对象引用聚合的根对象。聚合内对象具有一致的生命周期,一旦聚合根对象消失,则聚合内其他对象也要消失。

领域驱动设计使用了工厂模式来构造聚合对象。工厂方法只能返回聚合对象,不能返回聚合内细分的实体和值对象,需要确保外界对聚合的引用一定是通过根对象实现的。通过工厂来分离聚合的构造和使用,保证业务一致性。

聚合的仓储通过资源库来实现。外部系统只能通过资源库访问聚合。一个聚合只能有一个资源库对象,也就是以聚合根对象命名的资源库,不能再提供其他的资源库。

域和子域的划分是为了能够对复杂问题分而治之。在系统化思维中,特别强调系统中部分的划分和部分之间关系的处理。域的概念可以理解为系统化思维的一种实践。划分域后,可以简化认知、隔离域的变化、聚焦重点。一般通过观察业务流程、观察领域模型、观察分析过程,从业务视角出发来划分业务能力,实现域的定义和划分。

限界上下文是一个显式的边界,和子域的边界保持一致,如用户上下文(对应用户域)、支付上下文(对应支付域)。限界上下文能够明确领域模型的清晰的、达成共识的边界。边界不清晰常常引起诸多问题,如业务需求由哪个团队开发、模型定义放在哪个域。

 

领域驱动的架构设计

在一般的架构设计中,架构分层具有依赖关系。上层一定依赖于下层,下层为上层提供接口和服务。而在领域驱动设计中,推荐六边形架构来强化领域模型的重要地位。让外界系统服务于领域模型,实现领域内部的确定性。领域内部关注如何通过模型及其相关概念,在抽象的层次上把业务表达出来。

领域模型定义接口,由其他层实现接口。整体的设计完全围绕领域模型进行。一般架构设计中都把基础设施作为最底层,并且通常认为基础设施具有确定性。而在领域驱动设计中,对于基础设施(如数据持久化),由领域模型定义接口并由基础设施层实现接口。这样的设计保证领域模型对抽象有确定的定义,而基础设施作为六边形外围接口的实现可以随时替换。

 

image.png

 

领域驱动的事件风暴

领域模型的定义是在需求分析过程中产生的。需求分析一般使用被称为【事件风暴】的分析方法。使用领域驱动设计的理念去做需求分析,意味着我们将把事件作为项目的中心。通过【事件风暴】可以发现完整的业务场景和潜在的遗漏点,可以建立端到端的共识,能够帮助梳理出测试用例。

 

image

 

事件的发生一般会对领域对象产生影响。因此【事件风暴】的分析步骤一般包括:

首先确定终态业务事件,比如打车已经到达目的地;

然后从终态业务事件出发,反推达成此事件需要的前提条件,从而确定业务的事件流;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyswsj.html