首页 > 其他分享 >DDD-领域驱动设计

DDD-领域驱动设计

时间:2022-12-30 15:13:06浏览次数:39  
标签:聚合 对象 子域 领域 设计 驱动 上下文 DDD

一、DDD概念介绍

  2004年Eric Evans发表Domain-Driven Design–Tackling Complexity in the Heart of Software(领域驱动设计)简称Evans DDD。领域建模是一种艺术的技术,它是用来解决复杂软件快速应付变化的解决之道。

1、什么叫DDD?

  常见的软件开发方式是拿到产品需求后,直接考虑数据库中表应该如何设计,这种方式已经将设计与业务需求脱节,而更多的是直接考虑应该如何实现了,这有点本末倒置。而DDD是从领域(问题域)为出发点进行的设计方法。

  领域驱动设计的核心是“领域”,从一开始就要让团队走到正确的点上。当我们组建好了团队之后,应该从哪里开始?不是UI原型设计,不是架构设计,不是设计数据库,这些事情重要却非最高优先级。

  用正确的方法做正确的事情,运用领域驱动设计,就是要先识别问题域,进而为团队提炼达成共识的领域知识。要做到这一点,离不开团队各个角色的沟通与协作。

2、为什么要用DDD?

(1)DDD

➢核心诉求就是将业务架构映射到系统架构上,在响应业务变化调整业务架构时,也随之变化系统架构;

➢DDD与微服务相得益彰。

(2)微服务

➢追求业务层面的复用,设计出来的系统架构和业务一致;

➢在技术架构上,系统模块之间充分解耦,可以自由地选择合适的技术架构,去中心化的治理技术和数据。

3、团队中常见的问题

我们对客户需求的理解,存在三个方向的偏差:

    (1)从客户处了解到的需求,并非最终用户的需求;

    (2)若无有效的沟通方式,需求的理解偏差会导致结果大相径庭;

    (3)理解到的需求并没有揭示完整的领域知识,导致领域建模与设计出现认知障碍。

在团队交流中,每个人都可能成为“盲人摸象的演员”

4、通过可视化的交流达成共识

保持沟通与交流是实践DDD的前提:

    (1)只有频繁地沟通,才能就业务需求达成整个团队的共识;

    (2)只有良好的协作,才能有助于大家一起提炼领域知识,建立统一语言;

    (3)只有快速反馈,才能尽可能保证领域模型,与程序实现的一致。

5、统一语言

  获得统一语言就是需求分析的过程,也是团队中各个角色就系统目标、范围与具体功能达成一致的过程。

  先从需求中考虑一些业务场景,和领域专家交谈场景的过程,从中识别出一些明显的领域概念,以及它们的关联。可以用文字或图形表示每个领域概念的含义及包括的主要信息。而领域专家是指对某一业务领域精通的人,不管是什么职业,什么身份,只要对某一业务领域精通,都可以称之为领域专家。

 

 

 

6、划分边界

什么是好的设计?其包含以下两个特点:

    (1)高内聚:就是把相关的行为聚集在一起,把不相关的行为放在别处。如果你要修改某个服务的行为,最好只在一处修改。

    (2)低耦合:如果做到了服务之间的松耦合,那么修改一个服务就不需要修改另一个服务。一个松耦合的服务应该尽可能少的知道与之协作的那些服务的信息。

拆解小秘诀:

了解牛的生理构造

避开筋、腱、骨、节交错的组织

从骨节的缝隙下手

 

 

二、DDD设计步骤

