Design goals and Complexity
"the young man or the young woman must possess or teach himself, train himself, in infinite patience, which is to try and to try and to try until it comes right" - William Faulkner

Programmers solve problems. How they solve each problem is a function of their skill, talent, knowledge & time. The resultant solution will resolve the problem with greater or lesser complexity in the design. Thus, I find thinking about how (and more importantly where) complexity is handled, a useful way to evaluate a design. For this I use the time-honored technique of having three levels:

Level Zero

(Below this level, the problem is not solved)

The programmer has provided a solution. However, the interface is a mine-field; click things in the wrong order, the program crashes. Or it works great, but you need to reread the documentation Every. Single. Time. Or the resultant surrounding workflow is a Rube Goldberg device. However it surfaces, the programmer has placed the complexity on the user.

Level One

The interface is well thought out and reasonably intuitive. Controls work as expected and the solution is robust - even bulletproof. The solution not only fits the larger context, it improves it. The code itself however, is hard to change (or even understand). It is not well-organized; Or is, but full of tricky, interleaved logic. Or over-engineered, over-patterned etc. Here, the programmer has placed the complexity on the maintainer.[1]

Level Two

The burden of managing complexity is on the current programmer. The person writing the code takes the time and employs the talent and skill necessary to find an elegant solution that reduces the code to the minimum complexity needed to solve the problem and does so in such a way that is understandable (and changeable) later: The user gains the benefits of a level 1 design, while maintainers are left with clean code to change.[2]

Implications

Level zero code is common; it's the default for new programmers and an uncomfortable amount of commercial software. The thing of it is: Too often this sort of code is derided (including by me) when there is both a de facto and a cost-benefit rationale for managing complexity this way. Short-term projects are one example; software written for one's own use is another.

Level 1 software can be very valuable and enduring. I tend to equate this type of code with the Hacker ethic in all senses of that term. And I don't mean that pejoratively - we all use hacked together solutions every day and much of the world's technology infrastructure is built on it. It is a practical and stable design level.

Having the skill (and the time) to write level 2 code is a rare and wonderful thing. Amidst the hyperbole, aspiring to be such a programmer is at the heart of the "Software as Craft" movement and is a worthwhile goal for anyone who aspires to be a professional programmer.

I don't believe level 2 is inherently better than a level 1 (or level zero!) - it's about context - however, I think that for regularly edited and changed code (i.e. much IT software), this level of skill is what's implicitly expected (if not gotten) by the customer. Ironically, the time needed is often the first thing that goes as a non-technical customer can only assess code quality based on level 1 considerations and so pushes for faster results because everything "looks" OK. Only later - when their investment can't be changed without major overhaul - do they realize there is something wrong. And so the cycle continues...

Summary

This model is handy in several situations including: Judging the quality of an actual solution; choosing among different solutions to a given problem; estimating - and even when to stop refactoring. And while I don't believe that all code should be worked until it exhibits level 2 quality, it is what I want others to think of the code I leave behind. And it is what I hope to encounter in theirs. That said, being a successful professional programmer requires (among many other things) the ability to write all three levels of code, and the judgment to know when each is appropriate to use.


[1] This may well be the same person who wrote the code. The essential characteristic of a level 1 design is that complexity is put off to future efforts, not the current one. Thus level 1 designs tend to be high in technical debt.

[2]How the programmer achieves this is a matter of personal preference and technique. I do not subscribe to the notion that any particular set of programming practices provides this - or inhibit it by their absence. It has always been the people, not their practices that is the essential determinant of quality. Anyone who says different, is selling something.