"High-level modules should not depend on low-level modules. Both should depend on abstractions."
"Abstractions should not depend on details. Details should depend on abstractions."
In order to understand this principle, we must explain the important concept of coupling and decoupling. Coupling refers to the degree to which modules of a software system are dependent on one another. The lower the dependency is, the easier it is to maintain and extend the system.
There are different approaches to decoupling the components of a system. One of them is to separate the high-level logic from the low-level modules, as shown in the following diagram. When doing this, we should try to reduce the dependency between the two by making them depend on abstractions. This way, any of them can be replaced or extended without affecting other modules: