Code, stress and entropy
By: Marc-Antoine Aubé
Tags: Software Development, Antifragility, Chaos Engineering, Software Architecture, Programming

Anti-fragility: Gaining from disorder

Some things benefit from shocks; they thrive and grow when exposed to volatility, randomness, disorder, and stressors and love adventure, risk, and uncertainty.

In his book Anti-Fragile, Nassim Nicholas Taleb classifies things in three buckets: fragile, robust and anti-fragile. In a best-case scenario, something fragile will stay unchanged. In a worst-case scenario, it will break. Something robust will stay as-is regardless of what happens, nothing gained, nothing lost. The last bucket is the one that is most interesting to me. The anti-fragile system will remain unchanged in the worst-case scenario, but improve when subjected to stressors, volatility or exceptions.

A good example of an anti-fragile system is our skeleton or our muscles. If you repetitively apply controlled stress, in the form of running or lifting weights, your body will improve. Your bones will get denser from the loading, your muscles will get bigger and stronger, your cardiovascular system will get more efficient at delivering oxygen where it’s needed. Your body slowly adapts to outside stress over time.

Shedding unused adaptations

There’s an inherent cost to all those adaptations, whether your currency is money invested in your architecture, or calories consumed. Unless subjected to those stressors regularly, your system will slowly get rid of those adaptations.

Our bodies have evolved over thousands of years with one major goal in mind: survival. It will let go of the extra muscle mass if it’s not absolutely required for your survival, because there’s an energy cost to keeping it around for nothing. Your body will optimize it away, unless you keep moving, jumping, balancing and lifting. Keeping unnecessary, energy-consuming adaptations is not a good survival strategy.

The same thing should be true for the code we write. Each pieces of a complex system should have to fight for its existence, and be disposed of when it’s not bringing enough value for what it costs. Sadly, this is often not the case. As a system is modified, its complexity generally increases, unless your team actively works against it.

The process of code refactoring can go a long way to reduce complexity and keep software entropy in check. Simplifying functions, extracting common logic, removing dead code.

Taking care of a codebase is often like tending to a garden: a little attention here and there, over time, goes a long way into keeping things orderly.

Keeping the desired adaptations

[…] if antifragility is the property of all those natural (and complex) systems that have survived, depriving these systems of volatility, randomness, and stressors will harm them.

What if you do want to keep those hard-earned adaptations?

Automated tests are a stressor we have in our arsenal that can help us improve and shape our systems. Either at the micro-level with unit tests, or the macro-level with system experiments, such as terminating a service instance to see how your system reacts. Software testing is a fractal, the same principles apply at every magnification level.

First, you start with a hypothesis, like “this function should react this way when receiving this input”, or “a new database read-replica should spin up when the load gets over this level”. Then you subject your code or your system to it, and make different assertions about the results. Chaos engineering, popularized by Netflix, is not that different from the kind of testing you are used to, it’s only happening at a different conceptual level.