【问题标题】:What are hidden dependencies?什么是隐藏依赖?
【发布时间】:2018-03-18 21:05:40
【问题描述】:

谁能给我一个隐藏依赖的例子。我google了一下,结果如下:

"可见依赖是开发者可以从 类的接口。如果无法从类的 接口,它是一个隐藏的依赖。”

(来源 - http://tutorials.jenkov.com/ood/understanding-dependencies.html#visiblehidden

但我还是不太明白。

这是否意味着当依赖发生在函数内部时,而不是在类的开头声明的变量?还是只是创建了接口中声明的签名方法以外的函数?

【问题讨论】:

    标签: c# dependency-injection dependencies


    【解决方案1】:

    透明(具体)依赖透明依赖是通过公共构造函数设置的依赖。

    不透明(隐藏)依赖不透明依赖是不通过公共构造函数设置的依赖,因此不容易看到依赖

    这是一个例子:

    // Transparent Dependency
    public class StudentService
    {
        private IStudentRepository _studentRepository;
        public StudentService(IStudentRepository studentRepository)
        {
            _studentRepository = studentRepository;
        }
    
        public List<Student> GetStudents()
        {
            return _studentRepository.GetAllStudents();
        }
    }
    
    // Opaque Dependency
    public class StudentService
    {
        public List<Student> GetStudents()
        {
            var _studentRepository = new StudentRepository("my-db-name");
            return _studentRepository.GetAllStudents();
        }
    }
    

    Opaque Dependecies 被认为是一种反模式,this article 强调了 Opaque IoC 的问题:

    1. 为实现不透明 IoC 的组件编写测试要困难得多

    2. 透明 IoC 帮助身份类别做得“太多”

    Mark Seemann describes优雅的第二点:

    构造函数注入的一大好处是它 明显违反单一责任原则 很明显。

    与此密切相关的是Nikola's 2nd law of IoC

    任何具有超过 3 个依赖项的类都应该受到 SRP 的质疑 违规

    【讨论】:

      【解决方案2】:

      下面是隐藏依赖的例子:

      class Foo 
      {
          void doSomething() //a visible method signature
          {
              //the body of this method is an implementation detail
              //and is thus hidden
              new Bar().doSomething();
          }
      }
      

      在上面的例子中,BarFoo依赖,因为Foo 依赖于Bar 的协作。

      它是隐藏的,因为Bar 的依赖在Foo 的构造函数或Foo 的方法签名中并不显式。

      将一个类视为定义一个向协作者公开的可见合同。方法和构造函数签名是该合同的一部分。方法doSomething() 的主体是隐藏的,因为它是未在合同中公开的类的内部实现细节。我们从签名中只知道有一个名为doSomething() 的方法,其返回类型为void

      举个反例,我们可以重构类以使依赖项显化:

      class Foo 
      {
          private readonly Bar bar;
      
          Foo(Bar bar) //the constructor signature is visible
          {
              this.bar = bar;
          }
      
          void doSomething() 
          {
              bar.doSomething(); 
          }
      }
      

      在上面的示例中,Bar 被显式定义为构造函数公开签名中的依赖项。

      我们也可以这样做:

      class Foo 
      {
      
          void doSomething(Bar bar) //method signature is visible
          {
              bar.doSomething();
          }
      }  
      

      现在doSomething 方法对Bar 的依赖是可见的,因为它包含在doSomething 的方法签名中。

      【讨论】:

      • 最后一个例子是否也可以被视为依赖注入?
      猜你喜欢
      • 2023-03-08
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      • 2011-08-10
      相关资源
      最近更新 更多