如何在早期开发阶段延迟采用特定的依赖注入框架?

How to delay the adoption of a particular dependency injection framework during the early development phase?

Robert C. Martin 在他的书“干净的架构:软件结构和设计的工匠指南”中提到,一个好的架构允许延迟对细节的决定。他提到的其中之一是:

It is not necessary to adopt a dependency injection framework early in development, because the high-level policy should not care how dependencies are resolved

实现该目标的正确工作方法是什么?如果没有特定的依赖注入框架,您如何开始以有效的方式进行开发?

How can you start developing in an efficient way without a particular dependency injection framework?

简短的回答是:

Just like you did before those DI frameworks exists!

即使这些框架有很多好处,在没有它们的情况下开始以独立于框架的方式编写代码也是一个很好的主意。这解决了代码异味 immobility.

假设您要设置控制器、用例和存储库。

 +------------+         +----------+        +------------+
 | Controller |  --->   | Use Case |  --->  | Repository |
 +------------+         +----------+        +------------+  

只需使用标准构造函数和 setter。

 Repository repo = new RepositoryImpl();
 UseCase useCase = new UseCaseImpl(repo);
 Controller controller = new ControllerImpl(useCase);

注意:我不喜欢 Impl 结尾。本例只是为了区分接口和实现。

我上面显示的这段代码与 DI 框架所做的完全相同。

如果您想使用 DI 框架,您可以将上面的代码包装在 DI 框架使用的方法中。在 java spring 中,我们将调用此类方法 工厂方法 。例如

@Bean
public Controller controller(){
    Repository repo = new RepositoryImpl();
    UseCase useCase = new UseCaseImpl(repo);
    return new ControllerImpl(useCase);
}

也许 UseCase 应该是单例,因此应该放在单独的工厂方法中。

@Bean
public UseCase useCase(DataSource ds){
    Repository repo = new RepositoryImpl(ds);
    repo.setCacheEnabled(true);
    return new UseCaseImpl(repo);
}

@Bean
public Controller controller(UseCase useCase){
    ControllerImpl controller = new ControllerImpl(useCase);
    SomeConfig c = ...;
    controller.setSomeConfig(c);
    return controller;
}

要点是我示例中的控制器、用例和存储库仅说明它们需要什么,而不说明它们来自何处。将设置代码或 bootstrap 代码与其他代码分开是个好主意。