Simple, beautiful software development
My current thinking when it comes to software development
My current thinking when it comes to software development
Both simplicity and beauty are awfully nebulous concepts. And yet, I find the pursuit of those things so entirely illuminating I have chosen them as the governing notions around which I shape my professional development.
It’s perhaps easiest to start on the common plane of the oxford dictionary definition of these topics, starting with the much simpler simplicity:
The quality or condition of being plain or uncomplicated in form or design.
This is a difficult definition to reason about, as it is essentially defined as an absence of another quality — complexity:
Consisting of many interconnecting parts or elements; intricate.
There is an inherent complexity when it comes to expressing human concepts in ways that computers can operate on them. Computers are inherently complex things; essentially sand that we’ve engineered to do some predictable things and built layers of abstraction on top of until they do things we can derive use out of. It is only with a love of that intricate, bespoke and extraordinarily complex relationship that I’ve become able to bend them to my will.
It seems odd, then, to espouse simplicity when designing software systems. However I submit that the pursuit of simplicity even given the complex nature of computers is the most useful characteristic to pursue in this design, with the goal of not only making computers do useful work but to help those who interact with them fit them neatly and seamlessly into their lives.
Caging complexity up into a simple, essentially magical black box
When facing any given problem in our lives we do not reason about the entire problem, but rather break the problem up into chunks that we can reason about in and of themselves. Having awoken in my typical daze of caffeine withdrawal I did not attempt to reconcile the froth steaming, coffee compressing and boiling of the water into a passable cappuccino but rather arrived at a favoured cafe at the agreed upon time of 10am and exchanged my credit card for the desired brew. In this exchange I have traded a set amount of choice for an optimized selection; instead of the vast array of ways I could combine my coffee, milk, sugar and water I choose the single option from the limited set of “Cappuccino, Americano or Latte”.
In designing software systems it is reasonable to take the same approach. If I am to try and make available the useful capacity to exchange goods for cash over the internet I will not “rack and stack” my own hardware, install operating systems, write software and finally make my service available to the world. While such a thing is possible it is akin to brewing my own coffee; I would create a poor estimation of what I endeavoured to. Instead, I would choose to consume an existing software package (likely Magento 2), and lease a virtualized computer from a large cloud provider. The vast array of choice is gone, but the results are far superior.
In essence software design is composing various of these little black boxes into a symfonic service that does some sort of useful thing for those around me.
The many and varied black boxes
Unfortunately the world of computing is an extremely diverse one. Even given our previous requirement of an setting up an eCommerce store there are innumerable combinations of these black boxes. There is:
Many cloud providers (Google Cloud, Azure and AWS being the largest)
Many different operating systems (Debian, Ubuntu, Fedora, Red Hat, OpenSuse, Windows)
Many different eCommerce software suites (Magento 2, Sylius, Spryker, OpenCart)
And even those are only a small slice of the requirements needed to make some sort of useful system for users.
It becomes necessary to try and identify “fault lines” in the software ecosystem; places in which one can group chunks of software together by their predictable qualities. If we are extraordinarily lucky there are already standards that govern how we should express our software that makes the underlying choice irrelevant — perhaps the best known being HTTP and HTML; the very standard on which this blog is built! However, more often than not there are no absolute standards on which the majority of the market has converged.
However, there are broadly common patterns that emerge over time — abstractions that have proven their superiority over the alternatives. These patterns are generally designed, then later ratified by semi official publications such as blog posts or so. Later, new implementations of that same behaviour arise such that a class of black box becomes apparent.
To try and return this heterogeneous set of solutions down once again to predictable components we need to understand the software ecosystem, and how each of our components fit into it. If we defer our own solutions to those being adopted by the wider industry we are likely to ride the crest of the technological wave, finding a large set of open source solutions to our problems.
Simplicity is then understanding the nature and constraints of the technological market and adopting solutions based where that is at, and where it is likely to go.
The discipline required to retain simplicity
My job particularly is predicted on the idea that continued development is always required. It is the nature of my position; given that I can build and release some thing that immediately replaces any necessity of my own repetition I make myself immediately obsolete. Accordingly, the temptation is to drive on and create ever more.
However, the painful truth associated with this indefinite trend of creation is that creation itself is not inherently valuable — indeed, just the opposite. By creating new things I can add new behaviour to a system making that system a little less predictable. Moreover, unless I am disciplined this new behaviour will modify the old, leading to a less stable and predictable system over time.
I am, by nature of my going work increasing the complexity of the system — making it less useful for those who currently derive use of it.
The pursuit of simplicity requires then a critical analysis of the total system with a view to remove some parts of it. To quote Antoine de Saint-Exupéry:
“In anything at all, perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away.”
While designing software to make its constituent components removable is not complex it is practically an extraordinarily difficult task to require us to face up to our previous failures when designing the software and remove them from the system.
Given the choice between retaining some software functionality and reviewing it critically too often we defer to ourselves and keep the functionality in the software “just in case”.
Keeping the software simple is then a combination of developing cognisant that we might be wrong and validating our assumptions before developing at all.
The beauty in the craft
While we can be tempted to forget in the frenzied implementation of some feature or other we are obligated to remember we craft these things for consumption by others. Couched in our comfortable offices, nice salaries and general hubris I conjecture that we have forgotten to take the time to appreciate and to share the beauty in our craft.
Software can be beautiful; indeed, for our software to be loved by our users we too need to pour our love into it — to all parts of it. To work together as a team on the single vision that defines our work; to keep in our mind the joy and delight of our users as they consume what we’ve built.
Like any other craftsmanship the success of what we write is not derived on some formulaic approach to solving the problem we have, but rather to being passionate about what we build. It is our obligation to take the time and the effort required to build beautiful software, and to share that software with others.
Simplicity is, in an ironic fashion a complex and nuanced topic. Beauty is even more subversive; harder still to pin down into some definable property. But being deliberate and disciplined in our consideration of these things while we do our software work can help focus us on what problems users actually have, and help users reach and take onto themselves the things we build.
Or something. ❤