Favor Elegance Over Simplicity
Everything should be made as simple as possible, but no simpler.
— Albert Einstein
As engineers, we are groomed to find the simplest solution that will work for our situation. The problem with simplicity is that it typically doesn’t scale (whatever that means to you). So what exactly do I mean by simplicity not scaling? Well, it’s hard to nail down an exact definition for scalable (many have tried), but in the context of a codebase, if you can add, remove, or refactor features without having to change any code that isn’t directly related to said feature and also change the behavior of an application by changing it‘s configuration (without code modifications), then I’d say you’re on the right track. Basically, you know it when you see it.
Simplicity strips out flexibility and doesn’t account for edge cases — it gets the job done, but doesn’t necessarily do the job well. You may be able to accomplish your goal in say, 1000 lines of code (I know, I know LoC is a terrible measurement of progress but bare with me while I make this point), but given edge cases, error handling, configurability, extensibility etc, a better solution would take say, 3000 lines of code. I hear you, that’s a 3X increase of code that needs to be reviewed, maintained and eventually, refactored. And this does introduce complexity. But not all complexity is created equal.
Let’s step back for a second and observe our universe. It’s huge and it’s getting bigger. It’s an incredibly complex construct with things much smaller and much bigger than our human minds are equipped to imagine. But for some strange reason, everything can be explained using mathematics. The reason why our universe is so easily “computable” is a mystery to us. But what we do know, is that given just a few assumptions (configuration), one could derive much of what we can observe (and much of what we can’t) and also predict what hasn’t yet occurred! This is an incredibly elegant phenomenon. Given all the autonomous processes that occur in nature, I don’t think anyone with a decent understanding of it would describe our universe as simple. However, it’s computability and predictability make it elegant at a level so fundamental we’re still making amazing discoveries.
One can apply this principle to software as well. When outright simplicity won’t do (and if you’re solving non-trivial problems it likely won’t), elegance is your best bet. By adopting a Twelve-Factor set of principles you are able to create an application architecture that allows the introduction of inevitable complexity to be a (mostly) non-disruptive process.
I believe that in the context of software development, when most people say simplicity, they’re actually referring to elegance on some level. If elegance is done well, it does give the illusion of simplicity in that complexity is only revealed through intentional investigation and insights. The idea is to allow for complexity to manifest itself through layers of perspective. For instance, if I’m using an application for the first time and have no idea how to use it, the interface should appear to be dead simple for me. As time goes on and I accumulate context and knowledge I should be able to opt into a certain degree of complexity as my knowledge and use cases evolve.
I’m not advocating the over-engineering of solutions here. I just want to frame simplicity in a way that doesn’t constrain creativity. I think we should absolutely continue ways to simplify unnecessarily complex systems (or at least encapsulate and/or automate it). But with the explosion of VR, AR, IoT and DevOps it’s hard to imagine a future where doing anything non-trivial is simple. But if we’re disciplined enough, it can still be manageable.