本书是Eric Evans对他自己写的《领域驱动设计-软件核心复杂性应对之道》的一本字典式的参考书,可用于快速查找《领域驱动设计》中的诸多概念及其简明解释。
其它本系列其它文章地址:
[译文]Domain Driven Design Reference(一)—— 前言
[译文]Domain Driven Design Reference(二)—— 让模型起作用
[译文]Domain Driven Design Reference(三)—— 模型驱动设计的构建模块
[译文]Domain Driven Design Reference(四)—— 柔性设计
Ⅲ.柔性设计
要让一个项目加速发展,而不是被其自身的历史包袱所拖累,需要一个能与之良好协作的设计,它会带来改变。一个柔性设计。
柔性设计是对深度建模的补充。
开发人员扮演两种角色,每种角色都必须通过设计来完成。同一个人可能扮演这两个角色,甚至可以在几分钟内来回切换,但与代码的关系却不是这样。一个角色是客户端的开发人员,他们利用设计的方式将领域对象编织到应用程序代码或其他域层代码中。柔性设计揭示了一个深层次的潜在模型,使其潜在性变得清晰。客户端开发人员可以灵活地使用一组最小松散耦合的概念来表示域中的一系列场景。设计元素以自然的方式融合在一起,其结果是可预测的,清晰的特征并且是健壮的。
同样重要的是,设计必须服从于开发人员来改变它。要做出改变,设计必须易于理解,并能表达出客户端开发人员正在使用的相同底层模型。它必须遵循该领域深层模型的概念,所以大多数变化都会在灵活点上柔性设计。其代码的影响必须透明明显,因此更改的后果将很容易预测。
• 使行为特征明显
• 降低变更成本
• 创建与之合作的软件开发人员
释意接口
如果开发人员必须考虑组件的实现才能使用它,则封装的价值就没有了。如果原始开发人员以外的人必须根据其实现来推断对象或操作的目的,新的开发者可能会推断出一个意图——操作或类只是偶然地执行。如果这不是意图的话,那么代码可能暂时有效,但设计的概念基础已经被破坏了,两个开发人员将在交叉目的下工作。
因此:
命名类名和操作名来描述它们的效果和目的,而不用参考它们做出履约的方法。这减轻了客户开发者理解内部的必要性。这些名字应符合通用语言,以便团队成员可以快速推断其含义。在创建它之前为行为编写一个测试,以强制您的思维进入客户端开发人员模式。
无副作用方法
多个规则或计算的组合的相互作用变得非常难以预测。开发人员调用一个操作必须理解它的实现以及所有委托的实现,以便预测结果。如果开发人员被迫刺破遮罩层,任何抽象接口的用处都是有限的。如果没有安全可预测的抽象,开发人员必须限制组合爆炸,对可行的丰富行为设置较低的上限。
因此:
将尽可能多的程序逻辑放入函数中,返回没有明显副作用的结果。严格地将命令(引起明显的状态改变的方法)分隔成不返回领域信息的非常简单的操作。当发现了一个符合职责的概念时,通过将复杂的逻辑转化为值对象来进一步控制副作用。
值对象的所有操作都应该是无副作用的函数。
断言
当操作的副作用只是通过实现而隐含地定义时,大量委托的设计就会成为一种混乱的因果关系。理解程序的唯一方法是通过分支路径来跟踪执行。封装的价值失去了。跟踪具体执行的必要性使抽象也失败了。
因此:
状态操作的后置条件以及类和聚合的不变性。如果断言不能直接用你的编程语言编写,请为它们编写自动单元测试。将它们写入符合项目开发过程风格的文档或图表中。
寻找具有相关概念集的模型,这些概念引导开发人员推断预期的断言,加速学习曲线并降低矛盾代码的风险。
断言定义了服务和实体修饰符的契约。
断言在聚合上定义了不变性。
孤立类
即使在同一个模块中,随着依赖性的增加,解释设计的难度也会大幅增加。这增加了理解的负担,限制了开发人员可以处理的设计复杂性。隐式概念对此负担的促进作用甚至超过了显示的引用。
低耦合是面向对象设计的基础。如果可以,一直这样做。消除图中的所有其他概念。然后类将完全独立,可以单独研究和理解。每个这样的自包含类都显着减轻了理解一个模块的负担。
闭合操作
大多数有趣的对象最终都只能做一些无法用基本元素来表示的东西。
因此: