Every developer must know...
Hello, in this article, I try to briefly explain the 5 basic SOLID Principles that every developer must know while creating a software product.
In the agile way of working, it is easy to lose focus on the design principles. This makes a software product difficult to manage and maintain. Thus, makes them reach their end-of-life cycle sooner due to an increase in cost.
Before starting, I'd like to ask a simple question: What are the goals you keep in mind while starting a new software project, a module within existing software, or even while working on one? Let me know in the comments.
Being an autodidact, and learning from the experiences as I go, I personally keep the following goals in mind:-
Object-Oriented Design -
Most of the software products are following Object Oriented Programming languages such as Java, C++, JS (though not class-based), and my favorite, Python.
An Object-Oriented design must help your software product be a flexible, scalable, maintainable and reusable product.
If you already follow the above statements, you have an amazing product with a great team.
SOLID Principles - How do the SOLID Principles help?
First, do you know about Tight Coupling? It means the group of classes is highly dependent on one another, which must be avoided in code. Therefore, the Solid Principles help in reducing the tight coupling. It makes your software product loosely coupled. This minimizes changes in your code. Also, a change in one class doesn't affect another, nor does it require changes everywhere else.
S - Single Responsibility Principle
Every class should have single purpose, single responsibility, single job which makes them have only one reason for change.
Every class should have one, and only one, reason to change. In practice, this means each class should do one thing well. A class that handles both database queries and email notifications is doing too much; split it. This makes your code easier to test, easier to understand, and far easier to modify when requirements change.
Recommended by LinkedIn
O - Open-Closed Principle
The software entities (classes, modules, functions, definitions) should be open for extension but closed for modification.
The function created by developer 'A' has a purpose to serve, so developer 'B' has to add some features on top of it. Then, developer 'B' must be able to extend it to add more features, but not modify anything within the original purpose of the function. Unless in the worst-case whole purpose/logic of the function needs to be changed. This principle separates the existing code from the modified code. It provides better stability, maintainability, and minimizes changes in the code.
L - Liskov Substitute Principle
The child classes or derived class must be able to work independent of their parent class without any unexpected behaviour.
If class B is a subclass of class A, you should be able to replace A with B anywhere in your code without anything breaking or behaving unexpectedly. This is more subtle than it sounds. A subclass that overrides a parent method in a way that changes its contract, returning different types, throwing unexpected exceptions, or producing different side effects violates this principle and makes your inheritance hierarchy unreliable.
I - Interface Segregation Principle
Avoid large, monolithic interfaces.
This principle tells us to avoid one big interface that has a lot to do and create separate interfaces. The interface that depends on usability and requirements rather than one general interface. Example - It will be better to display dishes based on each category rather than listing all the dishes a restaurant can offer in one aggregated menu card. This helps customers browse through what they really require/need. Similar examples can be imagined for online medicine stores and various other e-commerce.
D - Dependency Inversion Principle
Abstractions should not depend upon details, details should not depend on abstractions.
As stated earlier in this article, if your high-level module or class is dependent on a low-level module or class, then your code is tightly coupled, which makes it difficult to maintain and manage. If we try to change in one class, it can break another class, which is risky. After years, you might not even remember what depends on what and how? Therefore, we must follow the Dependency Inversion Principle.
Please be honest, tell me, we all have experienced this, we changed one thing, and another failed to execute properly, haven't we?
Following this principle makes our code much more reusable.
Last Note:-
My contribution to one of the biggest Python open-source projects, Indico. It is about adding a new feature of rejecting a participant with a reason. This can explain some of the principles mentioned above. Try to notice how I split the RHRegistrationsModifyStatus into RHRegistrationsApprove and RHRegistrationsReject. Also, how can I create a new WT-Form class and pass reason as Kwargs to the notification, without making any changes to the existing code i.e., open for extension.
https://python.astrotech.io/design-patterns/oop/solid.html
For a good explanation with examples: https://www.garudax.id/pulse/solid-design-principles-python-examples-hiral-amodia/
Reference: https://www.geeksforgeeks.org/solid-principle-in-programming-understand-with-real-life-examples/