Thoughts about SOLID - Basic Principles
Tags: solidprinciples, programming, learning, designpatterns
Published: 2024-05-12 01:26:34


Recently, I have been reflecting a lot on some development patterns, best practices, and code quality. Many ideas come to mind with such a broad theme, but in this series of articles, I would like to specifically explore the design pattern that we now know as "SOLID", adding some personal insights into its philosophy, its concrete implementations, and about each letter that composes it.

---

## In this article

[About its origins](#about-its-origins)
[About its importance](#about-its-importance)
[About its definition](#about-its-definition)
[About its applicability](#about-its-applicability)
[Final thoughts](#final-thoughts)
[Additional readings](#additional-readings)

---

## About its origins

![About its origins](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pculc3meamjvf6s060dm.png)

Initially proposed by Robert C. Martin in his 2000 article "_Design Principles and Design Patterns_," and later expanded by Michael Feathers to encapsulate them in the acronym we know today, the SOLID principles have been cemented in the realm of Software Engineering as **essential standards for building robust, maintainable, and scalable software**.

This is the summary as we know it today, over 20 years after its conception. It's interesting to see how, currently, this vision exactly achieves what every software engineer, as well as any corporation with technological assets, seeks as a result: **robustness, maintainability, scalability, and quality**.

Perhaps because of this, SOLID has become a "buzzword" in recent years - that is, a name that is easy to remember, where both those who position it as part of their knowledge and those who demand this competency for development positions may not necessarily understand or advocate for its real applicability.

This does not mean that its foundation is disposable, quite the opposite. In fact, what happens is that, living in the golden age of content, many focus on knowing **what** it is, through short bursts of information, but not everyone delves into the essential detail of **how it works**.

---

## About its importance

![About its importance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqxaafr8s2go8aitjorc.png)

When we talk about SOLID (or any other architectural pattern), it's important to understand that they are **proposals to improve our work** in software construction. In other words, it's not something you install in your product, a dependency you need to add to the application, and certainly not something that automatically creates competent software and solves all existing and future problems. The best ingredients and pots, when given to someone who doesn't know how to cook, don't guarantee quality food.

I would like to highlight a phrase that, for me, summarizes very well why the adoption of such proposals and standards is a constant in our field. Although Martin is addressing a more specific topic in his article in the excerpt below (_design patterns_), I believe it applies to _design principles_ in a similar way:

> The essential definition of a design pattern is a well worn and known good solution to a common problem.
>
> -- <cite>Robert C. Martin</cite>

In other words, these development paradigms have their roots in **optimizing the repetition process**. Throughout our careers, we often find ourselves facing problems where sharing code and ideas naturally presents itself in implementations. We duplicate approaches, consult previous constructions to base ourselves on the new ones, and thus end up evolving the code in an inconsistent way.

Thanks to the optimization exercises carried out by great thinkers and the community in this field over the years, much like with scientific experiments, **solid foundations** begin to emerge, serving as starting points for solving new problems. Blocks of code that were once duplicated are now transformed into patterns that avoid such duplications, proposing instead ways to **distribute logic in a reusable manner**.

---

## About its definition

![About its definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3jzs3jl58ebbmdk4kb7.png)

This is where the SOLID principles fit in: **as multifaceted tools** to solve problems and create patterns that, conceptually, can be shared among team members, present or future (assuming everyone seeks to share this knowledge).

The acronym itself identifies the 5 principles, not necessarily in order of importance, but in the order to form the word solid, creating the whole creative bond with the concept of robustness:

- **S**ingle Responsibility Principle: Classes should have only one responsibility, and therefore, a single reason to change;
- **O**pen/Closed Principle: Classes should be closed for modification but open for extension;
- **L**iskov Substitution Principle - Classes should be easily substitutable by their subclasses;
- **I**nterface Segregation Principle - It is better to have multiple specific interfaces than a single generic interface.;
- **D**ependency Inversion Principle - Classes should depend on interfaces and abstractions, not concrete implementations.

Reading only the description of each letter, it becomes clear why so many people feel little confidence or much confusion on this topic. I say this from experience: without concrete examples or practical demonstrations, it's difficult to understand what it means to "depend on abstractions and not on implementations," or even why you would need to "replace a subclass" without understanding the proper context. Martin's original article constantly includes examples, no matter how abstract they may be, as it is really a topic that can go unnoticed if we cannot visualize it.

An interesting point is that all concepts address the topic of **classes**, except for the letter **I**, which is the only one that covers the view of **interfaces**. In other words, the birth of SOLID (and of the design patterns intrinsically linked to its philosophy) is tied to the paradigm of OOP (Object-Oriented Programming). It is important to consider the time when Martin's article was published, which leads us to think about the maturity of this standard and its longevity at that moment in history.

This does not mean that the SOLID principles are limited only to this form of implementation, at least at the code level. Other development models, such as FP (Functional Programming), can also draw from the same source in terms of ideology. What I mean is that the proposed ideas, of having criticality in the analytical view of interfaces and entities, may also make sense in other contexts in which we will deal with these iterations. I intend to delve into this idea in future parts of this series.

---

## About its applicability

Upon understanding the definitions, we may ask ourselves (I certainly did the first time): "Alright, this is all very interesting, but how does it work in practice? How do I apply these concepts in my day-to-day work? How do I find opportunities in my projects to exercise this knowledge?" Amidst this, there's a dangerous impulse that can arise, and it's more than essential to reinforce a brief reality: **perhaps you won't need to use all the principles, all the time, simultaneously**.

The SOLID principles, like any design or architectural pattern, are a bit more empirical than other areas of knowledge, requiring us to exercise our **analytical vision** rather than just technical knowledge. Many well-known problems can be solved in an elegant, guaranteed, and well-established way - but does your problem fit into that solution? Or are you seeking problems to exercise a software engineering rehearsal?

Based on my turbulent early experiences with these paradigms, I managed to abstract 3 starting points that can help in understanding and facilitating the real application of the conceptual vision:

1. **Understand the abstracted essence**: Before looking at code or practical examples, try to understand what each letter means and what it proposes **at a design level, not a code level**. In other words, regardless of the language or framework in use, what are the gains at the application's structural level? And the losses? Martin's article itself is an excellent starting point, but as I mentioned earlier, online content with more informal (or formal, according to your preference) languages is abundant in our era.

2. **Exercise examples from your reality**: It will be of no use if the examples you seek deviate too much from your concrete knowledge. As real as they may be, they might not be consistent with your personal reality. Personally, I had a lot of contact with FinTechs and projects for the factory floor, and thinking about related entities in these contexts helps me a lot. And of course, **think about systems** - the functioning of a municipal library is quite universal, for example. You can even base it on personal hobbies, visualize something you like and master, and see it with that analytical perspective (when I think about video games, I can't count how many times I've used Super Mario 64, Banjo-Kazooie, and Donkey Kong 64 as reading keys).

3. **Seek an analytical vision**: Start observing, in your day-to-day, the entities you work with, no matter how simple your project may be. Is it already optimized enough? Can you see code or implementation duplications? Is there something that could be more generic, or perhaps more specific? Take a few minutes of your day to reflect on this and truly seek to understand the system behind the product - make notes, diagrams, a brief description, and seek relationships. It's not easy, and it's not a skill that will emerge overnight, but it's ideal to start somewhere. I also recommend alternating between doing this activity alone and with a partner - analyzing as a team can bring insights that might go unnoticed otherwise, as each person will have their own discernment based on their experience baggage.

---

## Final thoughts

![Final thoughts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oirld7t1bun8e2oizyoi.png)

The SOLID principles constitute an extremely powerful toolkit that, if used correctly and thoughtfully, can bring various benefits to both the software being built and those building it. It's no wonder that, even decades after Robert C. Martin's original idea was published, we continue to talk about it, advocate for it, teach it, and share ideas on the topic. The longevity of the entire concept, including the fact that it is undergoing iterations and evolutions by the community, demonstrates its deterministic importance.

There are many people who can present SOLID in a much more elegant or extravagant way than I can. My idea with this article was to ruminate a bit on the topic and present some ideas from my philosophy about this paradigm. :)

Thank you for reading this far. In future iterations of this series, I want to delve a little deeper into each of the letters, with some practical examples and again reflecting on the topic.

---

## Further reading

**Design principles and design patterns**, article by Robert C. Martin, 2000. Accessed at https://staff.cs.utu.fi/~jounsmed/doos_06/material/DesignPrinciplesAndPatterns.pdf

**Design Patterns**, book referenced by Martin as GOF (Gang of Four). Details about the book can be found on Wikipedia. Accessed at https://en.wikipedia.org/wiki/Design_Patterns