a bit of philosophy towards a practical cheat-sheet

0. Why?

There is a lot of literature available on software principles.

Some good examples:

They are a great read.

0.1 A reasonable cheat-sheet

Yet, they are long and not immediately available to one’s memory. For that, I have wanted to create a cheat-sheet.

Another thing I have wanted has been to link principles to core values. It helps with reasoning.

Why is that important?

0.2 Reasoning makes teams

I have noticed is that, in engineering teams, software principles tend to get thrown here and there; disconnected and as if they were gospel dogmas. We recite a one-liner and expect reverence to follow; regardless of the situation at hand. If there is a hint of doubt on one’s face then citing the name of the one-liner source (“…uncle Bob says that”) should convert even the most unfaithful. And for those rare and audacious non-believers then there is obviously nothing left but the “pyre” - “bad engineer!”. Easy. (sarcasm mode: on)

Here is the problem: I think that asking someone to take things on faith, on face value, does more harm than good.

We are forced to accept an opinion because otherwise we would be insulting the credibility of some revered source. How can someone not agree with uncle Bob’s one-liner? Regardless of the context. And just because somebody said so.

Having a great team, thinking & acting as one body, in synergy, wants members to be empowered; convinced that things are done in a way that makes sense to them.

To convince, being able to reason is key. And for that, I have found that we need to:

have a set of prioritised core values. Fundamental things that people can agree on. It is essential so as to allow a team to reach joint decisions.

be able to trace principles back to core values. Through reasoning, we deduce conclusions from values and form principles. They are no longer disconnected. They make sense.

keep laser-precision focus on what is more important. Should we apply principle A or B? Trace the principles back to the core values and then negotiation becomes clearer.

0.3 A compass

With that in mind then, I have tried to write down this cheat-sheet. A list of things that I always turn to when it comes to making a decision in software.

It has been acting as my compass. And I try to share it in every team I work with. I hope it helps.

1. Common ground

Let’s try and form a base.

On reasoning: To not lose ourselves, we will start as simple as possible. We will then take baby steps & link each one along the way. This should take us to a reasonable conclusion that we can always trace back to fundamentals.

Starting from the most fundamental statement that I can think of, here we go:

Problems cause pain. Repeated problems cause suffering. As people, our goal is to reduce pain and suffering. As Software Engineers, the less we suffer at work, the more we can focus on positive, proactive and creative work. Entropy is the measurement of disorder. In physics, systems tend to progress in the direction of increasing entropy i.e. more chaos. This applies to software as well. If we do nothing, things get worse. Complexity increases entropy. As such, software tends to want to get more complex unless we actively keep it in check. Complexity is many, small, simple things together, moving. Adding one more little thing can make something very complex all of a sudden (think of dimensions of variance and how many new combinations a single new dimension can offer). Most of our pains in software come from having more complexity that we cannot control. That’s when surprises happen. That’s when we start having headaches. As such, to achieve (1.2) as Software Engineers we need to find a way to deal with complexity always wanting to get bigger. It’s like our bodies wanting to get older and less fit unless we do something. Considering how entropy always wants to increase, the effort to beat entropy also tends to increase. It’s an arms race. To be ahead of the arms race we need to automate.

2. Simplification and cost

Complexity is reduced by simplifying. Making things simple is not simple. It’s also not cheap. And it never stops, because entropy always wants to increase. Different simplifications have a bigger or smaller effect. Under pressure, small ones may feel pedantic, that they don’t matter. But they do. That’s because of point (1.6) . Many small things can cause huge complexity. As such we need to strive to keep things as simple as possible. If we can catch small deviations at the beginning we will prevent from them growing into huge complexities.

3. Principles

3.0. Minimalism

“Simplicity, clarity, singleness”

“Everything Should Be Made as Simple as Possible, But Not Simpler” - Albert Einstein

“It’s the art of making complex things simple.”

These are some general principles that help with dealing with complexity:

3.1. Single responsibility

A thing should be responsible for serving a one, cohesive purpose. It should do it well and just that.

3.2. Separations of concerns

Contiuously breaking down a system to components where each achieves point (1).

3.3. Path of least surprises

If in doubt, a solution that is more consistent and offers fewer surprises is always more dependable and predictable. Hence less chaotic.

3.4. Continuous improvement

A system is never static. As such, no code should be considered as untouchable. Reality changes, requirements change. The system needs to adapt with it. Software should be changing as often as possible to reflect reality as close as possible, yet still remain simple. That is where the difficulty of software engineering happens. To keep up, while remaining simple. Otherwise you implode. Complexity arises.

3.5. DRY (Do not repeat yourself)

If one thing happens more than once then it’s a pattern. It should be done once and re-used. Otherwise, there will be 2 things that can start deviating from each other. That will create 2 dimensions of variance. That’s n X n combinations of results. Complexity has happened. See DRY.

3.6. Automate relentlessly

To be ahead of the arms race, we need to automate as much as possible. That forces things to be standardised, solid and repeatable. It allows us to worry about fewer things.

3.7. Code is read more often than written

Take care in naming things. They should indicate their role in whatever they solve. Not how they solve it. We spend more time reading code than writing. If that becomes hard then we waste time.

3.8. Only keep what is necessary