The SOLID principles are often presented as the foundational rules that all good developers should know and employ in writing object-oriented software. With such an elevated status, I decided it to dive into each principle and present my findings here. I was surprised at how often misunderstood some of these principles are.

Besides them being inherently difficult to understand, the SOLID principles can be even more difficult to grasp or apply in a dynamic language like Ruby. Terms like interface and abstract class are thrown around as standard language constructs, which we don't even have in Ruby.

Interestingly, though, approaching SOLID from a Ruby perspective leads us to discuss the concepts separately from the concrete implementations, which I think leads to a better understanding.

So let's dive in. First, we'll learn where SOLID came from and why it's worth learning. Then, each principle will have its own article picking it apart with its own example(s) along with takeaways.

Where does SOLID come from?

SOLID is an acronym, with each letter prefixing a tenet which is believed to help design good object-oriented software. This set of principles was introduced by Robert C. Martin — also weirdly known as "Uncle Bob," but I'll call him "Bob" to meet in the middle of my dignity and his wishes — in Design Principles and Design Patterns. There's an archived copy available courtesy of the Wayback Machine in case you want to give it a read.

Why is SOLID relevant?

There is much discourse about the SOLID principles and each part's relevance, particularly in how software development has changed since it was introduced.

Regardless, we still see SOLID referred to as a set of correct patterns, listed in software engineer job requirements, and otherwise presented as a set of absolute truths. SOLID is everywhere. Love it or hate it, understanding is the first step to forming a well-reasoned opinion.

The Principles

Now let's pick apart each principle.

To make this an easier read, I've split them up into individual articles of their own:

What did we learn?

Refer to each article for individual takeaways, but zooming out, here's what I learned.

SRP shocked me from the outset, once I realised how difficult it was to understand from its name, and how commonly misconstrued it is. I, myself, had always believed it meant the incorrect thing — that modules should only have one responsibility. The real meaning of SRP is much more narrowly applicable.

OCP had me discussing the idiosyncrasies of Ruby — or, highly dynamic languages — for the first time in this series, in that we need to play pretend a little bit when we talk about what's open and what's closed. My feeling is that this principle has value, but applied too soon it may cause a project to never reach completion.

For LSP we talked about typing and how it applies, or doesn't, in a duck-typed language. This principle can help us think more deeply about our objects' behaviour, which may lead us to better designs.

ISP draws another line between statically typed languages and their duck-typed cousins. We can more easily violate it in duck-typed languages without consequences, but I don't think violation is necessarily cause for concern.

Finally, DIP, whose name gives it an identity crisis as with SRP, has us thinking more even more about object behaviour to reduce coupling. Another useful one for better design, perhaps.

Apply only with context

My opinions on the SOLID principles shifted over the weeks I spent researched and writing about them. As a seasoned Ruby developer, I knew that they were aspirational and unlikely to be applied across the board to real-world projects, but I did believe that they were all generally a good idea.

Now, I believe that some of the principles have value, but in the wrong hands they can actively sabotage a project. Without enough context or experience, they may do more harm than good.

Don't optimise code that never runs

Rather than building projects with the goal of delivering some value, most of these principles are more likely to lead to building software for the sake of building software.

Does this code rely on a concrete implementation in another class? Does it inherit a few methods that it doesn't use? Forget shipping: go shave the yak for a few more days instead. Then, let's see what violations your new code turns up so we can talk about that instead of shipping actual software.

With context and experience, engineers should know where applying these principles may lead to more maintainable code. When changes may answer to many different parties, even the SRP could be a useful sanity check. In products that are proven and mature but becoming difficult to maintain, testing against the principles could improve the situation.

But imagine adhering strictly when building an MVP for a product that still requires validation. Think how much time and money will be wasted, writing code in such a way that is more extensible in a future that may never come, for a project that couldn't find its market fit — or worse, ran out of development budget before it could be shipped.

And we don't even need a brand new product for this to be a problem. Take a new feature: we could spend weeks building it for future extensibility, when it turns out that the functionality we needed was all we ever needed.

In that regard, YAGNI is an excellent contradiction for many of SOLID's teachings, and a rule of thumb that is more often applicable.

SOLID isn't important

To summarise, I don't think the SOLID principles are that important, or relevant, in today's world.

I do think that the practice of reading about SOLID, or any other software principles, can help lubricate the old brain cogs and help us think more about the design of our software. That's absolutely worth doing.

But applying SOLID? Nah. There are too many ifs, buts, and maybes to qualify it all.

Instead, spend time building real software. See what works, see what doesn't work. Learn from your peers. Read books, read articles, read newsletters. Ingest new ideas, keep thinking about code. Apply new ideas.

There aren't any shortcuts, but if there were, it wouldn't be any fun.

I hope this deep dive into the SOLID principles from a Ruby perspective was useful to you. If you have any feedback, don't hesitate to to reach out to me on Bluesky.