Proce55ing Source Code
Credit: Niels Heidenreich
In his book On Writing Stephen King argued that to be a good writer, you must be able to “Kill your darlings,” where, for the sake of keeping the prose moving, you must cut out the non-essential parts, no matter how well-written:
Mostly when I think of pacing, I go back to Elmore Leonard, who explained it so perfectly by saying he just left out the boring parts. This suggest cutting to speed the pace, and that’s what most of us end up having to do (kill your darlings, kill your darlings, even when it breaks your egocentric little scribbler’s heart, kill your darlings)…I got a scribbled comment that changed the way I rewrote my fiction once and forever. Jotted below the machine-generated signature of the editor was this mot: “Not bad, but PUFFY. You need to revise for length. Formula: 2nd Draft = 1st Draft – 10%. Good luck.”
Writing code is much like writing prose, but I think it’s even harder to cut your most beautiful ideas from a computer program. In software design, we have to research heavily and go through hours of trial and error to produce some of our solutions. It’s one thing to slash several paragraphs of prose crafted in a hour of brilliant inspiration, it’s quite another to throw away an inventive solution and the wisdom that came with it.
When we refactor, we seek to both reduce the amount of code and improve its logical flow. We use the term “elegance” to convey the ideal of well-written code. But there’s a nuance to this, we also need to avoid being clever for the sake of being clever:
In software design, when you find yourself feeling particularly proud of a neat little bit of design or code, stop and ask yourself how someone who didn’t give birth to it will regard it. If it turns out to be overwrought or too slick for the need, you should probably kill your darling and replace it with an ordinary solution that others can actually use, and not just marvel at. Darlings are sometimes characterized as being “ever so clever.” For an example, the phrase “ever so clever” is ever so clever.
Reading this passage, I can think of lots of times I’ve had to refactor code that was “ever so clever” and make it more straightforward. There is nothing inelegant about being straightforward, and your peers will appreciate it.
Some code falls on the borderline. Consider the following snippet from the MemexPlex codebase:
I managed to eliminate about 300 lines of code with this design pattern, and that’s great, but I also made the code much more difficult to comprehend. This is an example of the Decorator Pattern, where each object accepts an object of the same class as one of its arguments and then adds its own methods and properties to it. In this case, each object contains a section of HTML for building a complete web page, which the object accepting it then appends its own HTML section onto in in the appropriate place. I think this code falls in a gray area, not straightforward, but it increases maintainability dramatically. So it’s great so long as I’m the only one working with it.
Jay Fields also talks about the “Kill Your Darlings” concept as it relates to programming, considering it as a way to avoid stagnation:
George Malamidis taught me something about code attachment a few years ago: You always gain by allowing someone to show you an alternative solution. If someone wants to solve a problem in a different way, there are several gains to be had. If their way is inferior, you have an opportunity to mentor a team-mate. If their way is equally elegant, you’ve gained another solution, or point of view that may be superior in the future. If their way is superior you learn something new and the codebase improves. In exchange for these gains you only need to give up time. Time is valuable, but it’s also well spent on improving the ability of a team-mate or your personal ability.
I think killing your darlings extends beyond codebases and frameworks to languages themselves. At SpeakerConf 2009, I floated the idea that we should more actively seek to kill languages. Perhaps, after 3 versions of a language, it’s time for that language to be retired. Imagine what we could create if the resources dedicated to Java were instead focused on creating a successor to Java. Think of all the time that would be saved if backwards compatibility became a non-issue.
This is an interesting perspective, killing code, frameworks, and even languages as a means of forcing the programming community to improve the entire environment. It’s a way to fend off technology lock-in, like QWERTY for keyboard layouts, but for languages and frameworks. Look at what a huge standard the Zend Framework is, with tons of libraries and an enormous codebase, compared to the sleeker Code Igniter. One person’s code library is another’s baggage.
It’s another balancing act: learning from the mistakes of the past versus having the daring to venture into new solutions. Our code serves as a repository of our knowledge, and, if you’re like me, you keep libraries of old code around so you can quickly look up how you solved some bit of minutiae, like a string manipulation or regex expression, without having to figure it out again. If you’re also like me, you keep stackOverflow open all day looking for new solutions. The code I’ve written in the past has survived the trial by fire of a production environment, but it’s old, while the code I find online, while not as fleshed-out, will often provide a more modern and elegant solution.