乐趣区

关于ddd:解构领域驱动设计-第一篇-读书笔记

DDD 要解决什么问题?

第一本对于 DDD 的书, 书名就是 < 畛域驱动设计 - 软件外围复杂度应答之道 >, 表明 DDD 其实就是为了应答软件复杂度的挑战.

是什么造成了软件的复杂度?

  1. 规模
  2. 构造
  3. 变动

规模

其实包含了两方面, 一方面是因为需要越来越多, 性能越来越多. 另一方面是因为性能点之间是有分割的, 牵一发而动全身, 因而规模随着业务的倒退很容易呈指数级的回升.

构造

另一方面文中提到很大水平是因为品质属性造成结构复杂. 我感觉其实还有别的方面. 咱们来剖析一下咱们设计构造的目标:

  1. 性能, 资源利用相干的. 反对横向拓展的架构, 反对分库分表的构造, 微服务进步资源利用效率. 总线转分布式通信
  2. 为了进步代码可维护性. 例如咱们设计分层架构就是为了不同档次职责拆散, 进步可读性和可拓展性
  3. 晋升沟通合作和管理效率. 例如要合乎康威定律(任何组织在设计一套零碎时, 所交付的设计方案在结构上都与该组织的沟通构造保持一致)
  4. 升高业务复杂度. 例如咱们拆分出不同的子畛域来防止认知过载.

简略的逻辑是不须要构造的, 但随着逻辑的增多, 咱们须要引入构造来升高复杂度, 构造肯定水平上也会让逻辑变得复杂, 但只有收益比老本要高, 减少构造就是正当的. 但因为对构造的误用, 或者定义不够清晰, 职责划分不同明确导致不仅没有升高复杂度, 而且还减少了复杂度.

例如咱们对性能适度思考, 为应答高性能的挑战而减少各种中间件和进行异步化革新. 又例如咱们尽管进行了分层架构的设计, 但到处都有不合乎分层准则的代码呈现. 或者咱们谬误的应用了康威定律, 导致了软件复用性大大降低, 进步了保护和拓展老本.

下面两个起因影响的其实是 理解能力 , 而变动影响的是咱们 预测能力.

变动

预测能力的有余会让咱们产生适度设计或者设计有余. 设计的实质在于如何和做取舍, 如何均衡不同条件的影响使其达到最优. 如何形象才是最正当的, 这点很大水平上依赖每个人对业务的了解和教训的积攒.

设计元模型蕴含什么

畛域驱动设计是以 畛域 作为驱动力, 应用 畛域模型 作为外围来进行设计.

为了升高规模, 畛域又能够拆分成 子畛域 . 为了让资源失去最无效的利用, 子畛域能够分为 外围子畛域 , 撑持子畛域 , 通用子畛域, 依附不同类型的子畛域来正当分配资源.

应用 限界上下文 来确定业务能力的自治边界. 通过 上下文映射 来表白限界上下文的协作关系.

通过 分层架构 将畛域独立进去, 隔离技术复杂度和业务复杂度.

通过了 领域专家 进行沟通, 在 对立语言 的领导下获取到畛域模型.

畛域模型蕴含了 实体 , 值对象 , 畛域服务 畛域事件. 畛域逻辑都会封装到这些对象中.

聚合 是最小的业务单元, 能够封装多个 实体 或者 值对象, 并维持边界范畴内业务完整性.

工厂 仓储 负责聚合的生命周期治理.

问题空间和解空间

软件世界能够一分为二, 一边是问题空间, 蕴含了用户的痛点, 爽点, 痒点, 是用户的问题, 是软件的外围价值. 另一边是解空间, 蕴含了对问题的解决方案和具体实现.

软件系统的构建实则是对问题空间的求解, 以取得形成解空间的设计方案.

咱们只有明确了用户的问题是什么, 能力找到最合适的解决方案.

用户可能会说, 在订单提交后, 我要批改订单的性能. 其实批改订单是一个解决方案, 属于解空间的内容. 那用户的问题是什么呢? 用户是放心不小心点错了. 
那依据这个问题咱们能够有十分多的解决方案, 例如提交订单前后商品列表的确认. 提交按钮设计得更正当一些. 减少勾销订单的入口让用户从新提交订单等等, 在老本和体验之间抉择一个平衡点, 让本人有更多的抉择.

