6

我正在阅读 Fowler 的重构书并看到Preserve Whole Object。一种不同的、较新的观点认为这种重构与你应该做的完全相反:干净的代码说话——不要寻找东西!.

Fowler 确实提到您应该查看是否可以将方法移动到使用大量参数的类中。我认为这将是唯一合理的选择。对于定义不明确的方法,这种重构似乎是一种创可贴。

Fowler 的源材料有点过时了。是让这种技术走上渡渡难关的普遍智慧,还是实际上存在您想要进行这种重构的情况?还是我误解了测试驱动的风格,因为这些示例处理对象构造,而不是消息发送?

4

1 回答 1

11

面向对象设计中有许多概念,例如模式、原则和实践,起初可能看起来相似或矛盾。事实上,它们中的大多数既不相似也不矛盾。使他们与众不同和一致的是他们的意图。

Preserve Whole Object重构和 The Clean Code Talks 视频中提到的Service Locator模式之间的看似矛盾发生在它们被视为相同概念时,尽管它们的意图和本质不同。

保留整个对象重构只是一种通过减少函数参数的数量来使代码更易于阅读、理解和维护的技术。另一方面,服务定位器是一种设计模式,用于使用控制反转概念管理系统中不同组件之间的依赖关系。与对系统具有局部影响的Preserve Whole Object重构技术不同,它应用于系统的一小部分(一个功能),Service Locator模式对系统具有全局影响并解决更大的体系结构问题(依赖管理)。

何时使用 Preserve Whole Object 重构?

当函数有两个或多个参数(基本上是一个对象的属性)时,请使用保留整个对象重构,因此请改为传递对象。

有一个类似的概念称为Parameter Object (aka Argument Object ) ( Introduce Parameter Object refactoring ),它指出如果你有一组参数不是一个对象的属性,但在概念上彼此相关或自然地在一起,换行他们拥有自己的类,而是传递该类的实例。它主要用于向对象发送消息时。

引用Clean Code,第 3 章:函数,函数参数,第 43 页 (Robert C. Martin):

参数对象

当一个函数似乎需要两个或三个以上的参数时,很可能其中一些参数应该被包装到它们自己的类中。例如,考虑以下两个声明之间的区别:

Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius);

通过创建对象来减少参数的数量可能看起来像是作弊,但事实并非如此。当变量组一起传递时,就像上面示例中的 x 和 y 一样,它们很可能是一个值得拥有自己名称的概念的一部分。

何时使用服务定位器模式?

当您的类具有概念上不相关的依赖项并且您不希望您的类依赖于具体实现时,请使用服务定位器模式。实际上,这是您想要使用任何依赖管理方法的时候。另一种选择是依赖注入方法,它将所有依赖项显式指定为构造函数的单独参数。而服务定位器在单个容器对象中传递所有依赖项。事实上,Service Locator模式和Preserve Whole Object正是这种相似性重构将参数组合在一个对象中,这会造成混淆。依赖管理技术主要用于对象构造。

依赖管理的两种方法各有利弊,在控制容器反转和Martin Fowler的依赖注入模式文章中进行了讨论。

何时使用两者?

有时会出现这样的情况,您的类将具有两个或多个概念上相关的依赖项,您可能希望将它们组合在一个对象中并使用Service Locator将其作为依赖项传递。因此,如您所见,这两个概念并不相互排斥。

于 2012-05-07T21:15:19.477 回答