Why do we need to apply -SOLID- software design principles?
Sep 19, 2024 4 Min Read 1990 Views
(Last Updated)
What are software design principles? And why it’s a right-hand thumb rule to apply certain design principles in software engineering? For those unfamiliar with the term, Software engineering is a systematic & procedural approach to software development.
Being in the IT industry for 7 Years, I was lucky to work with multiple companies from early age- startups to Fortune 500. Most of them were very different in their work procedures & work ethics. Yet, Surprisingly similar in one area: lowering the expenses at the detremint of proper system architecture.
-A System Architect
Before we begin with our System Design Principles, let’s fuss over the definition of “Technical Debt.” Technical Debt is the result we get when we prioritize the speedest deployment over code.
Table of contents
- Technical Debt??
- SOLID-An integral part of Software Design Principles
- S--Single Responsibility Principle (SRP)
- What If SRP is absent?
- O--Open closed principle (OCP)
- Should we use OCP every time? No.
- L--Liskov Substitution Principles (LSP)
- I--Interface Segregation Principle (ISP)
- The benefits of applying ISP
- D--Dependency Inversion Principle
- Wrapping up
Technical Debt??
- No matter how skilled your team is, technical debt will accumulate over time.
- If it goes unchecked, technical debt will entirely kill your project.
- To ensure that your project remains working, use SOLID principles during your development.
If you are familiar with OOPS, then you must have heard about SOLID principles. These five software development serves as a foundation for building software products that are easier to scale & maintain.
However, there are serious consequences of not using SOLID principles such as Rigidity, Immobility, Coupling & viscosity.
- RIGIDITY: Software implementation that is hard to change.
- Immobility: Deployment which is difficult to reuse.
- Viscosity: Difficult to add on new features in a systematic manner.
- Coupling: Issues related to interdependency.
- Fragility: It’s easy to break the implemented code.
Further in this article, we’ll discuss the SOLID software design principles In detail. Read till the end, and you will learn several tips that can save you time & trouble while writing code.
Interested in switching to Full-stack development career? Ensure you’re solid on full-stack development essentials like front-end frameworks, back-end technologies, and database management. Join GUVI’s Full Stack Development Course with Placement Assistance. You will be able to master the MERN stack (MongoDB, Express.js, React, Node.js) and build real-life projects.
SOLID-An integral part of Software Design Principles
Solid is an acronym for 5 software design principles that assists us to keep technical debt under control.
The main goal of SOLID is to make you & your tech team more productive which can only happen if the whole code is maintainable through decoupling and decomposition. Let’s deconstruct SOLID principles into their letters.
ROADMAP TO FULL STACK DEVELOPMENT + SYLLABUS (UPDATED)
S–Single Responsibility Principle (SRP)
A class, function, or module should have a single responsibility. They all should have only one reason to change.
If a class, module, or function has many responsibilities, it increases the probability of bugs. Making a crucial change to one of its responsibilities could affect the other ones without the developer’s knowledge. To comprehend it in easy words “Responsibility” can be defined as a reason to change, and each entity should have one, and only one reason to change.
One reason to change = > one responsibility!
The main objective of this principle is decoupling. If classes will have a separate behavior, and in case a bug arrives, it won’t hamper other unrelated behaviors. Thus creating an organized hierarchy in software design.
What If SRP is absent?
- Code is hard to read & comprehend.
- High rate of coupling.
- We unintentionally create a God Class or Monster Method. ( A class/method that controls way too many objects in the code and has grown beyond all logic to comprehend)
- Multiple If/switch statements – a clear indication that the method has more than one reason to change.
O–Open closed principle (OCP)
Class, modules, or functions should be open for extensibility but closed for modification. Although, BUG fixing is okay.
Modifications are an integral part of software design & its evolution. But if you have already upgraded to a stable build, modifications can trigger instability. Hence for a right-hand thumb rule avoid modifications, rather evolution should progress based on extension.
The principle is eminent in Production! For instance-open source libraries. The premise is that if a developer has created and published some class modification in the class can break the implementation of those, who have started using this specific class.
OCP was originally described in the context of inheritance, where you should always prefer composition over inheritance as it is easier/malleable to modify later. OCP minimizes the risk of regression bugs & enforces decoupling by isolating changes in specific components. Nevertheless, It’s not the hard end rule?
Should we use OCP every time? No.
- Start small -> Make changes inline
- More changes -> Consider inheritance
- Many changes/dynamic decisions -> consider interface and design patterns like Strategy
L–Liskov Substitution Principles (LSP)
Subsets should be subsituatble for their base type.
Barbara Liskov, 1987
If A is a subtype of B then all the objects of type B in a program may be replaced with objects of type A without altering any of the desirable properties of that program.
The principle explains how polymorphism should work, and not how it actually works, but how it should work. Needless to say, achieving clean substitution of the entities is not easy as it sounds. There are 6 rules to ensure LSP.
- Pre-Condition -> Preceding condition of the subtype should not be more restrictive than the supertype
- Invariance -> In some cases, the same type should be strictly used throughout
- Post-condition Rule -> Trailing condition of the subtype should not be less restrictive than the supertype
- Contra-variance of Methods Arguments (inputs) -> Method arguments of subtype should be more generic than the subtype
- Covariance of Return Types (outputs) -> Return types of the supertype should be more generic than the subtype
- No exceptions are allowed -> No new exception should be thrown in the subtype which is not there in the supertype
I–Interface Segregation Principle (ISP)
An ideology that no client should be forced to depend upon the interfaces that they do not use.
Many methods are written in a single large interface, and the class implementing that interface has to implement redundant methods. When a class is instructed to execute an action that is not useful or wasteful, it may trigger unexpected bugs. instead of this, we should split the interface into multiple smaller interfaces. So that we can keep the methods in the interface as granular as possible. Avoid redundancy.
Please note that “interface” in the above principle name does not strictly adhere to the interface, it could be an abstract class.
The benefits of applying ISP
- Code becomes more succinct and focused.
- It reinforces the use of LSP & SRP.
- It leans the interface, minimizes redundancy on unsued members, and reduces code coupling.
D–Dependency Inversion Principle
High-level modules should not depend on low-level modules. In fact, Both should be dependent on abstraction.
Abstraction should not rely on details, details should rely on abstraction.
Sometimes modules with great complex structures come under scrutiny when we modify or update modules at a much lower level. This is a horrifying experience for any software developer especially when software needs frequent revamp. SOLID’s last principle dependency inversion principle solves the specific issue using a key rule that High-level modules & low-level modules should never be codependent. Entities must depend on abstractions, not on concretions.
This principle says a Class should not be fused with the tool it uses to execute an action. Rather, it should be fused to the interface that will allow the tool to connect to the Class. if you are working on Spring Framework, you might be familiar with this principle.
It also says that both the Class and the interface should not know how the tool works. However, the tool needs to meet the specification of the interface. Thus reducing the dependency of high-level classes on a low-level classes by introducing an interface.
Wrapping up
So we have summarized five integral pillars of software design principles. These SOLID principles will help you make your code easy to adjust, extend and test with little to no problems.
For more such engaging & thoughtful content on Software development, enroll in GUVI’s Career Programs offering a springboard for knowledge & deep dive into in-demand streams: Full Stack Development, Data Science, Automation Testing, Data Engineering, UI UX Design & more.
It’s Industry’s leading live online class platform, that offers placement support & IIT-M recognized certifications.
Did you enjoy this article?