After looking up on the top most of the answers I've found is this:
- High level modules should not depend upon low-level modules. Both should depend upon abstractions.
- Abstractions should never depend upon details. Details should depend upon abstractions.
My understanding on this is that this kind of design violates it? because the class Car depends on the lower level class Engine?
public class Car {
private Engine engine;
public void run() {
engine.start()
// do other stuff
}
}
public class Engine {
public void start() {
// do stuff that will start engine
}
}
If it does violate it, whats the solution? I can't think of an alternative.
Im also having a hard time understanding the second part "Abstractions should never depend upon details. Details should depend upon abstractions."
3 Answers 3
Below link explains the concept of dependency inversion well: http://www.oodesign.com/dependency-inversion-principle.html
Basically, it boils down to complex classes depending on behaviour of simple classes, rather than the classes themselves. In your example, the below would be a good implementation of dependency inversion:
interface Movable {
public void start();
public void throttleUp();
public void throttleDown();
//etc..
}
class Engine implements Movable {
public void start() {
//code
}
//implement other methods
}
class Car {
Movable engine;
public void setEngine(Movable engine) {
this.engine = engine;
}
public void run() {
engine.start();
//code...
}
}
In future you can create different types of engines like petrol, diesel, steam, electric. But as long as they implement Movable, your Car will not change since it is decoupled.
Comments
You need to understand the difference between runtime dependency and code dependency. Car will always have a runtime dependency on your Engine implementation details, because the control flow will move from the Car to the Engine.
However, Dependency Inversion is about the source code dependencies. You could make Engine an interface or abstract class, and different subclasses could provide their own start() implementation (polymorphism). This way, your Car would depend only on the Engine abstraction (on the source code level), but not on the details of the various start() implementations. You could add new engines to the system after Car was written, compiled and deployed.
Also note that these principles are more like recommendations, not "always/never" rules. Use your own judgements.
8 Comments
Dependency Inversion is part of the SOLID paradigms, so if you want write SOLID code then you must follow those rules.Let me rephrase all that is already there in your post and see if it makes sense
- It is perfectly alright for Car to be dependent on the interface of Engine like in your case (as long as the Engine is injected).
- High level module like Car should not depend on low level implementation details - say a particular subclass of Engine e.g. JetEngine but it is alright for it to depend on the interface Engine
- Abstractions like Engine should not depend on any particular implementation (say a subclass Nut, Bolt or Engine again).
Comments
Explore related questions
See similar questions with these tags.