(ARTICLE): Finished the SOLID article.
All checks were successful
Deploy to Server / deploy (push) Successful in 22s
All checks were successful
Deploy to Server / deploy (push) Successful in 22s
This commit is contained in:
parent
c6cfc8c57a
commit
75b2612079
@ -1,15 +1,15 @@
|
|||||||
Date: 2025-11-??
|
Date: 2025-11-??
|
||||||
Desc: SOLID principles help developers write better code, but how?
|
Desc: Learn the SOLID principles of object-oriented design for cleaner code and better architecture, with real-world C++ examples.
|
||||||
# SOLID Principles: Writing "Clean Code"
|
# SOLID Principles: Writing Clean Code
|
||||||
|
|
||||||
<img src="/journal/SOLID.png" alt="Solid principles guide" style="background-color: white; border-radius: 15px; margin-inline: 10px; margin-top: 2.5%; margin-bottom: 1.5%; width: 95%; max-width: 500px;">
|
<img src="/journal/SOLID.png" alt="Diagram showing SOLID design principles for OOP" style="background-color: white; border-radius: 15px; margin-inline: 10px; margin-top: 2.5%; margin-bottom: 1.5%; width: 95%; max-width: 500px;">
|
||||||
|
|
||||||
###### Image source: [Geeks for Geeks](https://www.geeksforgeeks.org/system-design/solid-principle-in-programming-understand-with-real-life-examples/)
|
###### Image source: [Geeks for Geeks](https://www.geeksforgeeks.org/system-design/solid-principle-in-programming-understand-with-real-life-examples/)
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
###### Author: Hayden Hargreaves
|
###### Author: Hayden Hargreaves
|
||||||
|
|
||||||
###### Published: 11/??/2025
|
###### Published: 11/10/2025
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ maintainable and extensible software. Adapting these principles into your own co
|
|||||||
|
|
||||||
The five principles are as follows:
|
The five principles are as follows:
|
||||||
- **S** - Single-responsibility Principle
|
- **S** - Single-responsibility Principle
|
||||||
- **O** - Open-closed Principle
|
- **O** - Open/closed Principle
|
||||||
- **L** - Liskov Substitution Principle
|
- **L** - Liskov Substitution Principle
|
||||||
- **I** - Interface Segregation Principle
|
- **I** - Interface Segregation Principle
|
||||||
- **D** - Dependency Inversion Principle
|
- **D** - Dependency Inversion Principle
|
||||||
@ -33,6 +33,13 @@ The five principles are as follows:
|
|||||||
This article serves as an *introduction*, not a comprehensive guide. However, a simple understanding
|
This article serves as an *introduction*, not a comprehensive guide. However, a simple understanding
|
||||||
of the principles can help you level up as a developer!
|
of the principles can help you level up as a developer!
|
||||||
|
|
||||||
|
## Key Takeaways
|
||||||
|
|
||||||
|
- **Single Responsibility Principle:** Each class should do one thing and have only one reason to change.
|
||||||
|
- **Open/Closed Principle:** Code should be open for extension but closed for modification.
|
||||||
|
- **Liskov Substitution Principle:** Subtypes must be substitutable for their base types without affecting program correctness.
|
||||||
|
- **Interface Segregation Principle:** Never force a client to depend on methods it does not use.
|
||||||
|
- **Dependency Inversion Principle:** Depend on abstractions, not on concrete implementations.
|
||||||
|
|
||||||
## Object-Oriented Programming Refresher
|
## Object-Oriented Programming Refresher
|
||||||
|
|
||||||
@ -66,7 +73,7 @@ The **[Single-Responsibility Principle](https://en.wikipedia.org/wiki/Single-res
|
|||||||
### The Misunderstood Principle
|
### The Misunderstood Principle
|
||||||
|
|
||||||
The SRP is the simplest, yet most commonly misunderstood principle. The goal of the SRP is to **prevent
|
The SRP is the simplest, yet most commonly misunderstood principle. The goal of the SRP is to **prevent
|
||||||
unexpected side effects* by keeping each unit (class) simple and with only a single purpose. A class
|
unexpected side effects** by keeping each unit (class) simple and with only a single purpose. A class
|
||||||
with many responsibilities will often need to be modified as requirements change, which can lead to
|
with many responsibilities will often need to be modified as requirements change, which can lead to
|
||||||
more bugs. When a class is changed, it can impact classes that depend on it, which can result in
|
more bugs. When a class is changed, it can impact classes that depend on it, which can result in
|
||||||
unexpected bugs in code that did not seem to change. However, a class with a **single responsibility**
|
unexpected bugs in code that did not seem to change. However, a class with a **single responsibility**
|
||||||
@ -263,12 +270,6 @@ class. But Bertrand Meyer suggests that [inheritance](https://en.wikipedia.org/
|
|||||||
> ~Bertrand Meyer
|
> ~Bertrand Meyer
|
||||||
>
|
>
|
||||||
|
|
||||||
This is problem because it frequently introduces tight coupling if subclasses depend on the
|
|
||||||
implementation of a parent class. For that reason, "Uncle Bob" revised the principle to the **[Polymorphic](https://en.wikipedia.org/wiki/Polymorphism_(computer_science))
|
|
||||||
Open/Closed Principle**. Using interfaces instead of **superclasses** (a class which has subclasses) allows
|
|
||||||
different implementations which can be swapped and changed with relative ease. Furthermore, the calling
|
|
||||||
(using) code does not need to be changed, as long as the interface's requirements are met.
|
|
||||||
|
|
||||||
This is a problem because it frequently introduces tight coupling if subclasses depend on the
|
This is a problem because it frequently introduces tight coupling if subclasses depend on the
|
||||||
implementation of a parent class. For that reason, "Uncle Bob" revised the principle to the **[Polymorphic](https://en.wikipedia.org/wiki/Polymorphism_(computer_science))
|
implementation of a parent class. For that reason, "Uncle Bob" revised the principle to the **[Polymorphic](https://en.wikipedia.org/wiki/Polymorphism_(computer_science))
|
||||||
Open/Closed Principle**. Using interfaces instead of **superclasses** (a class that has subclasses) allows
|
Open/Closed Principle**. Using interfaces instead of **superclasses** (a class that has subclasses) allows
|
||||||
@ -447,7 +448,6 @@ public:
|
|||||||
this->width = w;
|
this->width = w;
|
||||||
this->height = w; // Mutates height
|
this->height = w; // Mutates height
|
||||||
}
|
}
|
||||||
In the context of mathematics, a square is a rectangle. However, in the context of programming, forcing a square to inherit from a rectangle typically violates the LSP. This violation occurs because the settings are being overridden, and each value is set individually from each method. The expectation for a rectangle is that the height and width will be set independently!
|
|
||||||
|
|
||||||
void setHeight(int h) override {
|
void setHeight(int h) override {
|
||||||
this->height = h;
|
this->height = h;
|
||||||
@ -573,7 +573,8 @@ The [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_in
|
|||||||
|
|
||||||
>
|
>
|
||||||
> "Entities must depend on abstractions, not on concretions. It states that the high-level module
|
> "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."
|
> must not depend on the low-level module, but they should depend on abstractions." ~Robert "Uncle
|
||||||
|
> Bob" Martin
|
||||||
>
|
>
|
||||||
|
|
||||||
This means that a class should rely on abstractions (interfaces or abstract base classes) rather than
|
This means that a class should rely on abstractions (interfaces or abstract base classes) rather than
|
||||||
@ -687,7 +688,60 @@ private:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Don't Repeat Yourself
|
||||||
|
|
||||||
|
Before wrapping up, there is one more guideline that is not a part of the *SOLID* acronym but is
|
||||||
|
relevant to programming in any paradigm. The **Don't Repeat Yourself** (DRY) rule states:
|
||||||
|
|
||||||
|
>
|
||||||
|
> "Every piece of knowledge must have a single, unambiguous, authoritative representation within a
|
||||||
|
> system". ~Andy Hunt and Dave Thomas
|
||||||
|
>
|
||||||
|
|
||||||
|
The DRY rule is not directly part of the **SOLID** principles; however, it is commonly paired together as
|
||||||
|
a result of Uncle Bob's strong feelings about the guideline.
|
||||||
|
|
||||||
|
>
|
||||||
|
> "Duplication is the root of all evil in software". ~Robert "Uncle Bob" Martin
|
||||||
|
>
|
||||||
|
|
||||||
|
The purpose of the guideline is to encourage developers to avoid writing duplicate code in a system.
|
||||||
|
Adhering to the *DRY* principle allows developers to create modular and reusable modules. Many believers
|
||||||
|
in the system also believe that *DRY* code is more readable and easier to maintain and troubleshoot.
|
||||||
|
|
||||||
|
DRY is not the topic of this article, but if you would like to learn more, this [article](https://www.geeksforgeeks.org/software-engineering/dont-repeat-yourselfdry-in-software-development/)
|
||||||
|
contains some solid points that support the guideline.
|
||||||
|
|
||||||
## SOLID Only For OOP?
|
## SOLID Only For OOP?
|
||||||
|
|
||||||
|
The focus of the SOLID principles is on **object-oriented programming**, but that does not mean they apply
|
||||||
|
*only* to OOP. The terms "class" and "interface" can be abstracted down to their underlying philosophies,
|
||||||
|
and the benefits of SOLID can be implemented anywhere these abstractions exist! For example, the **single
|
||||||
|
responsibility principle** can be applied to teams, functions, modules and micro-services. The idea of
|
||||||
|
the open/closed principle is desirable in any architecture.
|
||||||
|
|
||||||
|
The **Liskov Substitution principle** is a little bit harder to apply elsewhere, but anywhere a polymorphic
|
||||||
|
relationship is observed, the principle can apply. The **interface segregation principle** encourages the
|
||||||
|
breakdown of large, complex contracts, which is applicable in any design context and functional
|
||||||
|
programming.
|
||||||
|
|
||||||
|
Finally, the **dependency inversion** principle encourages decoupling via abstraction, which serves as the
|
||||||
|
core of many architectural design patterns. Therefore, the SOLID principles originated in an OOP context,
|
||||||
|
but they offer "timeless wisdom" ([Digital Ocean](https://www.digitalocean.com/community/conceptual-articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design#frequently-asked-questions-faqs))
|
||||||
|
for the development and maintenance of robust, scalable systems.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Understanding and applying the SOLID principles is not about memorizing five rules or following them
|
||||||
|
strictly; **it’s about learning to think more critically about design**. Each principle—Single Responsibility,
|
||||||
|
Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion—offers a lens through
|
||||||
|
which you can identify poor architecture and refactor toward cleaner, more maintainable code. When
|
||||||
|
used thoughtfully, they lead to systems that are easier to test, extend, and collaborate on.
|
||||||
|
|
||||||
|
While SOLID principles were born in the world of object-oriented programming, their underlying
|
||||||
|
philosophies reach far beyond it. Whether you’re structuring a microservice, designing a REST API,
|
||||||
|
or writing a simple Python script, their concepts encourage scalability, flexibility, and craftsmanship.
|
||||||
|
The ultimate goal isn’t to follow SOLID for the sake of it, but to build software that is a pleasure
|
||||||
|
to read, modify, and maintain.
|
||||||
|
|
||||||
|
|
||||||
## "Don't Repeat Yourself" From Uncle Bob
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user