DDD社区权威解读:2020年之领域驱动设计 - ziobrando


DDD事件风暴发明人Alberto Brandolini文章,是DDD社区对传统DDD的发展和丰富:
从最初的提法到现在已经过去了几年,这个概念和社区也发生了很多事情。该文是经过努力的尝试,旨在向新手描述域驱动设计,从而减轻了浏览历史记录的负担。

DDD定义
领域驱动设计DDD是一种用于高复杂度高价值企业软件的软件开发方法。
它不是体系结构或方法论。这是一种更全面的方法,跨社会技术堆栈的不同层:从阅读业务需求和组织约束到良好的编码实践。
多年来,实践和工具不断发展,但大多数核心概念仍然存在。

关键特征

  • 策略已嵌入到方法中:它不是一种适用于所有方法的单一规范。
  • 专注于学习:这是交付高价值软件的主要障碍,所以让我们将其作为我们方法的核心。
  • 语言(banq注:英语等自然语言)是软件开发领域的一等公民。
  • 多个模型是不演变为泥泞球的关键。
  • 复杂的架构选择至关重要。如果您仅想到CRUD,那么您还有很长的路要走。
  • 期望良好的编码实践。没有经过严格测试的进化软件会导致自杀。


战略
并非大型系统的每个部分都需要复杂的方法。如果将DDD的许多功能应用在错误的位置,则可能会过大。但是,无论如何,检测当前的业务需求,了解形势并制定明智的策略都是一件好事。
DDD建议将重点放在核心域(即该域当前状态下的高价值部分)上,而对其他部分(如支持子域和通用子域)则退回到更保守的方法。
大图战略性事件风暴可以成为了解组织当前策略和需求并检测其当前核心的强大工具。
绘制上下文映射可以帮助解读战略上的局限性和成功项目的障碍,否则会浪费大量资金在一开始就注定要失败的项目中。(banq注:条条大路罗马,首先把罗马方向确定,在南面还是北面,否则南辕北辙)

专注于学习
DDD就是要学习领域的内在复杂性,提炼为有效软件构建模型所需的知识。在项目结束时,DDD从业人员很难与领域专家区分开。
如果学习是瓶颈,那么我们应该得出后果,并停止尝试针对可预测的交付进行优化,而是开始针对有效的学习进行优化。
Whirlpool漩涡模型是一种描述“过程”的方法,该过程不是顺序的,并且主要由可用反馈的质量决定。
在此问题空间中出现了诸如EventStorming,Domain Storytelling和Event Modeling之类的协作建模实践,从而弥补了传统需求收集无法提供的学习差距。
演进软件是我们正在努力的。高度的领域复杂性意味着我们无法一口气学习所有内容,这是由于我们对复杂领域的学习限制所致:我们可以马上理解财务吗?或因为域本身在不断发展。我们最初编写软件的尝试将是一个合理的近似值,但是我们必须重写才能使事情正确。
诸如Mob编程之类的协作编码方法在DDD空间中越来越受欢迎。

偶然的复杂性
如果学习是最难管理的资源,那么避免学习不必要的复杂性对于任何成功的团队都是至关重要的。
有界上下文有助于定位复杂性,避免了很多复杂情况,您还应该意识到...
无处不在的语言将封装本地理解,因此没有人需要记住...

专注语言
无处不在的语言是DDD中的原始概念。它描述了参与项目的每个人所讲的无歧义语言。但是,口语只能由字典部分定义。在DDD中,语言已成为确定我们实施模型质量的工具:翻译和误解是意外复杂性不断攀升的指标,而有边界上下文中无处不在的语言的出现则标志着团队学习的进展。
重构以获得更深刻的见识是一种反映团队学习到代码的方法。可读且意图公开的代码最终将成为一种使用更精确的对话语言的代码。
这种语言的形式在过去几年中不断发展:尽管最初主要是对名词进行强调,但随着时间的流逝,更复杂的事件驱动型语言出现了,领域事件是业务叙事和业务描述及其软件实施基础
领域事件在语义上比名词更精确,并且它们触发软件和组织中的反应。EventStorming再次帮助使软件语言接近于业务语言,这比数据更具说故事性。

