1. 概念

解决的是难以理解&难以维护

由Eric Evans最先提出,Eric指出,领域驱动设计是一种处理高度复杂领域的设计思想,它试图通过分离技术实现的复杂性,围绕业务概念构建领域模型,来控制业务的复杂性,解决软件难以理解难以演化的问题。团队应用DDD可以成功地开发复杂的业务软件系统,使系统在增大时仍然保持敏捷

2. 战术 & 战略设计

  • 战术设计

    • 帮助我们创建DDD模型中各个部件
  • 战略设计

    • 帮助我们理解哪些投入是最重要的,哪些既有软件资产是可以拿来重新使用的,哪些人应该被加到团队中

3. 通用语言

通用语言是团队自己创建的公用语言,团队中同时包含领域专家和软件开发人员

开发团队和领域专家一起通过 **通用语言(Ubiquitous Language)**去理解和消化领域知识,从领域知识中提取和划分为一个一个的子领域(核心子域,通用子域,支撑子域),并在子领域上建立模型,再重复以上步骤,这样周而复始,构建出一套符合当前领域的模型

  • 核心点

    • 通用语言是一个很泛的概念,它作为一种沟通工具,在开发团队内部,开发团队与领域专家之间使用。它包含了自然语言、文档和图表等内容。对通用语言中名词,动词的使用需要认真考量,因为这些名词和动词会作为后面模型的指导命名

    • 通用语言中定义的术语在一个**限界上下文(bounded context)**中不能存在二义性。同一个事物在不同的限界上下文中因为所关注的侧重点不同,所以所表达出的概念是不同的,但在同一个限界上下文中应该表示的是一个概念。比如用户在微信中的聊天场景,朋友圈以及支付场景中所有表达的概念就应该是不同的,聊天场景关注的是用户间的聊天内容,而支付场景关注的是用户的账户余额

    • 模型(Entity,值对象,Service,Aggregate root)是存在于限界上下文中的

    • 一个子域可以包含多个限界上下文

  • UML

img

4. 领域模型「Domain Model」

领域模型可以理解成是对现实世界中的对象进行高度抽象,又称为“领域对象模型”、“概念模型”、“业务实体”,它通常都具有目标对象的特征和行为,当多个领域模型结合在一起时,就可以完成各种业务逻辑,其实也是对现实世界中对象之间关联关系的一种还原

  • 模型的特点

    • 为了解决特定问题

    • 对现实世界进行模拟

    • 抽取了现实世界一部分属性

    • 同时忽略了另一部分属性

    • 多角度、多方法

    • 人造物

a. 贫血模型

贫血模型指的是领域对象只包含了对象的特征,没有对象具体的领域行为,只有对象属性设置和获取(GET/SET)方法,所有的业务逻辑都放在业务层

  • 优点: 各个层次之间松耦合,结构清晰,领域对象只是用作存放和传输的载体

  • 缺点: 只有属性没有行为的对象时没有生命力的,这样会使得业务层的逻辑十分大

b. 充血模型

充血模型是指模型中不仅包含了对象的属性,且包含了对应的领域行为,比如业务逻辑、数据持久化等操作,业务层则只是简单的调用逻辑、事务控制和权限控制等等

  • 优点: 面向对象开发,业务层简洁统一

  • 缺点: 业务逻辑划分难以明确,什么样的业务放在对象中,而什么样的业务放在业务层,模块化开发更难,业务层的人需要深入了解领域层对象的行为方法

5. 聚合的经验法则

  • 在聚合边界内保护业务规则不变性

  • 聚合要设计得小巧

  • 只能通过标识符引用其他聚合

  • 使用最终一致性更新其他聚合

6. 构造块

a. 值对象「Value Object」

  • 是对一个不变的概念整体所建立的模型,在这个模型中,值就真的只有一个值,没有唯一标识,描述领域的某个方面而本身没有概念标识的对象
    如用户领域模型中的”手机号码“

  • 不需要有标识符

  • 属性不发生变化

  • 需要改变时,直接替换

b. 实体「Entity」

  • 实体是一类对象,拥有全局唯一标识符

c. 聚合「Aggregate」

  • 聚合是一组相关领域模型的集合

  • 聚合内的领域对象有一致的生命周期

  • 聚合对内高内聚,对外低耦合,有着清晰的边界和所属关系

  • 每一个聚合都会有一个根,称之其为聚合根,只能通过聚合根来访问聚合内的对象

  • 聚合根有全局标识

  • 聚合根用来保证业务固定规则/不变性,在数据变化时必须保持的一致性规则

d. 工厂「Factory」

用来封装创建对象时的复杂逻辑,当有些细节需要隐藏,而又找不到合适的地方来隐藏它们时

  • 具体形式

    • 领域对象的工厂方法

    • 独立的工厂类

    • 工厂可以创建实体,聚合和值对象

