Don’t trade simplicity for convenience

The following excerpt from the preface to The Go Programming Language from Alan A. A. Donovan and Brian W. Kernighan introduced the idea of a pernicious change – a change that trades simplicity for its shallow cousin, convenience.

I love the term ‘shallow cousin’.

From a distance, an increase in convenience is a good thing, right? Time and time again, across the last 25 years, I have seen the pattern of the ‘convenience wrapper’ be implemented and then brutally failing.

The convenience wrapper:

  • makes easy things trivial and complicated things impossible
  • must itself be maintained, so now you have two sources of complexity, the original code that you wanted to encapsulate, plus the wrapper.
  • grows with time. The more it is used, the more functionality is packed into the convenience wrapper, until you have exactly the same power as the bit you wanted to encapsulate – and exactly the same problems as before.

So, as a reminder to myself – ask yourself ‘is this adding convenience or creating simplicity?’

As Rob Pike put it, “complexity is multiplicative”: fixing a problem by making one part of the system more complex slowly but surely adds complexity to other parts. With constant pressure to add features and options and configurations, and to ship code quickly, it’s easy to neglect simplicity, even though in the long run simplicity is the key to good software.

Simplicity requires more work at the beginning of a project to reduce an idea to its essence and more discipline over the lifetime of a project to distinguish good changes from bad or pernicious ones. With sufficient effort, a good change can be accommodated without compromising what Fred Brooks called the “conceptual integrity” of the design but a bad change cannot, and pernicious change trades simplicity for its shallow cousin, convenience. Only through simplicity of design can a system remain stable, secure, and coherent as it grows.