SOLID Principles

For decades, developers have made the same software design errors. The SOLID principles are coding standard created to avoid these known bad designs and help the new generations of developers with principles.
Principles
SOLID stands for:
- Single responsibility principle:
A class should have one, and only one, reason to change.
A component (class, struct, method…) should have one responsibility. One responsibility helps to develop manageable, maintainable, extendable, reusable and testable components. If you wonder how small your component should be, the smaller is your component the better it is so it is easier to manage, maintain, etc.
Once your code works, you should think about code organization. Look at your class and the way you can break it into small units with single responsibilities. it will help to understand the complexity of a component. Working with smaller components help to have well-defined and well-labeled components as well as reusability.
- Open-closed principle:
Entities should be open for extension, but closed for modification.
A component (class, module, method…) can never be 100% open-closed. The project backlogs tell you what change often, so components that will need modifications. In an ideal system, we incorporate new features by extending the system, not by making modifications to existing code.
- Liskov principle:
Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.
It means that a method with a parameter could use the base/parent class or a subclass/derived class as the parameter type without breaking anything.
- Interface segregation principle:
A client should never be forced to implement an interface that it doesn’t use or clients shouldn’t be forced to depend on methods they do not use.
In a protocol, if your client doesn’t use all of the methods, it means that you should break down your protocol into smaller one.
- Dependency inversion principle:
Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions.
High level modules are concrete type which contain implementation details. Low level modules are abstract classes/interfaces which represent concepts. Classes should depend upon abstractions, not on concrete details. Abstraction helps to isolate the impact of details change. The less you components are coupled, the more flexible and reusable you component is.