Here are 3 statements, all of which means the same thing:
- Depend upon Abstractions. Do not depend upon concretions.
- 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.
This principle was introduced by Robert Martin together with the rest 4 SOLID principles. In my opinion it is the simplest one in terms of understanding. But not the least in importance. Not elaborating it too much, lets say it in short and straight forward:
Put abstraction level (interfaces) between high-level and low-level modules
When interfaces are involved, lower level modules can be changed, extended without fear to affect high level modules which actually use them. In turn, high level module does not have to care about implementation details of low level modules.
Example
Lets leverage our classic HR sample. Lets say we have class for calculating annual bonuses. So far we have it applied just for one employee type – Administrator. But later on we have to do the same with another employee type – Salesman.
Wrong
//Before change... public class BonusCalculator{ public int getBonus(Administrator employee){ //... calculate ... } } //After change... public class BonusCalculator{ public int getBonus(Administrator employee){ //... calculate ... } public int getBonus(Salesman employee){ //... calculate ... } }
As we see in the sample in order to add another employee type, we had to change BonusCalculator class itself by adding another method signature with new employee type. We had to do this, because BonusCalculator class is dependent upon employee type.
Correct
public interface BonusedEmployeeInterface { //... } public class Administrator implements BonusedEmployeeInterface { //... } public class Salesman implements BonusedEmployeeInterface { //... } public class BonusCalculator{ public int getBonus(BonusedEmployeeInterface employee){ //... calculate ... } }
In the sample above we have added another abstraction level – BonusedEmployeeInterface. Leveraging it in the class BonusCalculator lets us calculate bonuses to any number of types of employees. The only requirement is that its class must implement BonusedEmployeeInterface.
Please check for other principles of SOLID in this post – SOLID Software Design Principles. Summary.