Luis Teijon
Luis Teijon

Reputation: 4899

What are opaque dependencies?

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

Answers (3)

David Osborne
David Osborne

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

Silas Reinagel
Silas Reinagel

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

NikolaiDante
NikolaiDante

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

Related Questions