什么是不透明依赖项?
What are opaque dependencies?
我在阅读有关设计模式的内容时注意到 "opaque dependencies" 一词被广泛使用。
一些消息来源指出:
Opaque dependencies are the bad kind of dependencies
Opaque dependencies are the kind that you can’t assign using a class’s
public API.
但是我不是很了解。
有人可以给我一些使用这种依赖关系的例子吗?我为什么要避免使用它们?
例如:
public class MyService
{
private IRepository repo = new Repository();
public MyService()
{
repo = new Repository();
}
}
repo
将被归类为 不透明的依赖关系 因为没有(简单的)方法来改变它,例如在单元测试中。
这是同一个例子,但是作为透明依赖:
public class MyService
{
private IRepository repo = new Repository();
public MyService(IRepository repositoryDependency)
{
repo = repositoryDependency;
}
}
这里我们可以传入自己的IRepository
并测试MyService
的行为,DI Container之类的工具可以为我们设置依赖项,这是它做不到的不透明示例。
不透明的依赖项是隐藏的。不透明依赖的反面是显式依赖。
不透明的依赖关系很糟糕,因为使用 class 的开发人员可能没有意识到这种依赖关系的存在。调用各种方法时可能会出现意想不到的副作用
不透明依赖
public class Users
{
private Database database;
public Users()
{
this.database = new SqlDatabase(...);
}
public User Find(int userId)
{
return database.GetById(...);
}
}
显式依赖
public class Users
{
private Database database;
public Users(Database database)
{
this.database = database;
}
public User Find(int userId)
{
return database.GetById(...);
}
}
基于@NikolaiDante 的回答,我将添加一个论点,即不透明依赖项可以通过透明依赖项引入。
例如:
public class MyService
{
private ISomeContext context;
public MyService(ISomeContext context)
{
this.context = context;
}
public void DoSomethingUseful()
{
var repository = this.context.CreateRepository<IRepository>();
repository.Save(new X());
}
}
虽然对 ISomeContext
的依赖是透明的,但它隐藏了它用于解析 IRepository
的事实,我现在认为它是不透明的依赖。恕我直言,这减少了 class 设计的 'purity',通常有利于方便或懒惰。
'Digging into Collaborators' 部分 here 中有更多关于此类问题的内容。
我在阅读有关设计模式的内容时注意到 "opaque dependencies" 一词被广泛使用。 一些消息来源指出:
Opaque dependencies are the bad kind of dependencies
Opaque dependencies are the kind that you can’t assign using a class’s public API.
但是我不是很了解。
有人可以给我一些使用这种依赖关系的例子吗?我为什么要避免使用它们?
例如:
public class MyService
{
private IRepository repo = new Repository();
public MyService()
{
repo = new Repository();
}
}
repo
将被归类为 不透明的依赖关系 因为没有(简单的)方法来改变它,例如在单元测试中。
这是同一个例子,但是作为透明依赖:
public class MyService
{
private IRepository repo = new Repository();
public MyService(IRepository repositoryDependency)
{
repo = repositoryDependency;
}
}
这里我们可以传入自己的IRepository
并测试MyService
的行为,DI Container之类的工具可以为我们设置依赖项,这是它做不到的不透明示例。
不透明的依赖项是隐藏的。不透明依赖的反面是显式依赖。
不透明的依赖关系很糟糕,因为使用 class 的开发人员可能没有意识到这种依赖关系的存在。调用各种方法时可能会出现意想不到的副作用
不透明依赖
public class Users
{
private Database database;
public Users()
{
this.database = new SqlDatabase(...);
}
public User Find(int userId)
{
return database.GetById(...);
}
}
显式依赖
public class Users
{
private Database database;
public Users(Database database)
{
this.database = database;
}
public User Find(int userId)
{
return database.GetById(...);
}
}
基于@NikolaiDante 的回答,我将添加一个论点,即不透明依赖项可以通过透明依赖项引入。
例如:
public class MyService
{
private ISomeContext context;
public MyService(ISomeContext context)
{
this.context = context;
}
public void DoSomethingUseful()
{
var repository = this.context.CreateRepository<IRepository>();
repository.Save(new X());
}
}
虽然对 ISomeContext
的依赖是透明的,但它隐藏了它用于解析 IRepository
的事实,我现在认为它是不透明的依赖。恕我直言,这减少了 class 设计的 'purity',通常有利于方便或懒惰。
'Digging into Collaborators' 部分 here 中有更多关于此类问题的内容。