【问题标题】:Guidelines for designing classes for dependency injection [closed]为依赖注入设计类的指南[关闭]
【发布时间】:2008-09-24 14:35:15
【问题描述】:

This question about unit testing best practices 提到为依赖注入设计类。这让我开始思考这究竟意味着什么。

刚刚开始使用控制容器的反转,我对这个问题有一些想法,所以让我把它们扔到墙上,看看有什么问题。

在我看来,一个对象可以拥有三种基本类型的依赖关系。

  1. Object Dependency - 相关类将使用的实际对象。例如 LogInFormController 中的 LogInVerifier。这些应该通过构造函数注入。如果该类的级别足够高以至于在构造函数中需要超过 4 个这些对象,请考虑将其分解或至少使用工厂模式。您还应该考虑为依赖项提供一个接口并针对该接口进行编码。
  2. 简单设置 - 例如阈值或超时时间。这些通常应该有一个默认值,并通过工厂模式的构建器进行设置。您还可以提供设置它们的构造函数重载。但是在大多数情况下,您可能不应该强迫客户端必须明确设置它。
  3. 消息对象 - 从一个类传递到另一个类的对象,接收类可能将其用于业务逻辑。一个示例是 LogInCompleRouter 类的用户对象。在这里,我发现最好不要在构造函数中指定消息,因为您必须在 IoC 容器中注册 User 实例(使其成为全局),或者在拥有 User 实例之前不实例化 LogInCompleteRouter (为此您不能使用 DI,或者至少需要对容器的显式依赖)。在这种情况下,最好仅在方法调用需要时才传入消息对象(即 LoginInCompleteRouter.Route(User u); )。

另外,我应该提一下,不是所有的东西都应该被 DI'ed,如果你有一些简单的功能可以方便地分解到一次性类中,那可能没问题现场实例化。显然这是一个判断电话;如果我发现编写一个类如

class PasswordEqualsVerifier {
  public bool Check(string input, string actual) { return input===actual;}
}

我可能不会打扰依赖注入它,只会让一个对象直接在 using 块内实例化它。推论是,如果值得为其编写单元测试,那么它可能值得注入。

那你们觉得呢?欢迎提供任何其他指南或对比意见。

【问题讨论】:

    标签: inversion-of-control


    【解决方案1】:

    重要的是尝试对接口进行编码,并让您的类接受这些接口的实例,而不是自己创建实例。显然,您可能会为此发疯,但无论单元测试还是 DI,这都是一种普遍的好习惯。

    例如,如果您有一个数据访问对象,您可能倾向于为所有 DAO 编写一个基础,如下所示:

    public class BaseDAO
    {
        public BaseDAO(String connectionURL, 
                       String driverName, 
                       String username, String password)
        {
            // use them to create a connection via JDBC, e.g.
        }
    
        protected Connection getConnection() { return connection; }
    }
    

    但是,最好将其从类中删除以支持接口

    public interface DatabaseConnection
    {
        Connection getConnection();
    }
    
    public class BaseDAO
    {
        public BaseDAO(DatabaseConnection dbConnection)
        {
            this.dbConnection = dbConnection;
        }
    
        protected Connection getConnection() { return dbConnection.getConnection(); }
    }
    

    现在,您可以提供DatabaseConnection 的多个实现。即使忽略单元测试,如果我们假设我们使用的是 JDBC,有两种方法可以获取 Connection :从容器中获取连接池,或者直接通过使用驱动程序。现在,您的 DAO 代码未与任一策略耦合。

    对于测试,您可以创建一个MockDatabaseConnection,它使用预设数据连接到一些嵌入式 JDBC 实现来测试您的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多