SOLID, why do we need it?

Can Sözbir
6 min readOct 16, 2022

We know that bad code slows us down, but why do we write it? Every time we touch the bad code it slows us down, why do we write this stuff that slows us down?

Well, you have to go fast. You want to go fast, you do a good job. If you want to go fast, take your time, study the problem, and move deliberately instead of rapidly.

We can’t go fast by rushing, tearing through the code, and just making it work and releasing it as fast as we can. A programmer who is rushing like crazy is guaranteed to go slow.

What does wrong with the software? What are the symptoms of bad software? How do you know you have bad code? How does it slow you down?

Good code should explain what it’s doing. It should be boring to read because it tells you things obvious. But if you read a bad code, you’ll ask yourself, what the heck is going on there?

Symptoms of bad software;

  • It is rigid. The rigidity can be identified when nearly every change made to the code causes a cascade of subsequent necessary changes for dependent modules. When you make a change to a code if you need to change a massive amount of other code, that’s not good.
  • It is fragile. Fragility is the tendency of the code to break in many places even when you only change it in one place. You make one very simple change and a whole bunch of other things breaks but they break in parts of the code that have no relationship to what you changed. Fragile code breaks in strange ways, ways that you can not predict.
  • It is immobile. This is the inability to reuse code in other parts of your project. When you want to use a module already written before in your system, a module does what you need, it does more than that. It couples to some bizarre framework, it uses some weird database and the more you look at it the more you realize that yes you could use this code, but the problems you would be bringing in are so severe that you finally decide that it will be easier if you write it yourself.
  • The desirable parts of the code are so horribly coupled to undesirable parts of the code that you can not use the desirable parts of the code somewhere else.

The common thread of all of those flaws is; Coupling.

  • The reason the code is rigid is that the modules depend on each other in undesirable ways.
  • The reason the code is fragile is that the code depends on data structures in undesirable ways.
  • The reason that I can not take the desirable parts of a code and use them in my system is that that code depends on other codes in undesirable ways.

The bulk of the software design is managing dependencies, figuring out where to put code, and cutting the dependencies so that the dependencies don’t run in strange directions. How do you do that?

Here is a tree of function calls called the “procedure function call tree” that every application has.

We have the main program, and the main program calls some high-level modules, and these high-level modules call middle-level modules, and middle-level modules call lower-level modules.

The flow of control goes downwards. Which of these modules knows about the other?

To make it simpler. We have modules “m”, and “n”. The module “m” calls the function “f” within “n”. Which of those modules knows about the other?

It is the “m” who knows about the “n”.

How do we know the “m” knows about the “n”? How does the compiler know that the “m” depends on the “n”?

There is a statement in the source code of “m” that says “using n” if it is the .NET you are using.

Whatever language it is, the name “n” appears in “m”. There is a source code dependency from m to n.

And notice that the source code dependency and the flow of control point in the same direction. That is universal. To call one module to another, you have to have one module know about the other.

So, how do the source code dependencies run in the procedure calling tree? Must follow the red arrows.

High-level modules know about the low-level modules.

If we think about this, what rule does that violate?

Do you want your high-level modules polluted with low-level detail? This is what makes code hard to read, you’re reading code and you’re trying to get the idea of what’s happening at the high level, and all of a sudden you’re dealing with lower-level modules.

So if we want to make a change to low-level modules, we need to make changes to the higher-level modules as well because they are dependent. But that is insane, we don’t want details changing high-level policy, I want my high-level policy to be immune from details.

  • Why does code get rigid? Because we have got all this coupling down towards detail.
  • Why does code get fragile? Because we can make a little change on lower-level modules, and it can break a whole bunch of stuff above it.
  • Why does code get immobile? Because it’s tightly coupled with all this low-level crap.

What is Object Orientation?

There are three magic words in object orientation.

  • Encapsulation
  • Inheritance
  • Polymorphism

If we have an Object Oriented Language, we can put an Interface, the module “m” can mention the name of that interface and use it to call the function “f”. Also, the module “n” will derive from that interface.
Now the compile time dependency points against the flow of control.

This is what polymorphism gives you. The ability to create one module calling another and yet the compile time dependency point against the flow of control instead of with the flow of control.

If you have that power then you can take any of the red arrows on here and turn any one of them around. You suddenly have absolute control over your dependency structure.

And if you have absolute control over your dependency structure, you can avoid writing fragile, rigid, and non-reusable modules. You can get around what goes wrong with software by carefully deciding which direction the arrows between modules should point. This is what Object Orientation is.

Object orientation is about managing dependencies by selectively re-inverting certain key dependencies in your architecture so that you can prevent rigidity, fragility, and non-reusability. — Uncle Bob.

We have all heard before that object-oriented programming is for modeling the real world, and closer to the way we think.

But according to Uncle Bob, these things were made up by marketing people to sell the idea to executives who didn’t know what the programs were.

What are SOLID principles?

There are several principles we can talk about that take advantage of this aspect of polymorphism of object orientation. And they’re called SOLID principles.

I will write another article to summarise these principles. So, stay tuned!

Sources
Design Principles and Design Patterns, Robert C. Martin

You can watch the entire presentation from Uncle Bob himself by following the link: https://www.youtube.com/watch?v=zHiWqnTWsn4

--

--