Hi! I'm Eduardo Lávaque, and this is my blog.

Writing software for 11+ years. Eschew hype; focus on performance.

Living in Switzerland since 2017.

On SOLID

And a more workable alternative, Data-Oriented Design.

I hope the Wikipedia page for SOLID is solidly written, because it will be my reference.

On principle I don't like SOLID, because it is extremely thin and flaky.

I don't think I will convince any OOP people or Robert Martin people on my viewpoint, I don't intend to. But hopefully I can offer a viewpoint they haven't heard before.

If my understanding of a particular principle is lacking, or isn't enlightened, please do try to explain it to me. I don't think it'll change my opinion because I know what kind of code SOLID leads to, but at least I'll be able to argue more accurately instead of using a strawman argument.

I've been programming for ~11 years, in that time I've programmed professionally for ~10. I've worked in codebases that were truly SOLID and OOP and Clean Code, or were doing their best at least, and codebases that were simply trying to get things done. The difference is stark, and I wasted many years in the former.

Single responsibility principle

I will start with the basic argument: there is no way to quantify this. Therefore there is no way to know whether you're doing it right or wrong. This shows up as people disagreeing about whether a class is in fact single responsibility or not.

A guy wrote about a common misconception of the principle: https://www.sicpers.info/2023/10/ive-vastly-misunderstood-the-single-responsibility-principle/

When you write a software module, you want to make sure that when changes are requested, those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function. — Robert Martin, 2014

That clarification, I find, is no more useful than the original definition found on the Wikipedia page.

There is a more useful one stated by Martin (dunno why he wouldn't just use this statement):

Gather together the things that change for the same reasons. Separate those things that change for different reasons. — Robert Martin, 2014

It is still, however, vague and not useful on its own.

All changes happen due to "reasons" like changing requirements...does that mean all my code should be gathered together? That's probably not what he meant, but it would be a valid interpretation of his statement.

It seems to me like in general Robert Martin is trying to put together a thought that is more eloquently expressed by the beginning of the Data-Oriented Design (DOD) Principles (as specified by Mike Acton at around 11 minutes in).

The purpose of all programs, and all parts of those programs, is to transform data from one form to another.

If you don't understand the data, you don't understand the problem.

Conversely, you understand the problem by understanding the data.

If you have different data, you have a different problem.

(Emphasis mine.)

Man that is actually useful. We're talking about some ground truths now. DATA. The stuff we actually work with!

So perhaps we can start to work with "where does this data come from, what happens to it, and where does it go?" and organize our code around that, instead of having to load a whole organigram into our mind.

BTW this principle is meant to make code more stable, but organizations shift constantly, therefore the code will need to shift constantly as well, and programmers will need to add it to their JIRA board to update the code as the stakeholders switch around. The code is already structured like this by default and seemingly by nature, as observed by Conway's Law.

Open-closed principle

In modern programming it seems to mean use inheritance, so that you can extend the base class' behavior, without modifying the base class.

In principle it sounds good. However in practice, I've generally had to always touch the base class at some point. Why? Because, as per DOD, if the data changes, the problem changes, and the original class is no longer aligning with the problem, so it has to change...or you do the alternative which is painfully write the inheriting class in such a way that it has to carefully workaround all the problems of the base class.

I think this principle means well, but in practice it ignores the reality of programming.

In addition, in general, it led to the idea that a data class (however you want to call a class whose job is to represent data, in JS land it would be a Plain-old JavaScript Object, POJO) shouldn't be modifiable by outside code. That's ridiculous of course, so they way they work around it is by adding getters and setters. I don't use getters and setters, unless it's to modify another property when one of them changes. Otherwise I find them totally unergonomic, and they make it much harder to work with the data.

Getters and setters have their place, but it's not on every property, and probably not even on half of properties. Your data should be straightforward to work with, getters and setters make that harder. Follow DOD, not styleguide fads.

Liskov substitution principle

I don't mind this one. It means "if X says it implements Y or a derivative thereof, it should implement Y". It's a logical statement, and very easy to prove.

Interface segregation principle

I find this one is poorly thought out. It prevents deep abstractions, forcing one to do shallow abstractions. Abstractions are as valuable as the amount of complexity they hide. This is saying an abstraction is not allowed to hide very much. So what's the point of the abstraction then?

In A Philosophy of Software Design by John Ousterhout, Ousterhout already outlines a very eloquent argument for why this principle leads to worse software, by design.

Contrary to its stated purpose, this principle actively couples software more heavily, as it needs to know about more things to get its work done.

Caveat: "shouldn't have to ... about things it doesn't need to ..." is a phrasing which is infallible. Yet I've seen the code it produces, it is not maintainable code, it is highly coupled, but hard to reason about, code.

Dependency inversion principle

In theory, this is a good idea. And it's hard to come up with an argument against this.

The issue is that it states it as a rule, instead of as a suggestion. Generally this principle leads to a squared amount of files in the project. IMyThing which is the interface, and MyThing which is the class.

Very few things will actually need the implementation switched without the interface switched. A database layer might be a good use...but then again if you switch from one DB to another, you probably have to switch your model of interacting with that DB to begin with, so you need a new interface anyway, so your code will need to change anyway...Unless you use a very deep abstraction like a CMS on top of it. At scale that comes with its own problems due to performance, to the point that you eventually have to write queries directly, and oops there goes this principle.

Again, if you change the data you're working with, your program will need to change. This is just a fact of the matter.

The alternative, then

How did this happen?

Real programmers that get things done are very busy programming things and getting things done on complex projects. Until recently these programmers were hard to find in public spheres, although I argue now it is possible to find them in a previous post, Programming Role Models.


I hope the new year greets you well, and you can move upwards and forward towards your goals and towards a better life. For a better 2026!