In this blog post, the Dependency Inversion Principle was described by this motivational poster:
I don't understand what the poster means: How does soldering a lamp directly to the wall violate dependency inversion principle and how does having plugs follow dependency inversion principle. Maybe some skeleton Java or C# code about lamps and electrical outlets might be helpful.
From your link:
The “D” in SOLID is for Dependency Inversion Principle, which states that high-level modules shouldn’t depend on low-level modules, but both should depend on shared abstractions.
I do not know what they mean be 'shared' abstractions. In code, the lamp would be the 'high-level module', and where it get's it's power from would be it's dependency, or 'lower-level module'.
Your questions:
How does soldering a lamp directly to the wall violate dependency inversion principle
The lamp in the poster is violating the dependency inversion principle because it is not relying on an abstract power source. It relies on a very concrete implementation of being soldered directly to the electrical wiring in a wall. If this relationship were modeled in code, it might look something like this:
public class Lamp {
// This part is the equivalent of "soldering a lamp directly to the electrical wiring in a wall"
private ElectricalWiringInBobsWall electricalWiring = new ElectricalWiringInBobsWall();
private boolean isOn;
public void turnOn() {
electricalWiring.useElectricityInWatts(60);
isOn = true;
}
public void turnOff() {
electricalWiring.turnOffElectricityInWatts(60);
isOn = false;
}
}
The consequences of doing this are that the Lamp is very hard to use in other situations. In real life, the lamp itself would require a lot of rework if you wanted to move it to a different part of the house, use it on a generator, or even take it overseas and plug it in a different outlet. Similarily, in a code base, if you wanted to reuse this lamp with a different power source, you would have to change the code in the lamp itself, which might require retesting, or introduce new bugs.
how does having plugs follow dependency inversion principle
An outlet is more abstract because, as a user, you don't really have to know HOW the lamp gets it's power. All you have to know is that if you plug the lamp in, it works. The outlet is an abstraction over a power source. That is to say, it hides the details of where the power is actually coming from. There could be an outlet in a wall, on a generator, an an overseas adapter, on a solar panel power source, etc.
Employing the DIP in our class above, we want the Lamp
to depend on an abstraction, and have the implementation passed in as a dependency. In code, this might look like this:
public interface Outlet {
void useElectricityInWatts(int watts);
void turnOffElectricityInWatts(int watts);
}
public class Lamp {
private Outlet outlet;
private boolean isOn;
// We pass in the dependency instead of instantiating it and rely on an interface (abstraction)
public void plugInto(Outlet outlet) {
this.outlet = outlet;
}
public void turnOn() {
outlet.useElectricityInWatts(60);
isOn = true;
}
public void turnOff() {
outlet.turnOffElectricityInWatts(60);
isOn = false;
}
}
Now, a lamp can use any type of outlet: BobsOutletInHisWall, GeneratorOutlet, EuropeanAdapterOutlet, etc. It can easily be moved and used in other situations, and not have to change at all.
I know the example is far from perfect, but I hope that explains what the poster means.