面向服务体系结构的领域驱动设计

【注】本文译自:https://www.thoughtworks.com/insights/blog/domain-driven-design-services-architecture
  这篇文章是关于软件设计的选择。特别是大型系统,这些系统可能会以服务端点的形式分为多个可部署的对象。我不会特别谈论服务端点设计,但是我想讨论创建多个服务应用的构思阶段。

image

  当我们面对复杂的问题时,我们通常试图理解复杂的单个部分。通过分解问题,我们将其变成为更易于理解和管理的部分。
  正如在许多产品/项目管理周期中所描述的,对于现实生活中的问题,这通常是由本能驱动的。 我们不会使用公式来了解去一个需要签证的国家需要做什么。我们知道我们需要签证才能旅行,我们慢慢掌握需要的文件文件,需要填写哪些表格以及如何填写这些表格。当我们执行其中一个步骤时,我们不会将流程的所有细节都牢记在心,而只是要做手头的任务。这与要完成的任务的大小有关。潜在的真实标准是关于时间或进度、我们的执行力、我们的认知能力及其与任务熟悉程度的关系,甚至可能是执行这些任务的物理位置( 领事馆与 Photoshop 等)。
  在软件开发领域并没有什么不同。多年来,瀑布式的配方已被应用到软件开发过程中,最终,主要是基于启发式和基于经验的评估技术(计划扑克<Planning Poker>、T - 恤尺寸<T-shirt size>)和敏捷过程。在现实生活中,我们试着不去详述整个过程,而是通过观察我们的最新表现来尝试和理解整个旅程。
  同样适用于我们针对问题建模的软件。我们开始将它们分解为不同的应用的是方便管理单个应用,以更少的依赖关系更快地开发和部署,最后带来更多的技术选择自由。我们意识到,我们无法制定出适合所有人的完整流程。我们着眼于各个部分,并认识到我们在设计模式或技术方面的集体经验,并尝试应用其中最好的选择。
  理解和解决复杂性的一个有趣的软件设计技术是领域驱动设计(DDD)。领域驱动设计提倡基于与我们的用例相关的业务现实进行建模。由于 DDD 方法现在已经过时,而且宣传水平正在下降,我们许多人都忘记了 DDD 方法确实有助于理解手头的问题,并朝着对解决方案的普遍理解来设计软件。在构建应用DDD 会以域和子域的形式讨论的问题。它将问题的独立步骤/领域描述为边界上下文,强调使用一种通用语言来讨论这些,并添加了许多技术概念,如实体、值对象和聚合根规则以支持实现。有时,这些技术规则被视为是实施 DDD 的硬障碍,但最终,人们往往会忘记重要的部分是根据业务问题组织代码工件,并使用与(1)相同的通用语言。

设计为服务应用的边界上下文

  我想谈论的架构风格与微服务非常相似。它是关于将单体应用分离为多个独立的服务应用,或者从一开始就在边界上下文(DDD概念)的帮助下单独开发它们。
  有许多资源都强调了微服务叙述中更细粒度的服务的优点。越来越多的文章、博客和其他内容是关于陷阱和在向细粒度服务过渡之前或过渡期间应该拥有的安全网的。我将尽量不重复微服务或其他支持元素的好处,这些是迁移到这样的体系结构中所需要。我不想强调结果服务的“小型”性质,而是想强调如何通过应用领域驱动的设计概念来更好地分离这些服务。
  让我们使用一个真实的示例来实现我们的想法-借记卡/信用卡获取域。这个领域可以(不幸的是,很多时候都是这样)作为一组单体应用来实现。我们拥有多个应用的唯一原因是由于不同的应用中的存在严格的技术限制(例如希望执行批处理)。

image

  我所看到的大多数成功的架构都认识到,通过数据库进行集成是一种糟糕的实践,因为它使技术应用和业务职责之间的界限变得模糊,使业务逻辑泄漏到数据库中,并通过添加更多的应用服务器来阻止水平扩展。因此,以单体应用的的服务集成的形式发展到更好的架构。
image

  现在,应用之间的界限更加清晰了。但是,您可以看到,仍然存在隐藏的数据库交互,这一次是在各个应用内部发生的。我称它们为隐藏的,因为通常一开始它们通常很难被注意到。随着时间的流逝,代码的纠缠将使原先分离的业务流程人为地关联起来,并在业务开发中引入更多的摩擦,因为这种共置托管需要联合部署单独的功能,这可能会减慢速度。
  如果您幸运地有一个领域模型来指导的话,则领域建模可帮助您识别和分离复杂的实现。如果您还没有现有应用的域模型(在大多数情况下通常是这样),则无需遍历代码以了解不同的职责,而是构建域模型并将功能映射到手边的应用可能是一个更好的方法。这既能节省时间,又能避免被细节淹没的风险。此外,如果业务与开发团队之间存在差距(这可能是域模型最初不存在的主要原因),那么讨论域模型并映射到现有应用的功能将有助于缩小这一差距。
image

  我们设计演进的下一步是将域边界分离反映到我们的架构以及边界上下文中。一个域具有多个边界上下文意味着在同一域中可以有多个服务应用运行。有了适当的域模型,潜在的分离点就更可见了,这使我们可以从潜在的更细粒度的应用中受益(诸如单独发行和版本控制的好处,具有更多功能驱动的纯服务端点的潜力等,其中大多数已经在微服务文章中进行了讨论)。尽管许多微服务讨论都围绕技术不可知论和开发规范(避免/破坏整体),但对于我们大多数人所从事的应用而言,非常有价值的一项是领域和设计方面。一旦过渡到微服务架构(借助域模型),DDD 和更细粒度的服务便可以协同工作、相互支持。
image

  这还将为团队提供一定程度的独立性,更完善的服务功能以及更分离的交互,如许多微服务文章所述.
  同样,从我们的示例信用卡付款获取域中可以看出,这并不是我们的服务可以做到的最细粒度的分离。相反,这是在我们的领域知识所指导下最有意义的分离。重点不是规模,而是业务能力。我相信这是“正确的 SOA”,正如许多圈子所说的那样。

推荐阅读更多精彩内容