DDD战略1 领域驱动设计与软件复杂度

GitChat课程《领域驱动设计--战略篇》笔记,课程作者张逸

一.领域驱动设计(Domain Driven Design, DDD)概述

1.DDD是一种针对大型复杂系统的领域建模与分析方法
  • 改变了传统软件开发工程师针对数据库进行的建模方法
  • 将要解决的业务概念业务规则转换为软件系统中的类型以及类型的属性与行为
  • 通过合理运用面向对象的封装、继承和多态等设计要素,降低或隐藏整个系统的业务复杂性提高系统的可扩展性
2.DDD是一套方法论,建立了以领域为核心驱动力的设计体系
  • 传统面向数据的建模方法是关系数据库理论的延续,关注数据表以及数据表之间关系的设计,这种设计方法面对日渐复杂的业务逻辑缺乏灵活性与可扩展性,也无法建立可重用、可扩展的代码单元
  • DDD具备开放性,可以使用不限于DDD提出的任何一种方法完成设计。例如,
    1)使用用例(Use Case)、测试驱动开发(TDD)、用户故事(User Story)对领域建立模型
    2)使用整洁架构思想及六边形架构建立层次分明、结构清晰地系统架构
    3)使用函数式编程思想,利用纯函数与抽象代数结构不变性以及函数的组合性表达领域模型
3.DDD过程
  • DDD当然不是架构方法,也并非设计模式,而是一种思维方式,旨在加快开发处理复杂领域的软件
  • DDD是一个螺旋式的迭代设计过程,分为战略设计阶段和战术设计阶段
    分析业务需求——提炼统一语言——建立领域模型——完成程序设计及编码实现——重构
DDD过程
  • 战略设计阶段
    1)问题域:通过限界上下文(Bounded Context)和上下文映射(Context Map)对问题域进行合理的分解,识别出核心领域(Core Domain)与子领域(SubDomain),并确定领域的边界以及领域间关系
    2)架构:通过分层架构隔离关注点,将领域实现独立出来;通过六边形架构清晰地表达领域与技术基础设施的边界;通过CQRS模式分离查询场景和命令场景
  • 战术设计阶段
    1)整个软件系统被分解为多个限界上下文(或领域)后,就可以逐个进行战术设计
    2)领域驱动设计用以表示模型的主要要素包括:领域模型(值对象、实体、领域服务、领域事件)、资源库(从存放资源的位置获取、添加、删除或者修改领域对象)、工厂(负责领域对象的创建,用于封装复杂或者可能变化的创建逻辑)、聚合(封装一到多个实体与值对象,表示边界,并维持边界范围之内的业务完整性)、应用服务
战术设计诸要素之间的关系
  • 演进的DDD过程
    1)战略设计会控制和分解战术设计的边界和粒度
    2)战术设计则以实证角度验证领域模型的有效性、完整性与一致性
    3)战术设计进而以演进的方式对之前的战略设计阶段进行迭代,形成螺旋式上升的迭代设计过程
DDD螺旋式上升的迭代设计过程

二.软件复杂度

1.复杂系统
  • 由大量相互作用的部分组成的系统
  • 与整个系统相比,这些组成部分相对简单,没有中央控制,彼此之间也没有全局性通讯
  • 并且组成部分的相互作用导致了复杂行为
2.复杂系统理论
  • 理解力维度:Simple/Complicated
    影响因素:1)规模;2)结构
  • 预测能力维度:Ordered/Complex/Chaotic
    影响因素:变化(需求/第三方依赖)
3.控制软件复杂度的原则
  • KISS(Keep it Simple Stupid)原则
    1)单一职责:每个程序只做一件事情,通过添加新特性而非修改旧系统去应对新需求
    2)统一接口:每个程序的输入输出都是统一格式,A程序的输出可以直接作为B程序的输入,以支持程序之间的自由组合
  • 清晰与一致的结构
    1)整洁架构:无需依赖于任何基础设施就可以对它进行测试,只需通过边界对象发送和接收对应的数据结构即可
    2)稳定依赖原则:整洁架构遵循稳定依赖原则,不对变化或易于变化的事物形成依赖
  • 拥抱变化
    1)可进化性(Evolvability):通过划分设计单元的边界,保证边界内的单元实现细节不会影响到外部的其他设计单元,从而可以容易地替换单元内部的实现细节
    2)可扩展性(Extensibility):通过封装处理软件系统中的变化点(热点),以隔离变化、降低耦合
    3)可定制性(Customizability):通过引入元数据和使用插件模式满足定制化要求

三.DDD对软件复杂度的应对

1.需求引起的软件复杂度
  • 需求分为业务需求与质量属性需求,因此需求引起的复杂度可分为技术复杂度和业务复杂度
  • 技术复杂度
    技术的复杂度来自需求的质量属性,诸如安全、高性能、高并发、高可用等相互影响甚至矛盾的因素
  • 业务复杂度
    业务复杂度对应了客户的业务需求,业务复杂度随需求规模的增大而增加。规模扩大不仅增加产生功能的数量,还因为功能的相互依赖增大业务复杂度
  • 软件技术复杂度与业务复杂度的叠加,包括
    1)软件系统的规模方面:问题域过于庞大而复杂,使得从问题域中寻求解决方案的挑战增加
    2)软件系统的结构方面:开发人员将业务逻辑的复杂度与技术实现的复杂度混淆在一起
    3)软件系统的变化方面:随需求的增长和变化,无法控制业务复杂度和技术复杂度
2.DDD对软件复杂度的应对措施1:隔离业务复杂度与技术复杂度
  • 确定业务逻辑与技术实现的边界,从而隔离各自的复杂度
    1)理想状态下,业务规则与技术实现是正交的,无论使用何种技术,只要业务需求不变,业务规则就不会发生变化
    2)DDD通过分层架构与六边形架构隔离业务逻辑与技术实现
  • 分层架构的关注点分离
    1)领域层(Domain Layer):业务逻辑的关注点
    2)基础设施层(Infrastructure Layer):支撑业务逻辑的技术实现
    3)应用层(Application Layer):作为业务逻辑的外观,暴露能体现业务用例的应用服务接口;同时作为业务逻辑与技术实现的粘合剂,实现二者的协作
DDD分层架构
  • 六边形架构的内外分离
    应用层与领域层处于六边形架构的内核,并通过六边形边界与基础设施层隔离
DDD的六边形架构
3.DDD对软件复杂度的应对措施2:限界上下文的分而治之
  • 在通过分层架构和六边形架构对软件系统进行逻辑划分的同时,通过限界上下文垂直分割业务,将庞大的软件系统划分为多个松散耦合的小系统,从而限制了每个小系统的业务复杂度和技术复杂度
4.DDD对软件复杂度的应对措施3:领域模型对领域知识的抽象
  • 领域模型是对业务需求的抽象,表达了领域概念、领域规则以及领域概念之间的关系
  • 领域模型是对统一语言的可视化表示,减少需求沟通可能出现的歧义,简化领域逻辑

你可能感兴趣的:(DDD战略1 领域驱动设计与软件复杂度)