My son, who is a developer with a few years of experience, posed this question to me recently at breakfast. I could tell he was a little distraught.
My answer was, “All the time.” I don’t think this was much of an encouragement to him. I later relayed this story to a colleague of mine, a person I regard as one of the finest programmers I’ve ever known. His response was immediate: “All day every day.”
This seems odd to me. I don’t see such thinking in other professions. I’ve never had a plumber confess to me, “You know, I suppose my work is ok, but I just can’t shake this feeling that it’s crap, no pun intended.” Can you imagine a doctor saying that? Can you imagine a doctor even entertaining that notion?
Why do we feel this way?
What is a Hack?
I suppose the first question we should answer is, What is a hack?
I first heard the word used long ago, long before I knew what programming was, long before programming was available to the masses. A hack writer, for instance, is one who pumps out low-quality, short-deadline pieces just to make a buck. Although some famous writers (Anton Checkov, Arthur Koestler) were hacks early in their careers just to pay the bills, hacks are usually portrayed as mercenary, more devoted to income than art. In fact, according to Wikipedia, the term comes from hackney, which describes a horse that is easy to ride and available for hire.
I believe some of this carries over to the software development world, but not totally. In our case, the emphasis is not on making money as much as it is short-deadline work of questionable quality. We work quickly, sometimes at gunpoint, and aren’t happy at all with our work.
Where’s the Fire?
I believe part of the issue is that we are so used to rushing our work. There are a number of reasons for this—we are working to a completely unreasonable deadline (this happens in agile projects more than we are willing to admit), we are trying to keep up with the other devs on our team, and we sometimes feel like imposters so we push our work through.
Whatever the reason, we rush. We pull a story, give it a cursory read, create a feature branch, and start coding. We tack on a unit test at the end and submit a pull request. Then it’s on to the next story.
When we do this, several things happen. The code review elicits numerous comments, further cementing in our mind that we’re just not very good. Testing reveals a plethora of defects, with the same effect. We actually slow the process down because of all the rework.
Probably the most devastating of the results of hurrying through our work is that we accumulate a mountain of tech debt. Just as a credit card is a short-cut to accumulating things without going through the hard discipline of saving for them, rushing to finish our story causes us to pursue low-quality solutions in the name of expediency. We don’t refactor our code, so we have methods that are hundreds of lines long with an unfathomable number of dependencies, making them almost impossible to test. The result is brittle code with inadequate testing. Our confidence is almost zero that we can make changes without breaking something.
All this adds up to a tech debt invoice that will eventually come due and we will not have the funds to pay it back. Eventually, we must declare bankruptcy and start over with a very low credit score. Low as in zero.
What Do We Do?
That depends on how serious we think the problem is. Is it really this bad?
Sometimes. I’ve painted a pretty dark picture that isn’t entirely true or fair. Whether the landscape is as bleak as what I’ve described or not, I think we feel that we could and should be better. And I know from experience on some projects that I’m actually understating the case.
On the other hand, we’ve all worked on projects that were not disasters.
Regardless, there are some things I’ve noticed in the way I work and in the way that many of the teams I’ve been part of work that contribute to our angst. Here’s a list that is neither comprehensive nor exhaustive, but it’s a good place to start. I’ll be elaborating on them in subsequent articles.
- We don’t design. We start coding immediately. We need to step back and try to understand what we’re doing and consider how best to accomplish it. This takes some time.
- We don’t collaborate. We talk a lot about teams and say we value collaboration, but we still don’t like to pair. Designs should be a team activity and even if we refuse to pair when we’re coding, we’d better collaborate with one or two team members when we’re designing. We avoid insurmountable problems and massive rework when we talk things through and explore options with our teammates.
- We hurry. This may be the root cause. We feel time pressure even when there’s no deadline. This is good—we shouldn’t dawdle. But if we rush just to get something out the door and pull our story across the board, the story will just get blocked because of the defects and rework. In the words of UCLA basketball coach John Wooden, “Work quickly, but don’t hurry.”
We don’t write tests. This may be the most efficient remedy. Unit tests make us reason about our code and figure out way things could go wrong. Well-written tests expose design flaws and suggest solutions.
Tired of Writing Crap
The biggest thing we can do to improve our code is to realize it ain’t so great. A healthy discontent with the situation will lead you to make changes. In an excellent rant on the Clean Coder Blog, Robert Martin put’s it very succinctly:
That, according to Uncle Bob, is the motivation behind the Software Craftsmanship movement.
That will be the motivation behind your metamorphosis as a developer.