不为有趣之事,何遣有涯之生
不失其所者久,死而不亡者寿

DDD领域驱动战略篇(1) 软件复杂度

DDD领域驱动战略篇(1)

前言

  • DDD可不是什么新玩意,它已经诞生十几年了,只是因为微服务流行的契机,焕发了第二春
  • DDD是一套软件工程方法(一种设计思想、一种开放的设计方法体系),微服务只是一种架构风格,二者关系主要体现在限界上下文
  • 推行DDD难的原因:1 技能门槛高;2 不经过时间推移无法彰显价值
  • DDD发展可能趋势:1 以 DDD 设计方法为基础的框架的出现,让微服务设计与领域建模变得更加容易,降低领域驱动设计的门槛;2 以函数式编程思想为基础的领域建模理念与事件驱动架构和响应式编程的结合,可能在低延迟高并发的项目中发挥作用
  • 更好进行领域驱动设计的前提就是解决团队成员协作与沟通
  • 树立属于自己的技术标签(DDD纳入个人标签规划)
  • 领域驱动设计能够带来的收获:1 使得你的设计思路能够更加清晰,设计过程更加规范;2 为你的产品建立一个核心而稳定的领域模型内核,有利于领域知识的传递与传承;3 与领域专家的合作,能够帮助团队建立一个沟通良好的团队组织,构建一致的架构体系; 4 善于处理系统架构的演进设计; 5 有助于提高团队成员的面向对象设计能力与架构设计能力; 领域驱动设计与微服务架构天生匹配,微服务可以遵循领域驱动设计的架构原则
  • DDD学习之路会很崎岖,但是怕什么真理无穷,进一寸就有一寸的欢喜

软件复杂度

领域驱动设计概览

  • 领域驱动设计是一套方法论,具有一定的开放性,可以使用用例(Use Case)、测试驱动开发(TDD)、用户故事(User Story)来帮助我们对领域建立模型;可以引入整洁架构思想及六边形架构,以帮助我们建立一个层次分明、结构清晰的系统架构;还可以引入函数式编程思想,利用纯函数与抽象代数结构的不变性以及函数的组合性来表达领域模型。
  • 领域驱动设计贯穿了整个软件开发的生命周期,包括对需求的分析、建模、架构、设计,甚至最终的编码实现,乃至对编码的测试与重构。

  • 战略设计阶段:1 确认问题域(限界上下文,核心域,子域,通用域);2 通过多种分层架构(六边型、微服务、整洁、CQRS等)隔离关注点(多种架构的原因是因为限界上下文之间物理边界分开后,架构就是针对具体某个限界上下文系统了)
  • 战术设计阶段:应对领域复杂性,识别出主要要素:值对象、实体、领域服务、领域事件、资源库、工厂、聚合、应用服务

  • 领域驱动演进的设计过程:战略设计会控制和分解战术设计的边界与粒度,战术设计则以实证角度验证领域模型的有效性、完整性与一致性,进而以演进的方式对之前的战略设计阶段进行迭代,从而形成一种螺旋式上升的迭代设计过程

深入分析软件复杂度

  • 复杂没有一个公认明确的定义,我们先从理解力(分为 Simple 与 Comlicated 两个层次)和预测能力(分为 Ordered、Complex 与 Chaotic混沌 三个层次)两个维度来分析

  • 软件系统的所谓“复杂”其实覆盖了 Complicated 与 Complex 两个方面
  • 影响理解力的因素:1 规模;2 结构;
  • 影响预测能力的因素:变化
  • 优雅的设计和拙劣的设计都会使结构变得复杂,前者是主动控制,后者是不可控制错误滋生,是技术债
  • 变化可能来自业务需求(业务和用户活动本身复杂),也可能来自质量属性(非功能性需求)
  • 软件设计者们就像走在高空钢缆的技巧挑战者,惊险地调整重心以维持行动的平衡。故而,变化之难,在于如何平衡

控制软件复杂度原则

  • 当然也是从模块、结构、变化三个主要因素去控制
  • 手段一:分而治之,控制规模

    Kiss原则,单一职责原则

  • 手段二:保持结构的清晰和一致

    整洁架构

  • 手段三:拥抱变化

    敏捷,快速迭代,可进化、可扩展、可定制

软件需求复杂性

  • 需求复杂度可以分为:技术复杂度(安全、高性能、高并发、高可用性等)和业务复杂度
  • 技术复杂度与业务复杂度并非完全独立,二者混合在一起产生的化合作用更让系统的复杂度变得不可预期,难以掌控
  • 二者变化维度、周期也不同,再加上团队规模和人员流动等因素,加剧了架构腐化和系统复杂性

  • 面临的典型问题:1 问题域庞大复杂,难以寻求解决方案(规模上问题);2 开发人员将业务逻辑的复杂度与技术实现的复杂度混淆在一起(结构上问题);3 随着需求的增长和变化,无法控制业务复杂度和技术复杂度(变化上问题)

DDD如何应对软件复杂性

隔离业务复杂度和技术复杂度
  • 确认业务逻辑和技术实现的边界,从而隔离各自的复杂度
  • 理想情况下,业务规则和技术实现应该是正交的
  • DDD通过分层架构和六边型架构来确保业务逻辑和技术实现的分离

  • 分层架构关注点分离原则:将业务逻辑关注点放在领域层,技术实现放在基础设施层

蓝色区域的内容与业务逻辑有关,灰色区域的内容与技术实现有关,二者泾渭分明,然后汇合在应用层。应用层确定了业务逻辑与技术实现的边界,通过直接依赖或者依赖注入(DI,Dependency Injection)的方式将二者结合起来

  • 六边型架构的内外分离:内部领域层为核心,技术实现以周边适配器方式出现

如果我们在领域层或应用层抽象了技术实现的接口,再通过依赖注入将控制的方向倒转,业务内核就会变得更加的稳定,不会因为技术选型或其他决策的变化而导致领域代码的修改。

数据库和缓存隔离访问例子:

注意:缓存抽象是放在应用层,实现放在基础设施层

限界上下文分而治之

上一小节中,缓存接口放在了应用层,从层次的职责来看,这样的设计是合理的,但它却使得系统的应用层变得更加臃肿,职责也变得不够单一了。这是分层架构与六边形架构的局限所在,因为这两种架构模式仅仅体现了软件系统的逻辑划分。

如果我们将缓存作为一个独立的上下文,它拥有自己的应用层、领域层、基础设置层,那么我们就可以将庞大的问题域划分为松散的耦合的多个小系统,即不同的限界上下文

XXXX外贸系统的研发中心系统问题域划分示例:

领域模型对领域知识的抽象
  • 领域模型是对业务需求的一种抽象,其表达了领域概念、领域规则以及领域概念之间的关系
  • 模型是封装,实现了对业务细节的隐藏;模型是抽象,提取了领域知识的共同特征,保留了面对变化时能够良好扩展的可能性

某项目管理系统领域模型建模示例:

未经允许不得转载:菡萏如佳人 » DDD领域驱动战略篇(1)

欢迎加入极客江湖

进入江湖关于作者