zoukankan      html  css  js  c++  java
  • DDD(Domain-Driven Design) 领域驱动设计

    DDD(Domain-Driven Design) 领域驱动设计

    1. DDD(Domain-Driven Design)是什么?

    DDD是Eric Evans在2003年出版的《领域驱动设计:软件核心复杂性应对之道》(Domain-Driven Design: Tackling Complexity in the Heart
    of Software)一书中提出的具有划时代意义的重要概念。

    Domain-Driven Design 是指通过统一语言业务抽象领域划分领域建模等一系列手段来控制软件复杂度的方法论。

    DDD 的革命性在于领域驱动设计是面向对象分析的方法论,它可以利用面向对象的特性有效化解复杂性。

    2. 数据驱动和领域驱动

    2.1 数据驱动

    目前的主流开发模式是数据驱动。有了需求先建数据库表,然后编写逻辑。

    2.2 领域驱动

    领域驱动设计关心的是业务中的领域划分(战略设计)和领域模型(战术设计),其开发过程不再以数据模型为起点,而是以领域模型为出发点。

    领域模型对应的是业务实体,在程序中主要表现为类、聚合根和值对象,它更加关注业务语义的显性化表达,而不是数据的存储和数据之间的关系。这是“领域驱动设计”和“数据驱动设计”之间显著的区别。

    3. 领域驱动设计优势

    1. 统一语言

    统一语言(Ubiquitous Language)的主要思想是让应用能和业务相
    匹配,这是通过在业务与代码中的技术之间采用共同的语言达成的。

    2. 面向对象

    DDD的核心是领域模型,这一方法论可以通俗地理解为先找到业务中的领域模型,以领域模型为中心,驱动项目开发。领域模型的设计精髓在于面向对象分析、对事物的抽象能力,一个领域驱动架构师必然是一个面向对象分析的大师。

    DDD鼓励我们接触到需求后第一步就是考虑领域模型,而不是将其切割成数据和行,然后用数据库实现数据,用服务实现行为,最后造成需求的首尾分离。DDD会让你首先考虑业务语言,而不是数据。DDD强调业务抽象和面向对象编程,而不是过程式业务逻辑实现。重点不同,导致编程世界观不同。

    3. 业务语义显性化

    统一语言使得我们的核心领域概念可以无损地在代码中呈现,从而提升代码的可理解性。

    4. 分离业务逻辑和技术细节

    代码复杂度是由业务复杂度和技术复杂度共同组成的。实践DDD还有一个好处,是让我们有机会分离核心业务逻辑和技术细节,让两个维度的复杂度有机会被解开和分治。

    核心业务逻辑是整个应用的核心,最好只是简单Java类。也就是说,核心业务逻辑对技术细节没有任何依赖,依赖都是由外向内的,,即使有由内向外的依赖,也应该通过依赖倒置来反转依赖的方向。

    image

    4. 领域驱动设计核心概念

    4.1 领域实体

    面向对象编程的核心思想,也是DDD中寻找领域实体的核心思想。
    领域实体其实就是对象。

    4.2 聚合根

    聚合根(Aggregate Root)是DDD中的一个概念,是一种更大范围的封装,会把一组有相同生命周期、在业务上不可分割的实体和值对象放在一起,只有根实体可以对外暴露引用,这也是一种内聚性的表现。

    确定聚合边界要满足固定规则(Invariant),是指在数据变化时必须保持的一致性规则,具体规则如下:

    • 根实体具有全局标识,最终负责检查规定规则
    • 聚合内的实体(领域实体)具有本地标识,这些标识在Aggregate内部才是唯一的
    • 外部对象不能引用除根Entity之外的任何内部对象
    • 只有Aggregate的根Entity才能直接通过数据库查询获取,其他对象必须通过遍历关联来发现。
    • Aggegate内部的对象可以保持对其他Aggregate根的引用。
    • Aggregate边界内的任何对象在修改时,整个Aggregate的所有固定规则都必须满足。

    4.3 领域服务

    有些领域中的动作是一些动词,看上去并不属于任何对象。它们代表了领域中的一个重要的行为。当这样的行为从领域中被识别出来时,推荐的实践方式是将它声明成一个服务。其作用仅仅是为领域提供相应的功能。

    识别领域服务,主要看它是否满足以下3个特征。

    1. 服务执行的操作代表了一个领域概念,这个领域概念无法自然地隶属于一个实体或者值对象。
    2. 被执行的操作涉及领域中的其他对象。
    3. 操作是无状态的(无状态即没有保存数据)。

    4.4 领域事件

    领域事件(Domain Event)是在一个特定领域由一个用户动作触发的,是发生在过去的行为产生的事件,而这个事件是系统中的其他部分或者关联系统感兴趣的。

    1.事件命名
    事件是表示发生在过去的事情,所以在命名上推荐使用DomainName + 动词的过去式 + Event,这样可以更准确地表达业务语义。

    2.事件内容
    事件内容在计算机术语中叫作payload,有以下两种形式:
    (1)自恰(Enrichment):就是在事件的payload中尽量多放数据,这样consumer不需要回查就能处理消息,也就是自恰地处理消息。
    (2)回查(Query-Back):这种方式是只在payload放置id属性,然后consumer通过回调的形式获取更多数据。这种形式会加重系统的负载,可能会引起性能问题。

    4.5 边界上下文

    领域实体的意义是有上下文的。边界上下文(Bounded Context)的作用是限定模型的应用范围,在同一个上下文中,要保证模型在逻辑上统一,而不用考虑它是不是适用于边界之外的情况。

    那么不同上下文之间的业务实体要如何实现交互呢?
    就像关系数据库和对象之间需要ORM一样,不同上下文之间的实体也需要映射。
    在DDD中,这种机制叫作上下文映射(Context Mapping),我们可以使用防腐层(Anti-Corruption)来完成映射的工作。

    5 领域建模方法

    5.1 用例分析法

    用例分析法是进行领域建模中最简单可行的方式。步骤如下:
    1. 获取用例描述
    是一段格式化的需求文字描述。
    2. 寻找概念类
    寻找概念类就是对获取的用例描述进行语言分析,识别名词和名词短语,将其作为候选的概念类。
    3. 添加关联
    关联意味着两个模型之间存在语义联系,在用例中的表现通常为两个名词被动词连接起来。
    4. 添加属性
    我们需要区分概念类和属性(当然名词列表也会有无用的词语)。例如,对于上文抽取到的名词列表,“品名”是“商品”的属性,“iTouch”为无用的词语。

    5. 模型精化
    模型精化是可选的步骤,有时我们希望在领域模型中表达更多的信息,这时会利用一些新的手段来表达领域模型,包括泛化、组合和子域划分等。

    四色建模法

    四色建模法源于Peter Coad的Java Modeling In Color With UML一书,它是一种模型的分析和设计方法,要把所有模型分为4种类型,用4种颜色表示。

    image

    (1)业务关键时刻(Moment-Interval)
    这种对象表示那些在某个时间点存在或者会存在一段时间。这样的对象往往表示了一次外界的请求,比如一次询价(Quotation)、一次下单(Order)或者一次租赁(Rental)。Moment-Interval是最重要的一类对象,是系统的价值所在,一般用粉红色来表示。这样的对象一般有一个起始时间和终止时间,以及一个唯一的标识号,用来唯一地标识这一次客户请求,比如OrderNo。注意,“业务关键时刻”是我给“Moment-Interval”起的中文名称,本来想直译为“时刻-时间段”,但感觉“时刻-时间段”不能体现出这种对象类型的重要性。
    (2)角色(Role)
    这种对象表示一种角色,往往由人或者物来承担,会有相应的责任和权利。一般,一个Moment-interval对象会关联多个Role。例如,一次下单涉及两个Role,分别是客户(Customer)和商品(Product)。这类对象是除Moment-interval对象之外最重要的一类对象,一般用黄色来表示。
    (3)人-事-物(Party,Place or Thing)
    这种对象往往表示一种客观存在的事物,例如人、组织、产品或者配件等。
    (4)描述(Description)
    这种对象一般是用于分类或者描述性的对象,它的属性一般是这一类事物都有的属性,一般用蓝色来表示。

    资料

    1. 《代码精进之路:从码农到工匠》

    2. COLA(整洁面向对象分层架构) 4.0

    本文来自博客园,作者:不安分的黑娃,转载请注明原文链接:https://www.cnblogs.com/lihw-study/p/15113914.html

  • 相关阅读:
    jdbc框架 commons-dbutils的使用
    SpringBoot整合Quartz和H2的例子
    Microsoft VS 2008 过期解决方法
    数据库事务的隔离级别
    angularJS中ng-if的用法
    angularJS中ng-change的用法
    Hello,Akka
    Yum常用命令及Yum中文手册
    最大堆的插入/删除/调整/排序操作(图解+程序)(JAVA)
    别人要访问我的电脑上部署的tomcat,必须关闭防火墙吗?
  • 原文地址:https://www.cnblogs.com/lihw-study/p/15113914.html
Copyright © 2011-2022 走看看