软件开发项目中的关键决策:基于上下文图的策略性领域驱动开发

发表于:2011-11-01来源:infoQ作者:Alberto点击数: 标签:
软件开发项目中的关键决策:基于上下文图的策略性领域驱动开发当应用程序逐渐变得庞大和复杂后,很多面向对象建模的方法都达不到非常好的可伸缩性。上下文图是一种通用目的的技术,作为领域驱动开发大家族的一名成员,它帮助架构师和开发人员管理他们在软件开

  简介

  当应用程序逐渐变得庞大和复杂后,很多面向对象建模的方法都达不到非常好的可伸缩性。上下文图是一种通用目的的技术,作为领域驱动开发大家族的一名成员,它帮助架构师和开发人员管理他们在软件开发项目中不得不面对的形形色色的复杂性。与其他广为人知的DDD模式相比,上下文图可以应用在任何软件开发的场景中,在开发者进行策略性决策时,为他们提供一个高层视图,比如是采用全套的DDD实现,还是根据项目的特定条件进行取舍等。

  在这篇文章中,我们将探讨界限上下文,以及如何在构建上下文图时应用它们,来支持软件开发项目中的关键决策。

  多个模型共存

  领域驱动开发花了很大力气强调一件事,即维护应用程序模型的概念完整性。要做到这一点,需要很多因素:

  一种敏捷的流程,确保能从用户和领域专家那里频繁地获得反馈,

  确保有若干领域专家在场,并且与他们开展创造性的合作,

  (在应用和测试代码中)维护单一的、可共享的模型,并用通用语言精确地进行定义它,

  营造一种开放透明的环境,鼓励学习与探索。

  这些对于营造一个可以让高质量的设计繁荣发展的环境至关重要。即使是这样的环境,那些常见的DDD元素,比如实体、值对象、聚合,也会逐渐地形成一个复杂领域模型。所以,如果不对模型的概念完整性进行妥协的话,传统的DDD方法也不能盲目地应用在一个无限大的领域模型中。

  如图1所示,在DDD中,通用语言的关键责任是对模型进行完整性检查。无论是与领域专家的讨论,还是最终的实现代码,都可以通过使用相同的术语,并将领域知识清晰准确地进行定义,以此来保证团队中的每位成员可以分享都相同的领域知识和软件。

  图1. 通用语言应该是用于表达模型的唯一语言。团队中的每位成员应该对每个特定术语达成一致。这些术语不能有歧义,也不允许在不同角色间进行翻译。

  代码是表达模型的主要形式。虽然其他一些工件或许也能捕获需求或者局部设计,但是只有代码自身才会与应用程序的行为永远保持一致。不过这种看上去美妙的建模方式其实非常脆弱:如果满足了前面提到的四条要求,它能做到,但是不能被无限地扩展。真正让模型得以最大程度地扩展,并且不必牺牲其概念完整性的方法叫做“上下文”。

  了解“界限上下文”

  在领域驱动设计的世界里,“上下文”是这样定义的:

  “一个单词或一个句子所出现的环境,这个环境会反过来影响它们的含义。”

  这段定义初看起来相当含糊。它并没有直接告诉我们“上下文”的大小、形状或者其他什么特性。但是最后我们又发现这个定义其实非常准确地描述了“上下文”是什么,如果要想窥得其全貌的话,大概还需要一些具体的例子。

  示例1:术语相同,含义不同

  第一个例子很简单,它示范了在术语层面出现歧义的情况。有些词汇根据不同的使用场景,会有不同的含义。

  假设我们正在开发一个基于Web的个人金融管理程序(PFM)。该程序可能用于管理银行帐户(Account)、股票、储蓄,未来可能用于追踪预算和开销记录等等。

  在这个程序中,领域术语“帐户”可能是指不同的概念。谈论银行的时候,一个“帐户”在逻辑上其实是“金钱的容器”;于是我们自然而然地为相应的类加上“余额”、“帐户号”等属性。但是,在“Web应用程序”的上下文中,术语“帐户”会有非常不同的含义,它和用户的认证、可信度有关。如图2所示,相应的模型将是完全不同的。

  图2. 一个出现歧义的简单场景:当术语“帐户”应用在不同的上下文时,它的含义可以是完全不同的。

  这应该是我们在对应用程序建模的时候,所遇到的最简单的歧义场景了:一个术语,有两个与上下文相关的含义。这个问题的解决办法通常是在类的全名(类名或者包名)前面加一些前缀,以此来划分名字空间。但是在概念层面上,必须清楚我们在和两个上下文打交道,有时不同上下文之间的区别很大,足以防止开发人员犯错误,但有时这样的区别却非常微妙。

  不过,在类名层面上解决问题的方式并不能用在所有的情况下:在银行的领域里,术语“银行帐户”或许已经存在了,但却有不同的含义;或者领域专家坚持使用“帐户”作为术语。此时切记不要发明一个特殊的两头这种的术语,或者在专家术语和代码之间引入一个“翻译层”。否则你将不得不面对两个独立的上下文。

  绘制第一份上下文图

  当歧义真的到来的时候,我们需要一种工具来让开发团队明白,应用程序中正存在着两个不同的上下文。“歧义”是通用语言的头号大敌,我们必须铲除它。消除歧义的最好办法就是在上下文图中,将领域结构分拆在多个界限上下文中。

  图3. 包含两个领域上下文的上下文图

  按照领域驱动设计一书的描述,上下文图是用于将上下文边界变得更清晰的重要工具。其基本的想法是在白板上画出上下文的边界,然后选择性地将相关类的领域术语填写在上面。它不是一幅绘制精美的UML图:它是一个可用的工具,允许我们描绘那种模糊不清的状况,因此它自身看上去模糊不清也就不足为其了。

  示例2:概念相同,用法不同

  还有一种更加令人困惑的情况,就是底层的概念相同,但是使用的方式不同,最终导致了不同的模型。银行帐户的模型是一个BankingAccount类,如图4所示。

原文转自:http://www.ltesting.net