Reputation: 4899
I was reading about design patterns and I noticed that the term "opaque dependencies" was quite used. Some sources state that:
Opaque dependencies are the bad kind of dependencies
Opaque dependencies are the kind that you can’t assign using a class’s public API.
But I didn't understood very well.
Can somebody give me some examples where this dependencies are used and why should I avoid them?
Upvotes: 0
Views: 393
Reputation: 6801
Building on the answer from @NikolaiDante, I would add the argument that opaque dependencies can be introduced via a transparent one.
For example:
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());
}
}
While, the dependency on ISomeContext
is transparent, it's hiding the fact that it's used to resolve an IRepository
, which I now consider an opaque dependency. IMHO, this reduces the 'purity' of the class's design, often in favour of convenience or laziness.
There's more about this kind of problem in the 'Digging into Collaborators' section here.
Upvotes: 1
Reputation: 4213
An opaque dependency is one that is hidden. The opposite of opaque dependency is an explicit dependency.
Opaque dependencies are bad because developers who use a class may not realize that this dependency exists. There may be unexpected side effects when they call various methods.
Opaque Dependency
public class Users
{
private Database database;
public Users()
{
this.database = new SqlDatabase(...);
}
public User Find(int userId)
{
return database.GetById(...);
}
}
Explicit Dependency
public class Users
{
private Database database;
public Users(Database database)
{
this.database = database;
}
public User Find(int userId)
{
return database.GetById(...);
}
}
Upvotes: 2
Reputation: 18649
For example:
public class MyService
{
private IRepository repo = new Repository();
public MyService()
{
repo = new Repository();
}
}
repo
would be classed as an Opaque Dependency because there is no (easy) way to alter it, for example in a Unit Test.
This is the same example, but as a Transparent Dependency:
public class MyService
{
private IRepository repo = new Repository();
public MyService(IRepository repositoryDependency)
{
repo = repositoryDependency;
}
}
Here we can pass in our own IRepository
and test the behaviour of MyService
, and a tool such as a DI Container can set up our dependencies for us, which it can't in the Opaque example.
Upvotes: 2