Dependencies are, from that definition, the:
other objects they work with
For example, let's say you have this class:
class Widget {
public void DoSomething() {
WidgetCalculator calculator = new WidgetCalculator();
int someValue = calculator.calculate();
// and so on...
}
}
In this setup, Widget
has a dependency on WidgetCalculator
. It's an object that Widget
"works with", or rather, an object that Widget
needs in order to perform its own work. The code above does the job, but it leads to tight coupling. You can't easily swap out a different implementation of WidgetCalculator
for example, breaking changes in one class can break the other class, etc.
This is where dependency inversion becomes useful. Instead of creating an instance of WidgetCalculator
, it can require one. This could be as simple as:
class Widget {
public void DoSomething(WidgetCalculator calculator) {
int someValue = calculator.calculate();
// and so on...
}
}
Now in order to perform the operation, whatever consuming code is invoking that operation needs to provide the Widget
with its dependency. If there is a lot of code on Widget
with that dependency, it could be promoted to a constructor argument so that consuming code can't even create a Widget
without supplying the dependency:
class Widget {
private final WidgetCalculator calculator;
public Widget(WidgetCalculator calculator) {
this.calculator = calculator;
}
public void DoSomething() {
int someValue = this.calculator.calculate();
// and so on...
}
}
There are various ways in which a dependency can be provided, but the core principle is that the object requires that the dependency be provided to it rather than seek out the dependency itself.