解空间的解决方案不仅要解决问题

  1. 管制软件系统的复杂度.
  2. 晋升复用能力. 如果问题具备相似性, 解决方案就有复用的可能. 通过形象寻找到不同问题的共性时, 雷同的解决方案也能够使用到不同的问题.
  3. 能够响应问题的变动.

其实从不同的视角剖析进去的需要是不同的, 解决方案也是不同

技术视角和用户视角

例如当初有个需要, 心愿在应用微服务背景下, 服务的拆分和整合不影响 API. 因为当初是不同服务提供不同 API 前缀来进行匹配, 因而须要进行网关来解决这个问题.

技术视角 -> 计划级需要

技术视角的思路寻找业界的网关计划, 依据网关的通用维度, 例如性能, 性能, 可拓展性, 成熟度, 社区活跃度等进行剖析, 抉择一个各方面都比拟全面, 能满足需要的计划.

用户视角 -> 问题级需要

用户视角的思路是明确以后问题是什么, 心愿将来达到的状态是什么. 而后抉择一个最匹配最合适的计划.

计划级需要的长处是效率高, 能够利用的场景会绝对广一些. 但毛病是不够精准的解决问题.

例如依照技术视角抉择的计划尽管能解决我的问题, 但也可能是间接解决的, 例如我是想解决服务拆分整合导致 API 变动问题, 如果 API 能主动注册, 对用户无感天然是最好的, 但大部分的网关计划只提供了配置的性能而非主动配置, 尽管也能解决问题, 但不是特地敌对.
又例如抉择的网关的性能的确很弱小, 但很多其实我的项目外面用不上, 这样其实也会让网关更加简单, 晋升了保护的难度.

策略设计和战术设计

策略设计管制和合成了战术设计的边界和粒度, 战术设计则以实证角度验证畛域模型的有效性, 完整性和一致性, 进而以迭代的形式别离实现对限界上下文与畛域模型的更新与演进, 各自造成设计过程的闭环.

策略设计

  1. 对问题空间进行正当合成, 辨认不同的畛域, 确定子畛域的指标, 边界和建模策略
  2. 对问题空间进行解决方案的架构映射. 划分上下文.

战术设计

应用模型驱动设计, 次要是构建三种模型

  1. 畛域分析模型
  2. 畛域设计模型
  3. 畛域实现模型

业务复杂度和技术复杂度

软件的复杂度也能够分为业务复杂度和技术复杂度

业务复杂度: 例如电商外面优惠卷, 蕴含了各种规定的优惠卷, 满 100 元减 10 元, 2 件减 10 元, 2 件 8 折等等, 也有时效性, 笼罩的商品, 笼罩的人群等等逻辑. 要把这些规定逻辑理清原本就很简单, 这就是业务的复杂度.

技术复杂度: 为了应答品质属性, 例如为了应答三高, 高并发, 高可用, 高性能, 咱们会引入很多中间件, 为了划分弹性边界而引入微服务. 这些就是技术复杂度.

现实状况下, 咱们应该保障业务规定与技术实现是正交的.

图很活泼, 在一个容器外面退出了业务复杂度和技术复杂度两种易燃气体, 会让容器外部变得更加不稳固, 简略的逻辑变更, 人员变更很容易成为引爆点, 导致发生爆炸.

畛域模型

畛域模型富含畛域常识, 蕴含了业务概念, 业务规定, 和业务概念之间的关系.

模型是封装, 实现了对业务逻辑的暗藏; 模型是形象, 提取了畛域常识的独特特色, 放弃了面对变动时良好拓展的可能性.

模型是面向畛域常识的, 而非技术实现, 应该对领域建模和技术实现进行关注点拆散, 保障畛域模型的纯正性.

畛域模型不是实现后就能够束之高阁的, 畛域模型的构建有 3 个阶段: 建设畛域模型 -> 重构畛域模型 -> 精炼畛域模型

