3

我最终得到了一个看起来像这样的构造函数,同时试图得到一个我可以轻松测试的对象。

 public UserProvider(
            IFactory<IContainer> containerFactory,
            IRepositoryFactory<IUserRepository> userRepositoryFactory,
            IFactory<IRoleProvider> roleProviderFactory,
            IFactory<IAuthenticationProvider> authenticationProviderFactory,
            IFactory<IEmailAdapter> emailAdapterFactory,
            IFactory<IGuidAdapter> guidAdapterFactory,
            IRepositoryFactory<IVehicleRepository> vehicleRepositoryFactory,
            IRepositoryFactory<IUserVehicleRepository> userVehicleRepositoryFactory,
            IFactory<IDateTimeAdapter> dateTimeAdapterFactory)

这是对象将拥有的所有依赖项,也是我拥有的最繁忙的构造函数。但是,如果有人看到这个,它真的会引起很大的 wtf 吗?

我的目标是最终得到易于测试的逻辑。虽然它需要大量的模拟,但验证我的逻辑当然很容易。但是我担心我可能会得到太多的好东西。

我很好奇这对于大多数实施 ioc 的人来说是否正常。

我可以做一些简化——比如我真的不需要为几个适配器传递工厂,因为我可以直接传递适配器,因为它没有内部状态。但我真的是在询问参数的数量。

或者更重要的是,我正在寻找我不会过火的保证;)

但是我开始得到这样的印象,即 UserProvider 类应该被分解一下——但后来我得到了更多的管道,这就是导致这种担忧的原因。

我想一个子问题是,如果我有这些顾虑,我是否应该考虑使用服务定位器模式?

4

2 回答 2

7

当使用 DI 和 SRP 的构造函数注入违规变得非常明显。这确实是一件好事,而不是 DI/IOC 的错。如果您不使用构造函数注入,则该类将具有相同的依赖项,只是不那么可见。

您可以在具体示例中做的是将一些相关的依赖项隐藏在外观后面。例如 IVehicleRepository 和 IUserVehicleRepository 可以隐藏在 IVehicle 外观后面。将 IUserRepository、IRoleProvider 和 IAuthenticationProvider 放在外观后面可能也很有意义。

于 2012-06-01T16:30:00.123 回答
3

在我看来,构造函数有很多参数。以下是我将如何处理此问题以获得良好的可测试性并减少“代码异味”。

  1. 无需传入工厂来创建类的实例,只需传入类本身即可。这会自动将您的依赖关系减半,因为 UserProvider 不会关心创建它需要的任何对象(并在必要时随后处理它们)它只会使用给它的东西而不是使用它需要创建对象的工厂它需要的实例。
  2. 从构造函数中移除你的适配器,然后在 UserProvider 中创建这些接口的实例。例如,考虑一下您需要多久更改一次格式化 guid 的方式。只要您的适配器没有很多依赖项,这仍然是可测试的。

我要说的是在可测试性和实用性之间取得良好的平衡。在实现 Ioc 时,请尝试确定您过去在可测试性方面遇到的问题,以及您在维护和更改代码时遇到的问题,因为依赖项太多。那是您将看到最大好处的地方。

于 2012-06-01T16:46:03.460 回答