SOLID is a set of 5 principles that help developers write maintainable code. Applying these principles can avoid a lot of messy code and as an added advantage the code becomes very testable.
Let’s go over all 5 principles one by one:
This basically means that one class must only be responsible for one action.
Take our Peeler class, it does only one thing and that is peel().
Now take the Apple class we showed before. Besides from being an apple, it can remove it’s core and peel itself. One could say it has more than one responsibility.
In this case it even sounds strange, because apples cannot remove their own core, let alone peel themselves.
The open/closed principle states that classes should be open for extension, but closed for modification.
What this means is that when new functionality is required the original code remains untouched. This can be done by adding a new method to a class, but the preferred way is to extend a class and implement the new functionality in this class instead of modifying the existing one.
Liskov substitution means that when a class extends another class, one must be able to use it in the exact same way as its parent or base class. Allowing for substitution of the base class by the derived class in existing code.
So basically when a class is extended and it overrides an existing method, it should always call its parent’s version of the method and yield (at least) the same result.
This principle has everything to do with loose coupling. What it means is that a class should depend on interfaces instead of implementations.
This makes it easy to swap implementations used in certain logic and prevents classes from depending on each others implementations.
The dependency inversion principle states that rather than instantiating new objects in a class, these objects should be injected.
Injecting the dependencies (but relying on their interfaces) gives us the opportunity to easily swap them with a different implementation. Also the class is no longer responsible for initializing the dependencies in most cases.
In some cases it is not possible to inject the dependency (perhaps because it depends on values that can only be revealed during the runtime of the class that needs it). In these cases it is possible to inject a “Factory”.