《DDD战略设计相关核心概念梳理与理解.docx》由会员分享,可在线阅读,更多相关《DDD战略设计相关核心概念梳理与理解.docx(8页珍藏版)》请在优知文库上搜索。
1、DDD核心概念梳理DDD是什么,DDD的英文全称是Domain-DrivenDesign,翻译过来就是领域驱动设计。这种设计一般是用在微服务的系统中,当我们聊微服务的时候,争论最多的就是如何进行微服务的拆分,这也是最让人产生争议的地方。当我们聊微服务也必然会会聊到中台,中台又是什么呢?中台中台从2015年提出,就已经被我们熟知,但是每个人对中台的认识可能都千差万别,有没有一个大家都比较认可的定义呢?将通用的可复用的业务能力沉淀到中台业务模型,实现企业级能力复用。因此中台面临的首要问题就是中台领域模型的重构。而中台落地时,依然会面临微服务设计和拆分的问题。微服务:中台落地时需要用微服务进行支撑。
2、中台:复用业务,实现企业级能力复用。DDD:对中台进行领域建模,实现适合企业发展的中台。DDD可以说是微服务和中台的产品经理。我们去写业务功能时,是面向领域的,而不是面向数据库表来实现代码的。二、DDD是什么?DDD的核心思想:是通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业务模型与代码模型的一致性。DDD是一种处理高度复杂领域的设计思想,它试图分离技术实现的复杂性,并围绕业务概念构建领域模型来控制业务的复杂性,以解决软件难以理解,难以演进的问题。战略设计:主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,限界上下文可以作为微服务设计的参考边界。战
3、术设计:则从技术视角出发,侧重于领域模型的技术实现,完成软件开发和落地,包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。三、DDD架构分层首先我们来看下架构分层的原理图:第三方工R基础服务用户接口层用户接口层主要包含用户界面、Web服务。用户接口层负责向用户显示信息和解释用户指令。这里的用户可能是:用户、程序、自动化测试和批处理脚本等等。应用层应用层不应该有业务逻辑。它是很薄的一层,理论上不应该有业务规则或逻辑,主要面向用例和流程相关的操作。应用服务是在应用层的,它负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装,以粗粒度的服务通过API网关向
4、前端发布。还有,应用服务还可以进行安全认证、权限校验、事务控制、发送或订阅领域事件等。领域层领域层主要实现企业的核心业务逻辑,和之前的三层架构的Service层很像。领域层当中又包含聚合,聚合里面就带有聚合根、实体、值对象、领域服务等领域模型中的领域对象。领域模型的业务逻辑主要通过实体和领域服务来实现,采用充血模型来时先所有与之相关的业务功能。充血模型后面会解释。当单一实体(或值对象)不能实现时,领域服务就来进行聚合多个实体(或值对象),来实现复杂的业务逻辑。基础层基础层为其他各层提供通用的技术和基础服务,包括数据库服务、消息中间件、对象存储、缓存服务等。它是封装了所有的基础服务,当切换基础组
5、件时,只用稍微修改下基础服务就可以了。比如之前用的对象文件存储组件是阿里的,现在想换成腾讯的了,稍微改下基础服务,切换成腾讯的就可以了,不用去改业务逻辑代码。这个就是采用了依赖倒置的原则,通过解耦来保持独立的核心业务逻辑。传统三层架构转DDD四层架构传统的三层架构就是controller-service-model这种模型,我们的思维习惯就是基于数据库的表来开发业务功能。这种分层架构给开发人员带来了便利,但是如果有其他人过来看你的代码,他会很难从业务角度去理解,因为这些代码都是为操作数据库的表而写。有了DDD之后,代码是面向业务功能的,而不是面向数据库表的。DDD分层架构将业务逻辑层的服务拆分
6、到了应用层和领域层。应用层快速响应前端的变化,领域层实现领域模型的能力。三层架构数据访问采用DAO方式;DDD分层架构的数据库等基础资源访问,采用了仓储(RePOSitory)设计模式,通过依赖倒置实现各层对基础资源的解耦。四、DDD中各种ObjeCt数据持久化对象(PersistentObject,PO),与数据库结构一一映射,它是数据持久化过程中的数据载体。领域对象(DomainObject,DC),微服务运行时核心业务对象的载体,DO一般包括实体或值对象。数据传输对象(DataTransferObject,DTO),用于前端应用与微服务应用层或者微服务之间的数据组装和传输,是应用之间数据
7、传输的载体。视图对象(ViewObject,V0),用于封装展示层指定页面或组件的数据。微服务基础层的主要数据对象是P0。在设计时,我们需要先建立DO和PO的映射关系。大多数情况下Do和Po是一一对应的。但也有DO和Po多对多的情况。在Do和Po数据转换时,需要进行数据重组。对于DO对象较多复杂的数据转换操作,你可以在聚合用工厂模式来实现。当Do数据需要持久化时,先将DO转换为PO对象,由仓储实现服务完成数据库持久化操作。当Do需要构建和数据初始化时,仓储实现服务先从数据库获取PO对象,将PO转换为DO后,完成Do数据构建和初始化。领域层主要是Do对象。Do是实体和值对象的数据和业务行为载体,
8、承载着基础的核心业务逻辑,多个依赖紧密的DO对象构成聚合。领域层DO对象在持久化时需要转换为PO对象。应用层主要对象有Do对象,但也可能会有DTO对象。应用层在进行不同聚合的领域服务编排时,一般建议采用聚合根ID的引用方式,应尽量避免不同聚合之间的Do对象直接引用,避免聚合之间产生依赖。在涉及跨微服务的应用服务调用时,在调用其他微服务的应用服务前,DO会被转换为DT0,完成跨微服务的DTO数据组装,因此会有DTO对象。在前端调用后端应用服务时,用户接口层先完成DTO到DO的转换,然后DO作为应用服务的参数,传导到领域层完成业务逻辑处理。用户接口层主要完成DO和DTO的互转,完成微服务与前端应用
9、数据交互和转换。facade接口服务在完成后端应用服务封装后,会对多个DO对象进行组装,转换为DTO对象,向前端应用完成数据转换和传输。facade接口服务在接收到前端应用传入的DTO后,完成DTO向多个DO对象的转换,调用后端应用服务完成业务逻辑处理。前端应用主要是Vo对象。展现层使用VO进行界面展示,通过用户接口层与应用层采用DTO对象进行数据交互。五、领域分类在研究和解决业务问题时,DDD会按照一定的规则将业务领域进行细分,当领域细分到一定的程度后,DDD会将问题范围限定在特定的边界内,在这个边界内建立领域模型,进而用代码实现该领域模型,解决相应的业务问题。简言之,DDD的领域就是这个边
10、界内要解决的业务问题域。领域又可以分为多个子域,子域又包含核心域、通用域和支撑域。核心域:核心业务,决定产品和公司核心竞争力的子域。通用域:同时被多个子域使用的通用功能子域。支撑域:支持其他子域,非核心域和通用域。六、实现DDD流程实现DDD流程事件风暴领域故事分析提取领域对象(头脑风暴)(各种场景分析)口一代码落地领域对象域代码模型映先下面再讨论一下关于领域、业务、业务模型、解决方案、BC领域模型、微服务这些概念的含义和关系。初衷是我发现现在DDD领域建模以及解决方案落地过程中,常常对这些概念理解不清楚或者有歧义,导致我们不知道如何运用这些概念来落地我们的软件。先通过一个图来说明一下这些概念
11、之间的关系,如下图所示02领域、业务、业务模型领域,即问题域、问题空间,领域是一种边界、范围。所以,一个领域代表了一个问题域的边界,也可以理解为是一个业务的边界。领域边界越大,业务范围就越大,反之则相反。通常我们大家交流都比较喜欢用业务这一词,比如这块业务,那块业务,业务的边界,我是一个业务开发人员(区分于我是一个中间件开发人员)。而领域一词,相对比较抽象,不是那么容易懂。领域既然是一个边界,所以可以划分领域的大小。即领域划分,划分出来的子领域简称子域,每个子域对应个小的问题域和和小的业务;当然,不同的子域的重要性也是不同的,所以才有了核心子域、支撑子域的说法,这点显而易见。每个业务都有一个对
12、应的业务模型(注意这个业务模型不是领域模型,而是一个业务概念的模型,领域模型下面会提到),这个业务模型设计的时候,完全不需要考虑任何软件设计的思想,比如对象的抽象、继承、存储、性能,等。我们是从业务本身出发,分析业务边界范围内的各种业务概念,以及业务概念之间的关系,通常我们可以使用一个业务模型的图来表达这些业务概念以及业务概念之间的关系。那么如何得到一个业务模型呢?最常见的有名词动词形容词分析法,还有比如四色原型分析法,都可以。找一个适合自己的就行;业务模型本身非常有价值,它提炼了领域内业务的核心概念及其关系,可以帮助我们更好的理解业务本身。解决方案什么是解决方案?我们在进行DDD领域驱动设计
13、的实践时,会进行需求分析、领域划分、领域建模等工作。而我们的系统要落地,则需要有一套解决方案。例如,我们要实现一个电商平台,需要一个复杂的系统解决方案,但是如果这个解决方案过大,各模块、组件都揉在一起,那么就不利于整个系统的维护、演进、伸缩,等。所以,我们需要把解决方案拆分为一个个独立的小的解决方案;所以,我们可以发现,领域和解决方案,是两个完全不同的概念,领域代表问题空间,解决方案代表解决方案空间。解决方案该如何拆分呢?简单的回答是:看情况,凭经验。说的具体点,就是我们需要使用软件设计的各种原则、最佳实践、设计模式、非功能特性的需求,以及团队成员的情况来指导我们进行解决方案的拆分或者直接不拆
14、分,最终得出一个综合考虑后的拆分结果。所以,我们发现解决方案的拆分的维度可能有很多,没有一个单一-的在任何情况下都合理的切分维度。有时我们可能从性能的角度来拆分,有时从不同架构分开演进(如CQRS架构)的角度,有时从分开伸缩的角度,有时从切合团队组织架构的维度。但是拆分的时候,多考虑一些各个因素,才能让我们更好的进行解决方案空间的拆分。BCBC,即BOUndedContext,中文翻译为限界上下文。BC在DDD一书中首次出现,BC的理解分为两个层面:(1)Bounded,表示边界的意思;(2)Context,即上下文,我理解为是一个场景的上下文,这个场景不局限于普通的业务场景,而是各种上下文都
15、涵盖在内,是一个时空感知的概念。比如我们两个人在公司交谈时的上下文是一个上下文,但是在路上交谈时,则切换到另一个上下文了,因为交谈的地点发生了变化;所以,BC合起来理解,就是一个上下文的边界。BC有什么用呢?就是为了表达上面介绍的某个粒度的解决方案的上下文边界。那为何要强调这个边界呢?有了这个边界,我们才可以定义这个边界内的领域模型中所有对象概念的明确含义。如果没有这个上下文边界,对同一概念在不同上下文的理解,大家就会产生偏差。举个例子:商品,在商品中心的解决方案BC中,商品中心负责管理电商平台的所有商品,所以商品在商品中心BC中,是一个聚合根;但是在订单中心解决方案BC中,虽然也叫商品,但是它只是一个值对象。我们知道订单中心的订单是一个聚合,订单内聚合了多条订单明细,每个明细是一个实体,每个订单明细对应了一个商品。虽然叫做商品,但是这个商品本质上只是商品中心的商品的一部分信息,如商品ID、标题、价格,且是只读的。甚至更为常见的,叫同一个名称的对象,在不同的BC中,是属性完全不一样的不同的对象。那为何解决方案的边界要叫做BC呢对,我们可以不用叫做BC,比如你就叫做解决方案边界,也没问题。只是EriC在写作DDD这本书时,把他叫做BC,所以我们沿用了他的概念。我们主要的目的是为了用BC来表达解决方案空间的边界。BC和子域的关系?没有关系。因为它们是