1、基本概念

    (1)实体(Entity):一个由它的标识定义的对象叫做实体。通常实体具备唯一ID,能够被持久化,具有业务逻辑,对应现实世界业务对象。

    (2)值对象(Value Object):一个没有概念上标识符描述一个领域方面的对象,这些对象是用来表示临时的事物,或者可以认为值对象是实体的属性,这些属性没有特性标识但同时表达了领域中某类含义的概念。通常值对象不具有唯一ID,由对象的属性描述,可以用来传递参数或对实体进行补充描述。

    (3)服务(Service):提供的操作是它提供给使用它的客户端,并突出领域对象的关系。所有的Service只负责协调并委派业务逻辑给领域对象进行处理,其本身并真正实现业务逻辑,绝大部分的业务逻辑都由领域对象承载和实现了。Service可与多种组件进行交互,当一个领域操作被视为一个重要的领域概念,一般就作为领域服务,服务是无状态的。

    (4)聚合(Aggregate):用来定义领域对象所有权和边界的领域模式,是用来帮助简化模型对象间的关系。通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的形成。

    (5)聚合根(Aggregate Root):每个聚合都有一个根对象(聚合根实体),从外部访问只能通过这个对象。根实体对象有组成聚合所有对象的引用,但是外部对象只能引用根对象实体。只有聚合根才能使用仓储库直接查询,如果根实体被删除,聚合内部的其它对象也将被删除。

    (6)仓储(Repository):是用来管理实体的集合,仓储里面存放的对象一定是聚合,原因是domain是以聚合的概念来划分边界的;聚合作为一个整体概念,要么一起被取出来,要么一起被删除。外部访问不会单独对某个聚合内的子对象进行单独操作。因此,我们只对聚合设计仓储。

    (7)工厂(Factory):用来封装创建一个复杂对象,尤其是聚合时所需的知识,是将创建对象的细节隐藏起来。如客户传递给工厂一些简单的参数,然后工厂可以在内部创建一个复杂的领域对象,然后返回给客户。

    (8)领域事件(Domain Event):是将领域对象从对repository或service的依赖中解脱出来,避免让领域对象对这些设施产生直接依赖。领域事件的触发点在领域模型(domain model)中。就是当领域对象的业务方法需要依赖到这些对象时就发出一个事件,这个事件会被相应的对象监听到并做出处理。

 

 

2、描述需求

需求描述要点:

   (1)在对业务充分沟通和深入理解的基础上,从业务描述中提取名词,作为关键字;

   (2)对关键需求点描述的格式应尽量表述为“用户+需求场景+操作对象”,并在团队之间达成共识;

   (3)从提取出来的名词中总结实体,形成问题域;

   (4)需求描述格式不限,可以用UML提供的方法和图例进行领域模型设计、确定模型之间的关系,也可以用其他传统方式,目标是团队成员理解一致即可。

用UML方法描述需求举例:

 

 

 

3、划分领域

    (1)领域(Domain):领域就是问题域,一个领域可以拆分为多个子领域(Sub Domain)。

    (2)核心子域(Core Domain):子领域中最核心的叫核心子域,团队的核心资源应该用在核心子域上,因为它是产品成败的关键。

    (3)支撑子域(Supporting Subdomain):除了Core Domain外,其他的是支撑子域。

    (4)通用子域(Generic Subdomain):有些支撑子域比较特殊,因为它解决的是一类通用问题,这类子域我们叫做通用子域。

  通用子域对应的限界上下文,通常会跨多个子域;多个子领域有时会有相交的部分,称作共享内核,体现到代码上就是同一份代码,在多个领域模型中复用,领域示意图如下:

 

 

4、限界上下文

限界上下文划分依据:

    (1)围绕语言定义边界:利用语义相关性和功能相关性对用例归类;

    (2)与业务能力保持一致:避免限界上下文工作边界过大;

    (3)围绕团队创建上下文:从技术角度考虑重用和变化的应对、遗留系统的集成。

美团抽奖平台上下文映射如下:

 

 

 

5、战术建模

    (1)实体(Entity):当一个对象由其标识(而不是属性)区分时,这种对象称为实体;

    (2)值对象(Value Object):当一个对象用于对事务进行描述而没有唯一标识时,它被称作值对象;

    (3)聚合根(Aggregate Root):聚合是一组相关对象的集合,作为一个整体被外界访问,聚合根是这个聚合的根节点;

    (4)领域事件:领域事件是对领域内发生的活动进行的建模。

一个手绘的简易建模,如下:

 

 

 

6、用DDD写需求规格说明书

总结利用领域模型产出需求规格说明书的一般步骤:

    (1)需求的理解和描述,抽取提炼关键字;

    (2)根据需求划分出初步的领域和限界上下文,以及上下文之间的关系;

    (3)进一步分析每个上下文内部,识别出哪些是实体,哪些是值对象;

    (4)对实体、值对象进行关联和聚合,划分出聚合范畴和聚合根,进行建模;

    (5)将每个业务场景流程化,按照场景流程,使用事件编排,定义好事件上下游关系;

    (6)在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并重构。

三、推广DDD遇到的问题

1、推行DDD失败的原因

门槛高,概念多,噱头、口号,项目不配合.......

 

 

