这个关于单元测试最佳实践的问题提到了为依赖注入设计类。这让我开始思考这究竟意味着什么。
刚刚开始使用控制容器的反转,我对这个问题有一些想法,所以让我把它们扔到墙上,看看有什么能坚持下去。
在我看来,一个对象可以拥有三种基本类型的依赖关系。
- 对象依赖性- 将由相关类使用的实际对象。例如 LogInFormController 中的 LogInVerifier。这些应该通过构造函数注入。如果该类的级别足够高以至于在构造函数中需要超过 4 个这些对象,请考虑将其分解或至少使用工厂模式。您还应该考虑为依赖项提供接口并针对该接口进行编码。
- 简单设置- 例如阈值或超时时间。这些通常应该有一个默认值,并通过工厂模式的构建器进行设置。您还可以提供设置它们的构造函数重载。但是在大多数情况下,您可能不应该强迫客户端必须明确设置它。
- 消息对象- 从一个类传递到另一个类的对象,接收类可能用于业务逻辑。一个示例是 LogInCompleRouter 类的用户对象。在这里,我发现最好不要在构造函数中指定消息,因为您必须在 IoC 容器中注册 User 实例(使其成为全局),或者在您拥有 User 实例之前不实例化 LogInCompleteRouter (为此您不能使用 DI,或者至少需要对容器的显式依赖)。在这种情况下,最好仅在方法调用需要它时才传入消息对象(即 LoginInCompleteRouter.Route(User u); )。
另外,我应该提一下,并不是所有的东西都应该 DI,如果你有一些简单的功能可以方便地分解到一次性类中,那么当场实例化可能是可以的。显然,这是一个判断电话;如果我发现编写一个类如
class PasswordEqualsVerifier {
public bool Check(string input, string actual) { return input===actual;}
}
我可能不会打扰依赖注入它,只会让一个对象直接在 using 块内实例化它。推论是,如果值得为其编写单元测试,那么它可能值得注入。
那你们怎么看?欢迎任何额外的指导方针或对比意见。