[DDD读书笔记] 重构④使用分析模式和设计模式建模

585 阅读8分钟

前文回顾

上一篇介绍了该书的第三部分“通过重构来加深理解”,我们学习了INTENTION REVEALING INTERFACE,SIDE-EFFECT-FREE FUNCTION,ASSERTION和CONCEPTUAL CONTOUR等一系列模式,它们用于澄清代码意图,使得使用代码的影响变得显而易见,并且解除模型元素的耦合。

这一篇,我们继续学习该书的第三部分。

分析模式

Martin Fowler在《分析模式》一书中是这样定义分析模式的:分析模式是一种概念集合,用来表示业务建模中的常见结构。它可能只与一个领域有关,也可能跨越多个领域。

Flower提出的分析模式来自于对实践经验的总结,只要是在合适的场景下,这些分析模式就会非常实用。分析模式专注于一些最关键和最艰难的决策,并阐明了各种替代和选择方案。它们提前预测了一些后期结果,而如果单靠我们自己去发现这些结果,可能会付出高昂的代价。

我们也可以应用这些分析模式,帮助我们得到深层的模型和柔性设计。当我们可以幸运地使用一种分析模式时,它一般并不会直接满足我们的需求。但它可以为我们的研究提供有价值的线索和明确抽象的词汇。它还可以指导我们的实现,从而省去很多麻烦。我们应该把所有分析模式的知识融入到知识消化和重构的过程中,从而形成更深刻的理解,并促进开发。当使用众所周知的分析模式中的术语时,一定要注意,不管其表面形式的变化有多大,都不要改变它所表示的基本概念。

设计模式

大部分已发布的设计模式都更侧重于解决技术问题。设计模式与领域模式之间有什么区别?《设计模式》这部经典著作的作者为初学者指出了以下事实:立场不同会影响人们如何看待什么是模式以及什么不是模式。一个人所认为的模式在另一个人看来可能是基本构造块。

在《设计模式》中,有些(但并非所有)模式可用作领域模式,但在这样使用的时候,需要变换一下立场。

模式:STRATEGY

STRATEGY(策略)模式定义了一组算法,将每个算法封装起来,并使它们可以互换。STRATEGY允许算法独立于使用它的客户而变化。领域模型包含一些并非用于解决技术问题的过程,将它们包含进来是因为它们对处理问题领域具有实际的价值。当必须从多个过程中进行选择时,选择的复杂性再加上多个过程本身的复杂性会使局面失去控制。当对过程进行建模时,我们经常会发现过程有不止一种合理的实现方式,而如果把所有的可选项都写到过程的定义中,定义就会变得臃肿而复杂,而且可供我们选择的实际行为也会因为混杂在其他行为中而显得模糊不清。

image.png

我们需要把过程中的易变部分提取到模型的一个单独的“策略”对象中,将规则与它所控制的行为区分开。按照STRATEGY设计模式来实现规则或可替换的过程。策略对象的多个版本表示了完成过程的不同方式。

模式:COMPOSITE

Gamma在《设计模式》一书中这样描述:将对象组织为树来表示部分<—>整体的层次结构。利用COMPOSITE,客户可以对单独的对象和对象组合进行同样的处理。

image.png

当嵌套容器的关联性没有在模型中反映出来时,公共行为必然会在层次结构的每一层重复出现,而且嵌套也变得僵化(例如,容器通常不能包含同一层中的其他容器,而且嵌套的层数也是固定的)。客户必须通过不同的接口来处理层次结构中的不同层,尽管这些层在概念上可能没有区别。通过层次结构来递归地收集信息也变得非常复杂。

这种情况下,我看可以运用SOMPOSITE模式,定义一个把COMPOSITE的所有成员都包含在内的抽象类型。在容器上实现那些查询信息的方法时,这些方法返回由容器内容所汇总的信息。而“叶”节点则基于它们自己的值来实现这些方法。客户只需使用抽象类型,而无需区分“叶”和容器。

模式:FLYWEIGHT

FLYWEIGHT虽然是设计模式的一个典型的例子,却并不适用于领域模型。

当一个VALUE OBJECT集合(其中的值对象数目有限)被多次使用的时候(如房屋规划中电源插座的例子),那么把它们实现为FLYWEIGHT可能是有意义的。这是一个适用于VALUE OBJECT(但不适用于ENTITY)的实现选择。

重构

回到本书第三部分的主题:重构。当我们通过重构获得深层模型时,有三件事情是必须要关注的:

  1. 以领域为本;
  2. 用一种不同的方式来看待事物;
  3. 始终坚持与领域专家对话。

与传统重构观点不同的是,即使在代码看上去很整洁的时候也可能需要重构,原因是模型的语言没有与领域专家保持一致,或者新需求不能被自然地添加到模型中。

当重构发生时,修改的发起人一般需要挑选几个开发人员,必要时需要一位领域专家,一起组成一个4~5人的小组。小组会到会议室或咖啡厅进行头脑风暴,时间为半小时至一个半小时。在这个过程中,他们画一些UML草图,并试着用对象来走查场景。他们必须保证主题专家(subject matter expert)能够理解模型并认为模型有用。当发现了一些令他们满意的新思路后,他们就回去编码。

要想保证上述重构过程的效率,需要注意几个关键事项。

  1. 自主决定。可以随时组成一个小组来解决某个设计问题,问题解决之后团队就可以解散。
  2. 注意范围和休息。一般在几天内召开两三次短会就可以得到值得尝试的方案。
  3. 使用UBIQUITOUS LANGUAGE。

并不是所有的方面都需要精化设计。在模型中,只有那些对用户最重要的部分才具有较细的粒度。在这样的模型中,那些经常需要修改的地方能够保持很高的灵活性,而其他地方则相对比较简单。

持续重构渐渐被认为是一种“最佳实践”,但大部分项目团队仍然对它抱有很大的戒心。人们虽然看到了修改代码会有风险,还要花费开发时间,但却不容易看到维持一个拙劣设计也有风险,而且迁就这种设计也要付出代价。

在探索领域的过程中、在培训开发人员的过程中,以及在开发人员与领域专家进行思想交流的过程中,必须始终坚持把 “通过重构得到更深层理解” 作为这些工作的一部分。因此,当发生以下情况时,就应该进行重构了:

  • 设计没有表达出团队对领域的最新理解;
  • 重要的概念被隐藏在设计中了(而且你已经发现了把它们呈现出来的方法);
  • 发现了一个能令某个重要的设计部分变得更灵活的机会。

总结

本文介绍了分析模式和设计模式在模型设计上的应用,同时归纳了在代码重构时需要注意的地方。到这里本书第三部分就学习完了,希望本文对大家有所帮助。

系列文章