多种模型
企业问题没有单一模型作为解决方案。在DDD中,“有界上下文”的概念捕捉到了为更好的利益而协作的多个本地专用模型的概念。
不同的模型仅出于一种目的进行了优化,并且可以在内部应用不同的范例。因此,您将拥有一个EventSourced绑定上下文,以及一个更简单/更便宜的CRUD,例如在另一个BC中的实现。
上下文映射有助于可视化所涉及的不同模型的边界和目的,而“边界上下文画布”可以很好地帮助您讨论并快速记录任何给定边界上下文的边界和目的。
通常在反腐败层的支持下,在有界上下文中执行模型分离也可以提供更安全的开发空间。共享资源通常是对健康发展的威胁。
也就是说,人们不会重命名共享数据库中的概念,也不会完全重构概念,因为他们可能担心破坏在共享持久性上运行的其他实现。一个私人的持久性支持,允许更安全的代码演变更多的机会,同时保持其中明确约定合同更安全。

架构
在早期,DDD似乎是一种体系结构。在蓝皮书中,描述了一种体系结构方法(描述了诸如聚集,实体,价值对象,存储库等的战术模式),不幸的是,它不只是那样。
真实的故事是,DDD需要强大的体系结构基础才能交付演进软件,而在Domain Model之上的一系列模式书中提出的体系结构是2004年唯一可行的选择。
现在,情况变得更加多样化,并提供了更多选择:

  • 以Domain Events作为一等公民的更复杂的OO方法,请参阅Vaughn Vernon的实现域驱动设计
  • CQRS / ES中单独或经常结合使用的命令查询职责隔离和事件来源
  • 函数式语言,请参阅Scott Wlaschin的“ 域建模使函数式化”
  • Actor模型是实现复杂的,事件驱动的域模型的另一种巧妙方法,请参阅Vaughn Vernon的Actor模型Reactive消息传递模式

...可能还会有更多。

供应商独立性
这是一个经常被忽视的价值,但绝对存在。由于DDD处理企业软件的高价值部分,因此至关重要的是,您的组织必须控制其软件资产。
核心域的实现需要独立于供应商技术,无论是框架,中间件还是数据库。您的业​​务逻辑应该随着业务的发展而发展,而不是其他任何事情。
顺便说一句,供应商独立性一直是DDD寿命的关键因素之一。没有“ DDD框架”之类的东西。SOA开始时是一套合理的原则,然后在供应商工具的重压下崩溃,变得贪婪并劫持了架构选择。

微服务
微服务社区之间存在很多融合,这是因为“绑定上下文”概念非常适合检测理想的服务粒度,并且由于“事件驱动”已成为异步实现和更好地描述业务语言的成功范例。
有关本文的更多信息。

良好的编码习惯
不断发展的代码库要求安全。只有当我们控制系统的行为时,才能实现安全。假设前提控制了我们的上下文边界(banq注:特斯拉马斯克的第一性原理,公理是定理的前提,任何真理都是有假设前提的,除了这一句,这句是一个绝对真理之外,没有其他绝对真理了。),因此,必须使用有界上下文Bounded Contexts-这个概念并且进行足够的测试以确保我们的代码库安全。
尽管不是强制性的教条-DDD并未规定100%的代码覆盖率-DDD假定具有编写高质量代码和进行高质量测试的能力。
骇客和捷径-通常不建议您使用骇客和捷径,特别是那些创建锁定到平台和工具的工具。关注点分离也是实现级别的强大驱动力。

开发运维
DevOps运动的发展很大程度上独立于DDD,但到2020年,频繁且可靠的部署将加速任何反馈周期,因此就顺其自然。
BDD:行为驱动开发是另一种软件开发方法,它试图缩小软件与业务之间的差距。不同的工具,非常相似的心态以及非常紧密的社区。
行为驱动开发强调示例的作用,以了解业务期望的真实本质,而DDD则完全同意!

总结
加入该社区15年之后,我不得不承认,我对官方定义仍然不完全满意。也许我在看错东西。
如果我真的认为2020年的领域驱动设计可能是软件开发中最有趣,最开放的社区之一,那么它可以深入讨论技术主题及其对组织文化水平的影响。开放性,好奇心,精通性和完整性使这个社区变得很酷,而领域驱动设计对于任何战略性业务软件开发项目而言都是越来越有价值的工具。

banq注:文中一个观点不敢苟同,DomainEvent领域事件是与事件驱动架构EDA、EventSourcing或Actor模型等技术实现架构无关,是有关业务领域事件,其中存在Alberto Brandolini因为人情关系的推销左右。DDD社区也是一个DDD江湖,出头早的带出头晚的,尽管晚辈后浪才是真正专家,但是后浪还是不会忘记前浪的伯乐之恩。