2、统一语言问题

  使用统一语言需要我们将参与讨论的客户、领域专家与开发团队拉到同一个维度空间进行讨论,若没有达成这种一致性,那就是鸡同鸭讲,毫无沟通效率,相反还可能造成误解。

举例:结算的概念

  做支付、银行、电商、供应链等行业的朋友坐在一起谈及记账、清算、结算、核算、应收应付,这些词是否是一个明确统一的含义?

 

3、代码腐化问题

  单体系统其实也可以按照上下文拆分领域,再把代码级的领域拆分为部署视角的微服务。

 

四、DDD实践案例

以下通过旅游度假的案例来讲述DDD的实践

1、业务模式理解

(1)为用户提供休闲度假的旅游产品购买和服务;

(2)为用户提供多元化旅游场景服务和自主经营旅游产品服务;

(3)为景区和旅游商家提供度假旅游产品一体化产品售卖和分销平台。

 

2、背景和知识提炼

(1)知识提炼1 :用例分析及归类整理

 

 (2)知识提炼2:场景分析及建模草稿

 

(3)初步划分领域和限界上下文

 

(4)调整领域和限界上下文

 

 (5)限界上下文迭代结论

 

 

 (6)知识提炼-总结

 

 最后再强调一次统一语言的重要性!

 

 免责声明:本账号部分分享的资料来自网络收集和整理,所有文字和图片版权归属于原作者所有,文章仅供读者学习交流使用,并请自行核实相关内容,如文章内容涉及侵权,请联系后台管理员删除。

标签:聚合,对象,子域,领域,设计,驱动,上下文,DDD
From: https://www.cnblogs.com/youdingte/p/17014914.html

相关文章

  • 《程序与算法》课程设计(论文)指导书[2022-12-30]
    《程序与算法》课程设计(论文)指导书[2022-12-30]《程序与算法》课程设计(论文)指导书一、设计目的使学生具备理论联系实际的程序设计思想,掌握数据与结构中线性表和二叉树和......
  • 【李宏毅深度学习】(task5)网络设计技巧4—Batch Normalization
    学习心得(1)当errorsurface很崎岖时(比较难train),可以把山削平——BatchNormalization(2)比如在线性回归中,加入选取房子面积和卧室个数作为特征,它们的数值可能相差400倍(如面积......
  • 【李宏毅深度学习】(task5)网络设计技巧3—Adaptive Learning Rate
    学习心得(1)AdaGrad算法在迭代过程中不断调整学习率,并让目标函数自变量中每个元素都分别拥有自己的学习率;自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。(2)RMSProp......
  • 【李宏毅深度学习】(task5)网络设计技巧1—Local Minimum和鞍点
    学习心得(1)当loss无法继续下降时,可能是因为卡在criticalpoint,但不能说是卡在localminima,因为saddlepoint也是微分为0的点(2)如果hessian矩阵的所有的特征值eigenvalue都是......
  • 基于logisim-D触发器设计四人抢答电路
    实验1:设计一个简易4人知识竞赛抢答电路,要求是:裁判掌握一个按钮,作用是给电路复位和发出抢答开始命令;4名竞赛者各掌握一个按钮,每人对应一个指示灯,在主持人发出开始抢答命......
  • 5-1 脚手架创建项目流程架构设计
    1一周导读1.1标题完成imooc-cli脚手架创建项目流程开发1.2将收获什么命令行交互方法服务端框架eggjs的应用和API开发方法eggjs集成云mongodb1.3主......
  • 嵌入式:ARM汇编语言程序设计基础教程
    汇编语言程序设计的步骤①合理地分配存储器资源,将前述的目标系统‘数据结构模型’表示到各存储器单元。②CPU寄存器数量有限,在程序中,大多数操作都要使用寄存器;并且有的操......
  • SaaS架构:中央库存系统架构设计
    近年来,越来越多的零售企业大力发展全渠道业务。在销售额增长方面,通过线上的小程序、直播、平台渠道等方式,拓展流量变现渠道;在会员增长方面,通过各种各样的互动方式,全渠......
  • 实验室装修设计施工装饰工艺工程
      实验室的装修要做到防火防潮防腐等性能,增加通风,净化,无菌等功能,达到环保安权可靠经久耐用。实验室装修的设计主要有:空间的设计,格局的设计,功能的设计,实验流程的设计,实......
  • SaaS架构:多租户系统架构设计
    一、什么是多租户?多租户技术是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。它是为共用的数......