DDD学一步写一篇--DDD开发实践流程

DDD学⼀步写⼀篇--DDD开发实践流程
深度时空>硫化床DDD⼤家讨论的⽐较多的⼀般都是DDD的思想和理论,很少有⽂章讨论具体是如何实施和落地,所以这也导致很多同学看完了Evans经典巨著后对DDD还是不知道如何去实施。这篇⽂章我们讨论下DDD的实施步骤,聊聊怎么⼀步步在项⽬中实施DDD。
在习惯了传统的数据驱动开发模式后,View、Service、dao这种三层分层模式,开发者会很⾃然的写出过程式代码,这种开发⽅式中的对象只是数据载体,⽽没有⾏为,是⼀种贫⾎对象模型。以数据为中⼼,以数据库ER图为设计驱动,分层架构在这种开发模式下可以认为是数据处理和实现的过程。
数据驱动模式业务逻辑都是写在Service中的,定义的实体模型充其量只是个数据载体,没有任何⾏为。简单的业务系统采⽤这种贫⾎模型和过程化设计是没有问题的,但在业务逻辑复杂了,业务逻辑、状态会散落到在⼤量⽅法中,原本的代码意图会渐渐不明确,我们将这种情况称为由贫⾎症引起的失忆症。玻璃房
所以才有了⽬前很多⼤⽜推崇的DDD-领域驱动开发模式,将实体模型的数据和⾏为封装在⼀起,并与现实世界业务领域中的业务对象进⾏映射。将领域业务逻辑分散到领域对象中。
在⽬前主流的微服务开发过程中,其实可以把DDD中的限界上下⽂看作⼀个微服务,这个微服务对外提供的服务是⾼内聚、低耦合的。微服务架构强调的是从业务纬度去拆分系统,⽽DDD也是同样看重业务领域。
铜管焊接DDD的核⼼诉求就是将业务架构映射到系统架构上,在响应业务变化调整业务架构时,也随之变化系统架构。⽽微服务追求业务层⾯的复⽤,设计出来的系统架构和业务⼀致;在技术架构上则系统模块之间充分解耦,可以⾃由地选择合适的技术架构,去中⼼化地治理技术和数据。
过滤减压器DDD设计流程
按照实现领域驱动设计⼀书中描述的DDD步骤主要有4步:
1. 根据业务需求划分出初步的领域和限界上下⽂,以及上下⽂之间的关系;
2. 进⼀步分析每个上下⽂内部,识别出哪些是实体,哪些是值对象;对实体、值对象进⾏关联和聚合,划分出聚合的范畴和聚合根;
3. 为聚合根设计仓储,并思考实体或值对象的创建⽅式;
4. 在⼯程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不⾜的地⽅并重构。
1. 战略建模
在拿到⼀个业务需求的时候,DDD⾸先需要进⾏战术建模,战术建模其实就是DDD的第⼀步,根据具体业务区分⼦域,搞清楚各个限界上下⽂之间的关系。
限界上下⽂之间的映射关系主要有下⾯这⼏种:
合作关系(Partnership):两个上下⽂紧密合作的关系,⼀荣俱荣,⼀损俱损。
共享内核(Shared Kernel):两个上下⽂依赖部分共享的模型。
客户⽅-供应⽅开发(Customer-Supplier Development):上下⽂之间有组织的上下游依赖。
遵奉者(Conformist):下游上下⽂只能盲⽬依赖上游上下⽂。
防腐层(Anticorruption Layer):⼀个上下⽂通过⼀些适配和转换与另⼀个上下⽂交互。
开放主机服务(Open Host Service):定义⼀种协议来让其他上下⽂来对本上下⽂进⾏访问。
发布语⾔(Published Language):通常与OHS⼀起使⽤,⽤于定义开放主机的协议。
雨水循环系统⼤泥球(Big Ball of Mud):混杂在⼀起的上下⽂关系,边界不清晰。
另谋他路(SeparateWay):两个完全没有任何联系的上下⽂。
通过绘制全局的限界上下⽂的关系,能够梳理清楚业务需求中的各个领域、⼦领域之间的关系。
2. 战术建模—细化上下⽂
战术建模很重要的⼀步就是区分出整个限界上下⽂中的实体、值对象、聚合,战术建模其实对应了Entity、ValueObject、Aggregate。我们要提炼出业务中的精华,合理的抽象为这3个概念,并且这种抽象是需随着领域⾥的概念变化⽽变化的。这3者的结合运⽤会让我们的项⽬活起来,这是DDD的核⼼。这⾥再把这3个概念重新梳理⼀下。
Entity(实体): 每个实体是唯⼀的,并且可以相当长的⼀段时间内持续地变化。我们可以对实体做多次修改,故⼀个实体对象可能和它先前的状态⼤不相同。但是,由于它们拥有相同的⾝份标识,他们依然是同⼀个实体。例如⼀件商品在电商商品上下⽂中是⼀个实体,通过商品中台唯⼀的商品id来标⽰这个实体。
ValueObject(值对象):值对象⽤于度量和描述事物,当你只关⼼某个对象的属性时,该对象便可作为⼀个值对象。实体与值对象的区别在于唯⼀的⾝份标识和可变性。当⼀个对象⽤于描述⼀个事物,但是⼜没有唯⼀标⽰,那么它就是⼀个值对象。例如商品中的商品类别,类别就没有⼀个唯⼀标⽰,通过图书、服装、3C这些值就能明确表⽰这个商品类别。
不同上下⽂领域中的实体,在当前上下⽂中需要建模为值对象,因为当前领域⽆法直接修改这些对象的内部属性。
Aggregate(聚合):聚合类是实体的升级,是由⼀组与⽣俱来就密切相关实体和值对象组合⽽成的,这整个组合的最上层实体就是聚合。聚合类建议设计成⼩聚合,可以只包含根实体,⽽不需要包含其他实体,即使⼀定要包含,可以考虑将其设计成值对象。通过唯⼀标识来引⽤其他聚合或者实体,如果是外部上下⽂中的实体,引⽤其唯⼀标识或将需要的属性构造成值对象。如果聚合类创建过于复杂可以将其的创建动作封装在⼯⼚⽅法⾥。
聚合内部多个组成对象的关系可以⽤来指导数据库建表,但是肯定会存在⼀些问题,例如最常见的问题,⼀个聚合类中有⼀个List的值对象,那么在数据库中建⽴1:N的关联需要将值对象单独建表,这时候值对象表的id就不要暴露到资源库外部,让外部不可见。
领域服务:⼀些重要的领域⾏为可以定义为领域服务,简单的原则可以认为⼀些操作不适合放在实体或值对象,那么就可以把这些领域的组合⾏为定义为领域服务,这⾥的领域服务也有点类似于我们常⽤的3层架构的service层,但是不同的是,领域服务中是不包含实体类中对实体⾃⼰操作的⾏为,实体⾃操作的⾏为都是封装在实体类内部的。⼀切领域逻辑的对外暴露都需要通过领域服务来完成。
3. 数据仓储设计
DDD的设计过程中很多同学对于数据仓储的设计存在疑问,不知道DO如何存储到数据库中,其实业务DO最后落表到数据库中也没有什么特殊的处理⽅式,主要还是将DO转成PO(持久化对象)来进⾏
数据存储,PO的结构是和存储表结构对应的,这样就将DO的业务模型保存到了技术数据库中。下⾯介绍下整个DDD中数据转换的流程:
DDD数据转换流程2
⾸先领域的开放服务通过信息传输对象(DTO)来完成与外界的数据交互;在领域内部,我们通过领域对象(DO)作为领域内部的数据和⾏为载体;在资源库内部,我们沿袭了原有的数据库持久化对象(PO)进⾏数据库资源的交互。同时,DTO与DO的转换发⽣在领域服务内,DO与PO 的转换发⽣在资源库内。
与以往的业务服务相⽐,当前的编码规范可能多造成了⼀次数据转换,但每种数据对象职责明确,数据流转更加清晰。

本文发布于:2024-09-21 20:46:21,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/155502.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:对象   领域   业务   数据   服务   实体   设计
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议