DDD 如何控制软件复杂度

  1. 规模: 通过分而治之拆分畛域, 而后依据业务能力, 划分出不同的独立自治的限界上下文. 分而治之的过程首先是自顶向下继续合成的过程, 而后又是自底向上进行整合的过程.
  2. 构造: 需要分为业务需要和品质需要, 通过分层架构隔离业务复杂度和技术复杂度. 现实状况下, 咱们应该保障业务规定与技术实现是正交的, 防止业务复杂度和技术复杂度相互影响.
  3. 变动. 畛域模型不仅封装了畛域常识, 而且还进行了适当的形象来进步拓展性. 至于形象是否正当应该联合业务进行剖析, 须要对业务的倒退有肯定的洞察, 能力设计出拓展性较强的畛域模型.

畛域驱动设计对立过程

DDD 具备很强的生命力和开放性, 只有不违反它的外围准则, 能够依据一些最佳实际拓展 DDD 的方法论. 例如 CQRS, 事件风暴, 测试驱动开发等等. 张逸老师提出了畛域驱动设计对立过程, 并对每个过程进行了粗疏的形容, 交融了很多工具和方法论, 具备十分很强的指导性. 后续几个大的篇章都是围绕着这个统计过程进行阐述.

DDD 的有余:

  1. 不足标准的对立过程. 书中甚至把战术模式放到后面, 让人认为没有策略设计也能够进入战术设计.
  2. 不足与之匹配的需要分析方法. 尽管从书中能够意识到不足好的需要分析方法会导致无奈建设一个适合的模型, 但书中并没有指出有什么适合的需要分析方法.
  3. 不足规范化, 具备指导意义的架构体系. 4 层架构过于形象, 无奈满足突飞猛进的技术倒退. 例如用一个基础设施层囊括了所有的中间件, 第三方服务等等.
  4. 不足固有的领导办法. 没明确哪些时候应该做什么, 应该输入什么, 参加的角色是什么.

对立过程分为 3 个间断的阶段

  1. 全局分析阶段: 指标是摸索和剖析问题空间. 蕴含了对指标零碎执行价值需要剖析与业务剖析.
  2. 架构映射阶段: 别离从组织级, 业务级, 零碎级 3 个层面对问题空间进行求解, 实现从问题空间到解空间的架构映射
  3. 领域建模阶段: 就是对问题空间求解的过程, 指标就是建设畛域模型. 畛域模型分为分析模型, 设计模型, 实现模型.

横坐标是对立过程的不同阶段, 每个阶段的关注点会有所不同.
纵坐标是工作流, 也就是工作的内容, 蕴含了输出项, 工具和办法和输入项.

对立过程的工作流分为过程工作流和撑持工作流. 每个工作流都可能会贯通多个阶段, 只是在不同阶段的侧重点可能会不同.

全局分析阶段

  • 价值需要剖析: 明确愿景, 辨认相干方, 识别系统范畴, 明确指标零碎以后的状态和预期的将来状态.
  • 业务需要剖析: 依据不同的业务流程或者价值链, 通过划分不同阶段的场景, 剖析不同的业务能力, 进而划分出不同的子畛域, 并辨认子畛域是属于外围还是撑持还是通用.

架构映射阶段

  • 组织级映射: 是站在组织的角度, 较为宏观的剖析指标零碎与内部零碎的关系.
  • 业务级映射: 依据语义相关性和性能相关性对业务服务表白的业务知识进行归类, 辨认出边界较为正当的限界上下文. 不同的上下文通过上下文映射来表白协作关系.
  • 零碎级映射: 针对单个限界上下文, 建设零碎分层架构. (可能了解有误, 埋个坑, 等后续看完再来更正)

领域建模阶段

  • 畛域剖析建模: 辨认业务概念和业务规定, 造成畛域模型概念图. 分析模型是一个很好的沟通工具, 咱们能够通过分析模型和团队成员, 例如产品, 测试等进行沟通, 并在根底上造成对立语言, 领导分析模型的设计.
  • 畛域设计建模: 辨认聚合, 并辨认聚合内的值对象和实体, 造成以聚合为外围的动态类图. 次要是开发人员依据多个不同维度, 例如业务复杂度, 拓展性, 性能等等去剖析聚合的抉择和粒度是否正当.
  • 畛域实现建模: 代码实现. 须要和分析模型, 设计模型, 畛域模型保持一致. 通过分层架构隔离业务和技术复杂度, 让代码也能很好的表白业务逻辑.
退出移动版