三、精练
领域模型的战略精炼包括以下部分:
- 帮助所有团队成员掌握系统的总体设计以及各部分如何协调工作;
- 找到一个具有适度规模的核心模型并所它添加到通用语言中,从而促进沟通;
- 指导重构;
- 专注于模型中最有价值的那部分;指导外包、现成组件的使用及任务委派。
1、模式:Core Domain
在设计大型系统时,有非常多的组成部分——它们都很复杂而且对开发的成功也至关重要,但导致真正的业务资产——领域模型中最为精华的部分——被掩该和忽略了。
现实是我们不可能对所有设计部分都进行同等的优化,而是必须分出优先级。为了使领域模型成为有价值的资产,必须整齐地梳理出模型的真正核心,并完全根据这个核心来创建应用程序的功能。而开发人员往往对实现开发技术难点更有兴趣,这会促使开发偏离真正有价值的核心模型。
对Core Domain的选择取决于看问题的角度。例如,很多应用程序需要一个通用的货币模型,用来表示各种货币以及它们的汇率和兑换。另一方面,一个用来支持货币交易的应用程序可能需要更精细的货币模型,这个模型有可能就是Core的一部分。一个应用程序的Core Domain在另一个应用程序中可能只是通用的支持组件。尽管如此,仍然可以在一个项目中定义一个一致的Core。
由领域专家和技术能力较强的开发人员组成的联合团队是构建Core Domain的良好方案。
2、精炼的逐步提升
积极的精练方法是通过重构和重新打包显式地分离出Generic SubDomain,然后单独进行处理。在使用Cohesive Mechanism的同时,也要各持设计的通用性、易懂性和柔性,这两个方面可以结合起来。只有除去这些细枝末节,才能把Core剥离出来。
最富雄心的精炼是Abstract Core(抽象内核),它用纯粹的形式表示了最基本的概念和关系(因此,需要对模型进行全面的重新组织和重构)。
3、模式:Generic SubDomain
模型中有些部分除了增加复杂性以外并没有捕捉或传递任何专门的知识。任何外来因素都会使Core Domain难以分辨和理解。模型中的一般原则只是起到支持作用,不是我们的主要关注点,但对系统功能的实现又极为重要。
此时,可以把这些子领域的通用模型提取出来,并放到单独的Module中,同时不放任何专用的东西。这些通用的模型优先级低于Core Domain,可不分派核心开发人员来完成这些任务。并且在开发时可考虑一些现成的通用解决方案,以提高开发效率。
4、模式:Domain Vision Statement
项目开始时,模型通常并不存在,但对模型开发的需求是早就确定下来的重点。在开发阶段,我们需要解释清楚系统的价值,并不需要深入分析模型。很多项目团队会编写“愿景说明”类文档以便管理,愿景说明会展示应用程序为组织带来的具体价值。Domain Vision Statement就是模仿这类文档创建的,但它关注重点是领域模型的本质,以及如何为企业带来价值。
写一份Core Domain的简短描述以及它将会创造的,也就是“价值主张”。展示领域模型是如何实现和均衡各方利益的。描述要尽量精减,尽快写出来并随新的理解随时修改它。
Domain Vision Statement可以用作一个指南,它帮助开发团队在精炼模型和代码的过程中保持统一的方向。
5、模式:HighLighted Core
尽管团队成员可能大体是知道核心领域是什么构成的,但Core Domain中到底包含哪些元素不同的人会有不同的理解,甚至同一个人在不同的时间也会有不同的理解。若需要经常过滤模型以便识别出关键部分,则会分散精力,因此 Core Domain必须要很容易被分辨出来。
可以编写一个非常简短的文档(3~7页),用于描述Core Domain以及Core元素之间的主要交互过程。
也可以把模型的主要存储库中的Core Domain标记出来,不用特意去阐明其角色。使开发人员很容易知道什么在核心内,什么在核心外。
如果精炼文档概括了Core Domain的核心元素,那么它就可以作为一个指示器——用以指示模型改变的重要程度。
6、模式:Cohesive Mechanism
封闭机制是面向对象设计的一个基本原则。计算有时会非常复杂,使设计开始变得膨胀。因此,把概念上的Cohesive Mechanism(内聚机制)分离到一个单独的轻量级框架中。用一个Intention-Revealing Interface来暴露这个框架的功能。现在,领域中的其他元素就可以只专注于如何表达问题了,而把解决方案的复杂细节(如何做)转移给了框架。
在实践中,除非你识别出一种正式的、公开分布的算法,否则Cohesive Mechanism和Generic Subdomain的区别并不明显。在后续的重构中,如果发现一些先前未识别的模型概念会使这种机制变得更为简单,那么就可以把这种算法精炼成一得更纯粹的机制,或转换为一个Generic Subdomain。
7、通过精炼得到声明风格
8、模式:Segregated Core
9、模式:Abstract Core
我们处理大模型的方法通常是把它分解为足够小的子领域,以便能掌握它们并把它们放到一些独立的Module中。这种方法是有效的,只是太多的独立Module会使子域间的交互变得晦涩难懂,甚至更复杂。
当大量的Module间有交互时,会在Module间创建很多引用,这很大程度上抵消了划分模块带来的价值,并不会让模型变得更清晰易懂。我们不妨考虑采用横向切割的方法,利用对象的多态性忽略抽象类型实例的细节变化,从而可以解耦Module,同时精炼出一个更小、更内聚的Core Domain。
把模型中最基本的概念识别出来,并分离到不同的类、抽象或接口中。设计这个抽象模型使之能够表达出重要组件之间的大部分交互。把这个完整的抽象模型放到它自己的Module中,而专用的、详细的实现类则留在子领域定义的Module中,从而得到一个更清晰易懂的大模型。
这样在编码实现中,大部分专用的类将引用Abstract Core Module,而不是其他专用的Module。Abstract Core 提供了主要概念及其交互的简化视图。
四、大型结构
1、模式:Evolving Order
很多开发人员都亲身经历过由于设计结构混乱而产生的代价。为避免混乱,项目通过架构从各个方面对开发者进行约束。
一个没有任何规则的随意设计会产生一些无法理解整体含义且很难维护的系统。但架构中早期的设计假设又会使项目变得束手束脚,而且会极大地限制应用程序中某些特定部分的开发/设计人员的能力。很快,开发人员就会为适应结构而不得不在应用程序的开发上委曲求全,要么就是完全推翻架构而又回到没有协调的开发老路上来。
因此,应该让这种概念上的大型结构随着应用程序一起演变,甚至可以变成一种完全不同的结构风格。不要依此过分限制详细的设计和模型决策,这些决策和模型决策必须在掌握了详细知识之后才能确定。
在选择大型结构时,应侧重于整体模型的管理,而不是优化个别部分的结构。在“结构统一”和“用最自然的方式表示个别组件”之需要做出一些折中选择。
大型结构通常需要跨越Bounded Context,应该为不同Context中工作的开发团队保留一定的自由,允许他们为满足局部需要而修改模型。
当发现一种大型结构可以明显使系统来得更清晰,而又没有对模型开发施加一些不自然的约束,就应该采用这种结构。使用不合适的结构还不如不使用它,因此最好不要为了追求设计的完整性而勉强去使用一种结构,而应该找到尽可能精简的方式解决所出现的问题。要记住宁缺毋滥的原则。
2、模式:System Metaphor
软件设计往往非常抽象且难于掌握。开发人员和用户都需要一些切实可行的方式来理解系统,并共享一个整体视图。
System Metaphor(系统隐喻)是一种松散的、易于理解的大型结构,它与对象范式是协调的。由于系统隐喻只是对领域的一种类比,因此不同模型可以用近似的方式来与它关联,这使得人们能够在多个Bounded Context中使用系统隐喻,从而有助于协调各个Bounded Context之间的工作。System Metaphor是极限编程的核心实践之一,也是众所周知的大型结构,它对一些项目非常有用,而且很好的说明了总体概念。
当系统的一个具体类比正好符合团队成员对系统的想象,并且能够引导他们向着一个有用的方向进行思考时,就应该把这个类比用作一个大型结构。围绕这个隐喻来组织设计,并把它吸收到Ubiquitous Language中。System Metaphor应该即能促进系统的交流,又能指导系统的开发。它可以增加系统不同部分之间的一致性,甚至可以跨越不同的Bounded Context。但所有隐喻都不是完全精确的,因此应不断检查是否过度或不恰当,当发现它起到妨碍作用时,要随时准备放弃它。
3、模式:Responsibility Layer
如果每个对象的职责都是人为分配的,将没有统一的指导原则和一致性,也无法把领域作为一个整体来处理。为了保持大模型的一致,有必要在职责分配上实施一定的结构化控制。
一些领域内具有自然的层次结构。某些概念和活动处于其他元素形成的一个大背景下,而那些元素会因不同原因且以不同频率独立发生变化。如何充分利用这种自然结构,使它变得更清晰和有用呢?这咱自然的层次结构很容易想到把领域分层,这是最成功的架构设计模式之一。
所谓的层,就是对系统进行划分,每个层的元素都知道或能够使用在它“下面”的那些层的服务,但却不知道它“上面”的层,而且与它上面的层保持独立。这种自发的分层方式虽然使跟踪依赖性变得更容易且直观,但它对模型的理解没有多大的帮助,也不能指导建模决策。
分层模式有一种变体最适合按职责来分层,我们把这种变体称为Relaxed Layered System(松散分层系统),如果采用这种分层模式,某一层的组件可以访问任何比它低的层,而不限于只能访问直接与它相邻的下一层。
注意观察模型中的概念依赖性,以及领域中不同部分的变化频率和变化的原因。如果在领域中发现了自然的层次结构,就把它们转换为宽泛的抽象职责。这些职责应该描述系统高层目的和设计。对模型进行重构,使得每个领域对象、Aggregate和Module的职责都清晰地位于一个职责层中。

投资银行系统中的概念依赖性和切合点
4、模式:Knowledge Level
5、模式:Pluggable Component Framework
6、结构应该有一种什么样的约束
7、通过重构得到更适当的结构
五、领域驱动设计的综合运用
六、参考文档
DOMAIN-DRIVERN DESIGN
TACKLING COMPLEXITY IN THE HEART OF SOFTWARE
领域驱动设计
软件核心复杂性应对之道
【美】Eric Evans 著 赵俐 盛海艳 刘霞 等 译
2万+

被折叠的 条评论
为什么被折叠?



