具有许多类(C++)的程序中的依赖性反转

dependency inversion in programs with many classes (C++)

本文关键字:程序 依赖性 许多类 C++      更新时间:2023-10-16

我正在尝试将一些旧的C++代码转换为更可测试的形式。为了符合依赖反转原则(DIP),我在许多情况下都会使用依赖注入。

我的问题是如何最好地实例化具体的类。在这段代码中有大约100个我自己的类。Robert Martin在他的著作《清洁建筑》中认为,这些类是不稳定的,应该在工厂中实例化。然而(见本书第90页),这将需要每个类4个类,我想实例化。这意味着要上400节课。

为了便于说明,假设旧代码有一个类a(实例化并使用类A1到A5)、B(B1到B10)和C(类C1到C3)。

在新代码中,您建议如何以及在哪里实例化所有具体类?我特别想听听那些在大型C++程序中处理过这类问题的人的意见。谢谢

Bruce

在应用依赖反转原则时,我们将协作组件的图(也称为对象图)的构建延迟到最后一个负责任的时刻。由于我们希望最小化组件甚至单个库之间的耦合,因此我们将这些对象图的构建转移到系统中最易失的部分。这是启动组件。启动程序集中负责组成和构造这些对象图的部分通常被称为组成根。

在新代码中,您建议如何以及在哪里实例化所有具体类?

您应该在CompositionRoot中构造所有具体的组件(包含应用程序有趣行为的类)。

在一些托管环境中,如Java和.NET,API的可用性使我们能够在运行时查询应用程序的元数据(也称为反射),允许在编译时声明抽象和实现之间的关系,并允许在运行时使用通常称为DI Containers的可重用库动态构建组件。

C++可能没有在运行时查询元数据的能力。在这样的环境中,您使用Pure DI,这简单地意味着:您在Composition Root中手动new您的类。

请注意,在我的描述中,我没有使用";工厂";。需要指定返回其他应用程序抽象的工厂抽象不应该是规范,而应该是例外。您可能会将CompositionRoot视为一个大工厂,但应用程序中没有任何内容依赖于CompositionRoot。另一方面,复合根取决于一切。

因此,您的应用程序类几乎不需要依赖于工厂抽象。如果一个类需要不同的服务,它应该直接将其注入到其构造函数中,而不是注入一个可以解析该服务的工厂。