7. 层级

Repository

  • 是一个高阶抽象

  • 在业务语言层面上描述集合持久化的概念

Domain Service

  • 用于执行领域操作和业务规则

  • 涉及领域服务相关的操作不是一个实体或者值对象

  • 提供领域方法给其他限界上下文 / 应用程序调用

  • 操作是无状态的

8. 架构的定义

  • 根据软件要解决的问题,可以对目标系统的边界进行界定

  • 可以将目标系统按某个原则进行划分,以便并行或串行的进行工作,这些切分出来的部分,有着相互沟通的机制

  • 部分之间合并成为一个整体,完成目标系统的所有工作

img

9. 好架构的特点

  • 各层应该可以独立测试

  • 各层对外隐藏内部细节

  • 业务层只使用具体技术的抽象

  • 架构不应该依赖某个外部的库或框架,不应该被框架的结构所束缚

10. 業務模型「Business Model」

業務模型包含大量有用的領域信息並且重點強調業務的根本目標

  • 9個構造塊

    • img

    • 客戶細分

      • 企業目標用戶的不同類型

        • 小众市场

        • 大众市场

        • 企业对企业

    • 价值提供

      • 一家企业为其客户提供的产品或服务
    • 渠道

      • 企业将其产品或服务交付给客户的方式
    • 客户关系

      • 企业与每个客户细分市场的关系类型
    • 营收来源

      • 企业盈利的不同方式
    • 核心资源

      • 企业最重要的资产
    • 核心活动

      • 维持企业运转的根本活动
    • 核心合作伙伴

      • 企业最重要的合作伙伴名单
    • 成本结构

      • 企业要花费的成本

11. 如何创建有效的领域模型

  • 领域模型不一定就要匹配实际真实状况

    • 实际上,不应该期望对真实情况完整建模,而是对问题域中有用的抽象概念建模
  • 只对相关的内容进行建模

    • 领域模型是为了服务正在开发的应用程序而存在的

    • 创建领域模型时,要带有选择性,不必包含所有事物

    • 要生成一个满足业务用例需求的模型,而不是试图对现实环境建模

  • 领域模型是需要被不断调整的 以便保证其可用性

    • 业务未来的用例或者变化可能会使得模型毫无用处
  • 移除语言障碍,清楚专业术语

  • 限制抽象

    • 应该仅为通用性才采用抽象,即便这样也应当避免抽象的出现

    • 将抽象重点放在合适的抽象层级

    • 对行为而非现实进行抽象

    • 尽早频繁地在代码中实现模型

    • 不要过度迷恋精美设计,需要适时地毁弃掉模型中不再有用的部分

12. 领域层

  • 将领域模型的复杂性与应用程序偶发的技术复杂性隔离开

  • 负责确保基础架构关注的是管理事务和持久化状态的问题

  • 领域层仅仅会是应用程序的一小部分

  • 領域模型表示了創建來滿足業務用例需求的問題域的概念抽象視圖,包含抽象模型的領域層不依賴任何其他事物,並且不清楚它所服務的客戶端的技術細節以及保持領域對象的數據存儲

  • 上下文映射会返回现有的状况,它可以提供技术集成方法以及有界上下文之间关系的完整视图

  • 防止损坏层会在与另一个上下文交互时为模型提供隔离,可以提供一个上下文到另一个上下文的转移来确保不损害其完整性

  • 使用共享内核模式的集成可用于有重叠且共享一个公用模型的上下文

  • 遵循DDD原则开发的软件不需要使用任何特殊的应用程序架构方式,但其架构必须支持的一项是保持领域逻辑的隔离性

13. 应用程序服务层「Application Service」

  • 在抽象化领域模型的低层次复杂性时,为应用程序公开可用的能力和操作,此处的能力是由系统必须满足的业务用例所定义的

  • 应用程序逻辑包含业务用例所需的工作流步骤

14. 限界上下文

限界上下文是显示的,充满语义的,领域模型便存在于这个边界之内

限界上下文是一个显式边界,领域模型便存在于边界之内,在边界内,通用语言中的所有术语和词组都有它们特定的含义,而模型则需要准确地反映通用语言

15. 上下文映射图

上下文映射图表现的是项目当前的状态,如果项目会在将来发生变化,可以在到时再对上下文映射图做相应的更新,关注当前的项目状态可以帮助了解现如今所处的位置,帮助决定如何走出下一步

上下文映射图不是一种企业架构,也不是系统拓扑图,它可以帮助我们从解决方案空间的角度看待问题

上下文映射图

以映射图的形式对项目做出假设可以帮助更好地分离限界上下文