Taxation without representation: why code maintenance fails– and how to fix it.

The software industry, as a whole, has fallen into a dismal state. Software development is supposed to be a creative endeavor, but often it’s not. An overwhelming portion (more than 80% on mature codebases) of software engineering time is spent on software “maintenance” instead of new invention, a morale-killer that contributes to the high burnout rate in software engineering. In spite of these sacrifices on the part of developers, code quality seems nonetheless to decline inexorably, to the point where many software projects become intractably unfixable after a certain amount of time. Not only is maintenance painful, but it doesn’t seem to be working very well. What causes this? How does it happen? There are many factors, but I think the biggest problem the software industry faces is organizational: by failing to allocate maintenance responsibilities properly, the result is that these jobs are done poorly and the legacy/maintenance load becomes enormous.

Before reading further, I ask the reader to peruse Jeff Atwood’s excellent blog post, a header for what I’m about to write. In my mind, the most important point he makes is this one: We should probably have our best developers doing software maintenance, not whoever draws the shortest straw. 

Code maintenance, as usually practiced, is dull and lacks creativity. It’s also usually a career tarpit, because new invention is generally superior (from a developer’s perspective) in terms of visibility, education and advancement. Maintenance work rarely delivers on any of these. Maintaining one’s own code is a crucial educational experience, in which the developer sees first-hand the consequences of her architectural decisions. Maintaining the monstrosities created by others? It’s not much of a learning experience after the first time it’s done, and it’s rarely visible either. This incentive structure is perverse, because a working, healthy system that fulfills known, existing needs (i.e. the outcome of a successful maintenance project) is of more value than a new one that may or may not prove to be useful.

Maintenance is extremely important work; it’s the upkeep of one of a software company’s most important assets. Unfortunately, certain systemic aspects of organizational cultures make it unlikely to be rewarded in accord with its importance. The consequence is that maintenance work tends to “roll downhill” until it reaches junior programmers who lack the leverage to work on anything else. The result of this is that maintenance projects are usually done by people who don’t have the organizational knowledge, level of skill, or, most importantly, the political pull to do the job properly.

Inept or even average-case software maintenance fails to improve the general health of the code. A few bugs may be fixed or reactive features added, but the overall health of the software tends to decline. Methods become longer, dependencies are added, junk parameters are added to existing functions, and the architectural intentions behind the original system are buried under thousands of hacks. Code maintenance as practiced tends to beget an even greater maintenance burden in the future.

What needs to change? There’s a simple answer. Give maintainers power. The reason why the vast majority of software maintenance projects fail to improve code health whatsoever is that the developers in a maintenance role (usually junior programmers with no clout) lack the political pull to do their jobs properly. Telling a more senior developer, who was “promoted away” from maintenance duties years ago, to drop everything and document prior work is generally not an option for the maintenance programmer. Nor is removing ill-advised functionality from interfaces (someone more senior is guaranteed to “need” that function) or declaring a project in need of a rewrite. This is the sort of clout that a maintainer needs to have in order to have any shot whatsoever at succeeding.

There’s a flip side of this. If code maintenance work implies power, it absolutely shouldn’t be delegated to junior developers who can’t yet be trusted with that kind of power.

Giving software maintainers power will remove most of the stigma associated with such projects, seeing as they are hated because of the lack of power they often entail. It’s taxation without representation. Often, the maintainer’s job is specified in uninspiring and untenable terms like, “Make it work exactly like the old system, but faster”. Bug-for-bug replications, as well as faithful reproductions of any software without a spec, are doomed to failure. Improving code health necessitates imposing change on client developers. Rarely are such costs considered tolerable for the sake of “mere” upkeep, and maintenance projects usually, for that reason, fail to provide lasting improvement. The low rate of success observed on such projects makes them undesirable, and therefore they are avoided by the most skilled developers.

On the other hand, if maintenance responsibilities were coupled with sufficient power to restore the health of the codebase, such projects could become attractive enough that those with skill and seniority would want to do them. People who work on a daily basis with software generally develop a deep interest in the system’s health, and this alone can be motivation to commit time to its upkeep. Software maintenance has the reputation of grunt work, but it really isn’t intrinsically unpleasant for all developers; there are people who would enjoy such projects immensely if they were properly structured.

On structure, it’s critical that a company of any size separate the “software engineer” job description (which currently entails creative, new invention as well as maintenance) into two separate job descriptions. One (I’ll call it the “software architect” track) exists for the creative engineers who tend to fail at maintenance efforts because of their inability to tolerate ugliness. The other (I’ll call it the “maintenance engineer” track) exists for the “Sherlock Holmes” sort who enjoy deciphering ineptly- or even hostilely-written code. Since qualified maintenance engineers are uncommon, and since most developers find that work undesirable, maintenance engineers should be paid highly. I would argue that a 30% premium is not unreasonable. Moreover, they must be given social status and clout, since their job is to be pains in the asses of developers who are potentially more senior than they are. If maintenance projects are structured and allocated in this way, it’s very unlikely that they will dominate engineering time as they do now.

One thing I would argue against, however, is any suggestion that the maintenance engineer’s existence should absolve developers of the responsibility for maintaining their own code. It doesn’t. Maintenance engineers may be given a supervisory role in code and design review, but maintenance of one’s own work should remain each developer’s own responsibility; otherwise, “moral hazard” kicks in. I will also note that it is a terrible practice for developers to be “promoted away” from maintenance responsibilities, those being delegated to less important folk, as a reward for a successful launch. If the launch’s success came at the expense of enormous “technical debt” (the interest on which is usurious) then a maintenance time-bomb has been built.

I’ve addressed the social changes required in order to allow successful software maintenance. What will this entail in terms of project structure? In-place maintenance of defective systems– any software module that requires full-time maintenance effort fits the bill for “defective”– will become rarer, with outright replacement more common. That’s a good thing, because software either enervates or empowers and the former kind can rarely be upgraded to the latter through incremental changes. Note here that I’m advocating replacement, not “complete rewrites”. In my opinion, total rewrites (unless specific efforts are made to avoid prior mistakes) are often as inadvisable as in-place maintenance; the latter keeps defective software on life support, but the former practice often generates new defects– often more flaws, on account of the time pressure that complete-rewrite projects usually face.

What is gained in doing all this? First of all, job satisfaction among software engineers improves dramatically. Instead of the industry being characterized by a gloomy, never-ending maintenance slog, the proper allocation of such work ensures that it’s done properly and quickly rather than being passed from one hapless junior developer to another. Second, engineer productivity goes through the roof, because engineers with creative and architectural talents can unlock them instead of being forced to contend with legacy misery. Third, employee retention is improved not only for individual software companies but for the industry as a whole. Instead of architecturally-inclined engineers being burned out in droves (I’ll note that people with strong architectural talents tend to be notoriously intolerant of ugliness, to a point that can be emotionally and intellectually crippling in software maintenance) by the legacy burden that is the current reality of the industry, they’re encouraged to make a career of it, the result being better software architecture across the board. The result of these improvements in architectural know-how will be better products– more comprehensible, more attractive, easier to improve and keep up, and more profitable.