Simplicity is Hard

Simplicity – the art of maximizing the amount of work not done – is essential

I would like to start with a quote by Brian Kernighan that resonates with my development mindset:

"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?"

I believe that on one hand this message serves both a powerful illustration of a need for simplicity in software modern development. However, on the other hand, it illustrates the great deal of damage that uncontrolled programmer’s ego and search for illusory perfection of code can cause. People are bad at understanding complex and abstract ideas. People are even worse at explaining these ideas. One of the fundamental challenges of modern software construction is the sheer complexity of problems it attempts to address. The only reasonable way to constructively deal with these challenges is to generalize, abstract, and decompose complexity into its building blocks and simpler forms; in my opinion, it is best to keep decomposition until no further logical interpretations are possible. Nature strives for simplicity in its every form, so why are we so against being and seeming simple? I believe that programming is a natural extension of human intellect. In this lies its wonder and also dangers.

Naturally, people attempt to generalize and simplify things that they do not understand or agree. Effectively, complexity opens a door to multiple unforeseen interpretations - 100 people, 100 ideas. This in a good thing when we talk about abstract concepts of art, music, love, and perhaps a meaning of life. However, this is a very bad thing when we deal with mission and life critical code. Software development and developers must never attempt to focus on produce “beautiful” or creative code. Our professional duty is to design and construct code that is functional, reliable, and maintainable. Simplicity of code play a fundamental role in each of these 3 elements. Functionality of code is being able to perform a fixed task. Functionality is simple by definition as long as it follows single responsibility - This code does this and nothing extra. Everything extra is an unnecessary obstruction to its level of simplicity. One may ask how reliable code can even be “unsophisticated” to address all possible problems thrown at it. First of all, one really should never attempt constructing such code. It is hard if not impossible and promotes complexity. Secondly, reliable code is one that works every time (within a design margin). It is arbitrarily challenging to determine if complex code works every time for it is just as challenging (if not more so) to test. The only way to systematically produce reliable code is to make its composition individually simple and testable. When it comes to code maintenance, one dirty truth of software development is that majority of the work we do has to do with legacy code. Every developer’s nightmare is to deal with undocumented yet sophisticated and arguably painting-worthy algorithm someone wrote 5 years ago on a napkin and transcribed into enterprise level banking infrastructure software. As I discussed above, people are bad at translating abstract ideas. If you truly want your legacy code to become your legacy, keep in mind that maintainable code is simple for it can be understood and improved by other people when you are no longer around. We might think that we write code to communicate with machines, but we really write code to communicate with fellow developers. Machines are stupid and will digest everything thrown at them without looking twice - garbage in, garbage out. People won’t.

Simplicity of code promotes healthy lean development without excess waste in the form of added “features”. “Features” are only features when customers openly recognize and desire added value. Otherwise “features” are simply wasting development time, complicate code, and consume valuable development resources. Agile is built around adapting to changes versus following an established plan. Simplicity of code development is to construct just enough to address the specific functionality and stop right there. When change happens, adapt and add the now-missing functionality, and stop again. As developers, including myself, we are guilty in our attempts to predict the  “what-if”s and foresee the larger plan when things are unknown. However, the things are often do remain unknown until they are not. Very likely your predictions are false yet you already built in all the possible features that the customer might ever want into your God-module with 32 input parameters. When tempted with in advance answering questions that no one yet asked (or ever will), just remember there is a big chance that You Ain't Gonna Need It.

Many of us probably have a living example of personal pet projects (I am oh-so-guilty!). We tend to work on our toy ideas for a few days, months, and sometimes years - an ultimate software contraption that would be able to do so many clever things. We may have a seemingly great idea, which we may also keep to ourselves - we know better. The unfortunate news is that people with money, influence, and ability to make things happen may actually buy into your grand idea of solo rogue-like development not understanding the magnitude of such project. Perhaps our ego and proprietorial attitude prevented us from conveying this magnitude to the management and fellow developers. Who would ever want to share code ownership, right? Wrong. Few years and millions dollars later, long time after many other developers moved on with their working software products and much simpler implementations, your project grew to be so complicated it had to be abandoned without any chance of resurrection. The implementation grew out to be so obscure and cumbersome, no one could understand how to use you grand creation; not even you.

The morale of this totally fictional example is not to be ambitious in trying to solve everything at once and alone. Be conservative in what you do, and be liberal in what you accept from others. Don’t waste in the name of creativity. Be simple and be humble.


To view or add a comment, sign in

More articles by Stanislav Cho

  • Be Adaptive, the Rest Will Follow

    In software engineering being adaptable is about managing variability and uncertainty. Management, Customers, and…

  • Algorithmic Morality

    Recently I've been asked the following question - partially seriously and partially as an entertaining thought: Can…

    11 Comments
  • Orphans of Software Engineering

    You are a kid, and you are building a birdhouse. You found some dusty warped wood planks in your grandpa’s garage –…

  • 3-Year Autopsy : Reflections & Projections

    It's been nearly 3 years since I found myself entering professional cohorts of practicing engineers. Scalpel, please! I…

Others also viewed

Explore content categories