前提介绍
本章内容主要介绍了领域驱动设计的原则,这些原则应用后将有助于开发团队更好地对领域内复杂问题进行建模和实现。领域驱动设计融合了设计和开发实践,并演示了它们如何协同工作以创建更好的解决方案。好的设计可以加速开发过程,而开发过程中的反馈可以进一步优化设计。
传统的软件设计方案
传统的软件设计方案主要有两种模式:瀑布设计方法和敏捷设计方法,这两种大家应该都知道,那么为了都学习一下,所以我们暂时简单的介绍一下这两种方案。
瀑布设计方法
瀑布设计方法是软件设计的一种传统方法,这种方法存在单向流动的知识沟通,业务专家、分析人员和开发人员之间缺乏反馈信息交流,其中包含多个阶段。
- 业务专家提出需求
- 分析人员根据需求创建模型并传递给开发人员编码。
虽然该方法在过去被广泛采用并获得一定程度的成功应用,但它也有其缺点和局限性。
敏捷方法学
敏捷方法学,如极限编程(XP),是一种与瀑布方法不同的方法学。它们旨在应对预先难以确定所有需求,尤其是需求经常变化的情况。
在这种情况下,预先创建一个覆盖领域所有方面的完整模型是困难的。敏捷方法试图解决“分析瘫痪”问题,即团队成员因害怕做出设计决策而无所作为。
敏捷方法的倡导者认识到设计决策的重要性,但反对预先设计。相反,他们使用大量灵活的实现,通过由业务涉众持续参与的迭代开发和许多重构,开发团队更多地学习到了客户的领域知识,从而能够产出满足客户需要的软件。
敏捷方法学的问题和局限性
虽然敏捷方法提倡简单,但每个人都有自己的简单意义,因此存在问题和局限。此外,由于缺乏真正可见的设计原则,开发人员执行的持续重构可能会导致代码更难理解或改变。虽然瀑布方法可能导致过度工程,但对过度工程的担心可能会导致害怕做出深度、彻底的设计。
构建领域知识
以飞机飞行控制系统为例,我们可以看到领域知识是如何被构建的。在任何时刻,空中都会出现成千上万的飞机,每架飞机都按照自己的路径飞往目的地,显然要确保它们不会相撞。这时我们需要一个飞行监控系统,它能跟踪在指定区域内的所有航班,并判断这些飞机是否遵循了预定的航线。通过这个小的子集系统,我们就可以实现飞机在飞行中的全面监控。
认识和了解领域内容
在软件开发的视角下,我们应该从领域的理解入手。
在本例中,我们应该从空中交通监控开始。控制人员是领域内的专家,但他们并不是系统设计人员或者软件专家,因此不能期望他们会提供完整的问题域描述。
因此,我们需要通过与控制人员交流和分析数据来逐步了解该领域的内部结构,以此来设计和实现一个高效的空中交通监控系统。
实体模型介绍分析
控制人员和你都认同每个飞机都有一个起始机场和目的机场,因此,我们已经确定了“飞机”、“起始机场”和“目的机场”这三个需要考虑的实体,如下图所示:
飞机从某地起飞又在另一地降落,但空中发生了什么?班机会按照什么路线航行?
事实上,我们更关心的是它在航行时所发生的事情,控制人员说会给每架飞机指派一个飞行计划,飞行计划会用来描述假定的整个空中旅行。当听到“飞行计划”时,你可能会在你脑海中想到这是一个飞机在空中必须遵守的路径。
飞行计划
路线(route)
路线(route)包含了飞机航行中的一个重要概念,那就是飞机在飞行时要做的事,它们必须遵照一条路线。
很明显飞机的出发点和目标点也就是路线的开始和结束点,所以,不同于将飞机与出发点和目标点管理,看上去更自然的是将它与“路线”进行关联,然后路线再与适当的出发点和目的地关联。
当你与控制人员交流飞行器需要遵循的路线时,你会发现路线是由许多小的区间段组成的,这些区间段按照一定的顺序连接起来,形成了从起点到终点的一条曲线,这条曲线穿过了多个预定的方位点。
路线(route)
路线可以被看做是由一系列连续的方位点组成的,而以前你可能将起点和终点看作是路线的结束点,但现在你只把它们看作是整个路线中的两个方位点。尽管这种看法可能与控制人员的看法存在很大的不同,但这是必要的抽象,对于后续的工作来说是很有帮助的。这些发现为路线的计划提供了新的思路,具体的变化如下图所示:
这图中展示了另一个元素,即路线中的每个方位点实际上是在空间中的一个三维点,即具有经度、纬度和高度三个维度坐标。但当你与控制人员谈论路线时,你会发现他们并不是按照这种方式来思考的。实际上,他们将路线视为飞机航班在地球上的映射。因此,每个方位点只是地球表面上的一个点,可以用经度和纬度来表示。因此,正确的图应该是:
主要的步骤流程如下所示:
领域专家进行交流,相互交换知识
你提出问题,他们回答,从而从空中交通领域中挖掘出基础概念。这些概念可能看起来不完美,没有组织,但它们却是理解领域的基础。学习领域知识时,你应该尽可能多地向专家学习。通过正确提问和信息处理,你和专家会开始勾勒出领域的骨架模型。这种模型可能不完整,也不能保证是正确的,但它可以作为了解领域基础概念的起点。
挖掘出关键的领域概念
在软件设计中,软件架构师或开发人员需要和领域专家进行长时间的讨论。他们需要获取领域专家的知识,并将其转换为有用的形式。他们可能需要建立早期的原型,以验证系统是否按照预期工作。在交流和反馈的过程中,他们可能会发现模型或方法中的问题,并希望对其进行改进。这种交流不再是单向的,而是有着反馈的双向过程。这有助于我们更好地建立模型,从而获得更清晰、更准确的对模型的理解。领域专家掌握很多专业技能,但他们通常以特殊的方式组织和使用这些知识,这可能对将它们实现到软件系统中带来困难。
创建领域模型
通过与领域专家的交流,软件设计人员的分析思维会帮助挖掘出关键的领域概念,并创建可用于将来讨论的结构。作为软件专家和领域专家,我们一起创建领域模型,该模型反映了这两个领域的交集。虽然这个过程很耗费时间,但它必须这样做,因为软件的主要目的是解决真实领域中的业务问题,所以必须与领域完美结合。
面向人群
无论你是企业架构师、团队领导者、项目经理还是高级软件开发人员,本文章都可以帮助你正确理解领域驱动设计,并同时实现你的业务目标和技术目标。
重点决策人群:团队领导者、技术架构师、项目经理和业务架构师。
主题方向
Java、.NET、SOA、Agile、Ruby 和 Architecture。
推荐学习
《领域驱动设计——软件核心复杂性应对之道》(Addison-Wesley 2004,已由清华大学出版社翻译出版)。
领域驱动设计——软件核心复杂性应对之道
它提供了一个建模和设计技术的系统,成功的团队应用这一系统可以组装有业务需求的复杂软件系统,并使系统在增大时仍然保持敏捷。
Domain Language 是一个咨询小组,它指导和训练团队实施领域驱动设计,帮助他们使自己的开发工作对业务而言更有生产力和更有价值。
领域驱动设计建议
- 亲力亲为,模型需要代码支持。
- 专注于具体场景,将抽象思维应用到具体案例中。
- 不要试图对所有事情都进行领域驱动设计。可以画一张范围表,然后决定哪些应该进行领域驱动设计,哪些不需要。不必担心边界之外的事情。
- 不断进行实验,期望能够发现错误。模型的创造过程需要不断尝试和改进。