It’s not simple to be simple

Dotan Reis
3 min readFeb 17, 2021

In my last post I talked about anti-fragility, which is a way to design software systems that can successfully cope with the complexities of the outside world. This time I want to talk about the internal complexity of our systems, and how to avoid it.

Zen drawings are simple, but not easy (from: https://fineartamerica.com/featured/japanese-zen-painting-of-bamboo-stalk-with-leaves-black-ink-on-w-awen-fine-art-prints.html)

To start off, how do we define complexity? In a classic talk titled “simple made easy”, Rich Hickey defines the difference between things that are easy and things that are simple. Something is easy when wee know exactly how to do it, it’s “within our reach” and we have the tools for it. Easiness depends on the level of context and the skills you have.

Driving is easy, but it’s not simple (Photo by Jaromír Kavan on Unsplash)

Simple things are things that are easy to understand and predict. They usually do one thing. They are easy to compose and can be described with usually just one concept. Simplicity is more objective than easiness — it’s easier to agree on it.

Software systems should be simple, they don’t have to be easy.

If your software isn’t easy (to write, to design, etc) — it will take longer to develop it. If it’s not simple, it will take longer to debug it, to understand it and eventually to improve it. In the long run, complexity is much more expensive than hardship.

This isn’t just how to write. Clean Code, TDD, and other reliability tools are great coding habits that make the software seem much simpler, which is important, but they can’t really force you to write simple software.

How to keep things simple

In another talk called “Hammock Driven Development” Hickey talks about how long it should take to design software (hint: a lot) and the benefits of taking the time to do it correctly.

Simplicity is a lot about planning. I like the anti-fragility method for this: think about all the things that could change in your business needs or in the external world, and how they will affect your system, and compose the system such that a stress will only affect one component, which could be hardened to respond to it.

You want flows of data in your system to be as isolated as possible. You don’t want them to interact with each other and influence each other. That’s unpredictable, prone to bugs, and most importantly — complex.

If you do those things, you’ll end up with well-defined, easily composable components. Not necessarily few components, but it will be clear what each of them does, it will be easy to improve the system and debug it if something fails.

The simplest programs are stateless, functional and are written in a single level of abstraction. Complex programs are stateful, have side-effects and internal dependencies, and combine high level functionality with opaque low level implementation.

“Simplicity is a choice” says Rich Hickey. It’s also a tradeoff — it takes more time and effort to write simple things, but if your software is going to stay with you for a while, it’s probably worth it. (Plus, who wouldn’t want an excuse for sitting in a hammock?)

Spaghetti. Easy, not simple (Photo by Mae Mu on Unsplash)

--

--

Dotan Reis

Software developer @ riseup. MA student @ The Cohn Institute in Tel Aviv University