SOLID is an acronym that stands for five design principles. This helps to design a more understandable, flexible, reliable, and easily maintainable software. These principles are the basics of a good software design.
There are five SOLID principles:
- Single Responsibility Principle
- Open Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
The main reasons for a software failure or bad software are,
- Implementing many functionalities in the same class even though they are not related
- Implementing a tight coupling relationship among the classes.
To overcome these issues in software development, we need to consider the following points.
- An appropriate design pattern as per the project need
- Correct architecture and
- Design principles (SOLID, DRY, etc.)
Let us discuss the SOLID principles
1. Single Responsibility Principle:
The Single Responsibility Principle (SRP) states “A class or method should have only one responsibility”.
This means that each module or class or function in your code should have just one job to do. Everything there in class should be associated with one purpose.
This gives us a proper way of identifying classes at the design phase of an application and it causes you to consider all the ways a class can change.
Suppose, we have created a class UserService for register and login, which has the responsibility for user registration and login but not for sending or validating an email. If there is a need to send an email, then a separate class should be created for the same. UserService class should not be used for sending the email.
A separate class should be created for sending or validating emails.
2. Open Closed Principle:
This states that “Classes should be open for extension, but closed for modification”.
- Open for extension:
The new functionality/behavior can be added to satisfy the new requirements.
- Closed for modification:
To extend the new functionality/behavior, it is not required to modify the existing code.
It means the software is structured like that with every new release, we added the code for new functionality instead of modifying the previous one.
In other words, the behavior of a class ought to be extendable, without having to modify that class.
Suppose we have a Shape class with the CalculateArea method, which can be extended and used by its child class to calculate their area. Without modifying the base class Shape, area calculation for all the shapes is achieved. It is called Open for extension and closed for modification.
3. Liskov Substitution Principle:
This principle defines “Objects of a base class should be replaceable with instances of their subclasses without altering the correctness of the base class”.
This principle is an extension of the Open-Closed Principle and it means we must make sure that new derived classes extend the base class without changing their behavior.
Let us consider the example of the Liskov Substitution Principle violation is found in the .NET Framework’s ReadOnlyCollection<T> which implements ICollection<T> but does not provide the required behavior of Add or Remove.
Clearly, it might not make sense for ReadOnlyCollection<T> to allow records to be added or removed.
We should remember that a subclass should override the parent class’s methods in such a way that does not break functionality from a consumer’s point of view.
4. Interface Segregation Principle:
This states “Clients should not be forced to implement interfaces they do not use”.
Instead of one big interface, many small interfaces can be used based on the functionalities. For each submodule, an interface will be served.
Suppose we have an interface with both click and touch. But some classes need only click and some need only touch, the unused function throws an error while implementing the interface.
In such situations, ISP helps us in segregating the interfaces into two. So that the classes which need only click inherit only the IClick interface and others use the ITouch interface.
5. Dependency Inversion Principle:
This principle states the following two points.
- “High-level modules or classes should not depend on low-level modules or classes. Both should depend on abstractions”.
- “Abstraction should not depend upon details. Details should depend upon abstractions”.
Here, both Customer and its Repository classes depend on the interface.
And Save() method depends on the interface.
Finally, we have gone through all five SOLID principles successfully. And we can conclude that using these principles we can build an application with organized, understandable, and easily maintainable code.