Reputation: 2094
Could someone please give me an example of a hidden dependency. I've googled it, and found results like this:
"A visible dependency is a dependency that developers can see from a class's interface. If a dependency cannot be seen from the class's interface, it is a hidden dependency."
(Source - http://tutorials.jenkov.com/ood/understanding-dependencies.html#visiblehidden)
But I still don't quite get it.
Does it mean when a dependency is happening inside a function, and not a declared variable in the beginning of a class? Or is it when you simply create functions other than the signature methods declared in an interface?
Upvotes: 11
Views: 3723
Reputation: 15569
Transparent (Concrete) Dependency: A Transparent Dependency is a dependency which is set through a public constructor.
Opaque (Hidden) Dependency: An Opaque Dependency is a dependency that is NOT set through a public constructor, as a result it is not easy to see the dependency
Here is an example:
// 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 are considered to be an anti-pattern, this article highlights the problems with Opaque IoC:
Writing tests for component implementing Opaque IoC is much harder
Transparent IoC helps identity classes which are doing "too much"
Mark Seemann describes the second point elegantly:
One of the wonderful benefits of Constructor Injection is that it makes violations of the Single Responsibility Principle glaringly obvious.
Closely related to this is Nikola's 2nd law of IoC:
Any class having more than 3 dependencies should be questioned for SRP violation
Upvotes: 3
Reputation: 21487
The following is the example of a hidden dependency:
class Foo
{
void doSomething() //a visible method signature
{
//the body of this method is an implementation detail
//and is thus hidden
new Bar().doSomething();
}
}
In the above example, Bar
is a dependency for Foo
because Foo
relies on the collaboration of Bar
.
It is hidden because the dependency on Bar
is not explicit in the constructor of Foo
or method signatures for Foo
.
Think of a class as defining a visible contract exposed to collaborators. The methods and constructor signatures are part of that contract. The body of the method doSomething()
is hidden because it is an internal implementation detail of the class that is not exposed in the contract. All that we know from the signature is that there is a method called doSomething()
that is of return type void
.
For a counterexample, we could refactor the class to make the dependencies manifest:
class Foo
{
private readonly Bar bar;
Foo(Bar bar) //the constructor signature is visible
{
this.bar = bar;
}
void doSomething()
{
bar.doSomething();
}
}
In the above example, Bar
is explicitly defined as a dependency in the exposed signature for the constructor.
Alternatively we could do:
class Foo
{
void doSomething(Bar bar) //method signature is visible
{
bar.doSomething();
}
}
Now the dependency on Bar
for the method doSomething
is visible as it is included in the method signature for doSomething
.
Upvotes: 13