Software Development Patterns You Should Avoid
After more than a decade in software development, I’ve met developers of every stripe and witnessed all manner of bizarre development patterns. This essay walks you through these patterns and their characteristics.
IDD (IDE-Driven Development)
The greatest skill lies in what is left undone; the greatest wisdom lies in what is left unconsidered.
– Xunzi, “On Heaven”
IDD — IDE-Driven Development — is the path nearly every beginner must walk to enter the temple of software development. The IDE shields developers from a great many details, and with almost no configuration (compared to vim / emacs / sublime) it gives you code completion, code navigation, search, check-in and check-out — nearly every task you’ll ever perform in software development.
The harm, however, is obvious. Sink too deep into IDD and a developer, once separated from the IDE, becomes a headless fly: barely able to read code, barely able to write it, ignorant of how to compile, incapable of automating common tasks (such as taking an Android project from compilation to packaging to APK analysis), and unable even to perform basic git operations. Yet all these shielded details are the fundamentals of a software engineer — like the basic fingering of a pianist, they must be mastered. Imagine: if you can only read code inside the IDE, and without its jumps you can’t trace the thread of the code, what will you do when some code is only readable through a browser? Not read it? If you can only write code inside the IDE, and one day you can only write code by ssh’ing onto a server (don’t laugh — plenty of companies work this way, and plenty of situations demand it), will you just not write it?
Furthermore, if IDD developers can’t promptly extricate themselves from their extreme dependence on the IDE, they easily metamorphose into the next type.
- Target audience: beginners
- Comfort index: ★★★★★
- Hazard index: ★★★★
- The remedy: learn any shell-based editor
DDD (Debugger-Driven Development)
A competent programmer’s code is written line by line; an incompetent programmer’s code is debugged line by line.
– A Certain Someone, The Self-Cultivation of a Programmer
DDD — Debugger-Driven Development — is the inevitable reaction once IDD dependence reaches a certain depth. The typical manifestation: you write code without knowing whether it’s right, set countless breakpoints end to end, then launch debug mode and trace breakpoint by breakpoint. Find a problem, fix a problem (perhaps introduce a new one), until you’ve walked all the breakpoints several times over and slain every problem you hit. Then you wipe the sweat from your brow, curse under your breath — damn it, I’ve finally debugged this thing! — and call it a day.
DDD is a development style that squanders a programmer’s life. It pours our finite time and energy into infinite pointless thrashing. Because breakpoints are so readily at hand, programmers grow lazy about thinking, lazy about design — too lazy, even, to glance at the code they just wrote. One wave of the hand and countless red breakpoints are set; if something goes wrong, I’ll just debug it, right?
In truth, many concurrency problems cannot be reproduced or resolved through a debugger at all. Worse, DDD easily traps programmers in tunnel vision — we fixate on the tiny bit of state right in front of us and lose sight of the whole.
- Target audience: beginners
- Comfort index: ★★★★
- Hazard index: ★★★★★
- The remedy: spend more time thinking and designing; use TDD (Test-Driven Development); if you must trace state, use logging wisely rather than breakpoints
PDD (Print-Driven Development)
Since you, King, are fond of war, allow me to use a battle as an analogy. The drums roll, the blades clash, and the soldiers throw down their armor, drag their weapons, and flee. Some stop after a hundred paces, some after fifty. What would you say of one who mocks a hundred paces with fifty?
– Mencius, “King Hui of Liang, Part I”
Seeing DDD, the C programmer doing embedded work laughs: we don’t have that nasty habit — in most embedded scenarios, either breakpoints are too much trouble to set (you need a remote debugger) or they can’t be set at all (much kernel-space code, for instance), so our code is written, not debugged. But most of these programmers spontaneously band together and hoist their own banner: PDD, Print-Driven Development. The logic of their work looks like this:
// ...some awesome logic...
printf("haha, hit 1");
// ...some more logic
printf("!!!!!! hit 2");
if (awesome_check(awesome_state)) {
printf("####### condition captured")
}
PDD is a match for DDD — six of one, half a dozen of the other. The code PDD developers add is like the breakpoints DDD developers set: treat the head when the head aches, treat the foot when the foot aches. When the state somewhere is off, or the flow diverges from what was expected, they don’t stop to consider whether there’s a flaw in the design or why this result occurred — no, without a second thought they sprinkle in a print (set a breakpoint) to see what the state is. If they didn’t capture the right spot, they refine further, until they’ve passively stumbled onto the cause.
- Target audience: beginners
- Comfort index: ★★★
- Hazard index: ★★★★
- The remedy: spend more time thinking and designing; use carefully considered logging rather than throwaway print statements
BDD (Bug-Driven Development)
To view the sky through a tube, to measure the sea with a gourd, to strike a bell with a stalk of grass — how could one ever trace its patterns, examine its texture, or draw out its sound?
– Dongfang Shuo, “Reply to a Guest’s Objections”
Seeing BDD — Bug-Driven Development — I’m sure we all exchange a knowing smile. Originally I wanted to call this TDD (Ticket-Driven Development), which is closer to my intent, but to avoid confusion with Test-Driven Development I had to settle on BDD. This is probably the development pattern we’re most familiar with: at a software company with stable business (whatever its size), diligently maintaining existing code and cautiously adding new features is the primary duty of most programmers. At such companies, we’re less engineers than tinkers patching pots. Can’t understand the code? No matter — so long as you can read the logs (error messages). Can’t solve the problem? Don’t worry — finding a workaround to route around it is fine too. What’s more, when faced with some godforsaken issue you can’t read, can’t comprehend, can’t solve, and can’t even work around, a single stroke of the pen — not reproducible — and the issue is closed. Six months later, you’ve probably moved on to patch other pots anyway.
BDD developers practice the art of defense; their gorgeous defensive coding skills rival Andromeda’s Nebula Chains, guarding every inch of the system’s skin without a leak. If you see code where function A(a, b, c) calls function B(c), and even though parameter c is exhaustively checked at A’s entrance it is checked exhaustively again inside B (even though only A ever calls B), then this code was surely written by a BDD developer.
BDD developers’ horizons tend to be narrow; what they learn and use is confined to the existing system. Since the system isn’t their own work, and reading code means tracing back from a problem, their understanding of the system stays shallow. This isn’t from any lack of ability — on the contrary, those who do BDD work are usually very experienced programmers. But they’re hemmed in by the company’s demands, chased all day by tickets, run ragged, unable to improve effectively on the job, and gradually lost amid one crime scene after another, their horizons growing ever narrower.
- Target audience: “senior programmers” at companies with stable business
- Comfort index: ★★
- Hazard index: ★★★★
- The remedy: take the lead on a project yourself, or move on
RDD (Rat-race-game-Driven Development)
From day to day, we programmers dreamed of being an expert inside the team/company; however, when that day really comes we trapped ourselves.
– The Programmer Gentleman
These walls are kind of funny. First you hate ’em, then you get used to ’em. Enough time passes, gets so you depend on them. That’s institutionalized. They send you here for life, that’s exactly what they take. The part that counts, anyways.
– Red, The Shawshank Redemption
RDD — Rat-race-game-Driven Development — refers to the development pattern of spinning in place for an entire career. The rat race game is the classic example from Rich Dad Poor Dad — a rat running desperately inside a circular cage.
Every programmer strives to become an expert in their field. The price of expertise is enormous: years of accumulated effort to climb to the summit and don the hat of “expert.” Yet becoming an “expert” often means committing to a single road to the end — first, the accumulated momentum of the past is simply too great, and the opportunity cost of turning around too high; second, your employer pays you a higher salary precisely because of this, so you can only keep marching in the same direction.
We know software is a craft of engineering, not science. On the path of science, the farther you go, the rarer the equipment you craft; but in software at the same company or in the same industry, the farther you go, the more roads you find yourself walking again. You may be an expert in chip verification, so from your first job to your nth you do verification work — until one day you’re stunned to hear the position has been cut. You may be a master of bringing the web to the desktop, riding extjs high and mighty while the company depends on your skills to build its product — until one day nobody uses that product anymore, and you look at the market and find that your ninth-dan extjs prowess is less welcome than someone who’s just reached second dan in React.
RDD is like the high walls Red spoke of. When you’re mired in RDD and can’t pull yourself out, quietly, the very ability you were once proud of and relied on for survival becomes the greatest obstacle to your survival.
- Target audience: “experts” at large companies
- Comfort index: ★★★★★
- Hazard index: ★★★★
- The remedy: move between different teams within the company, or move on to a more challenging company
Having written all this, one of these patterns surely fits you. Have you found your own favorite development pattern? If not, congratulations. If you have, don’t panic — correct it if you can, and strive harder if you can’t.