Zen and the Art of Software Development

A good while back, “Uncle” Bob Martin tweeted the following:

It’s easy to read that tweet and imagine an insufferable coding diva who demands the very finest mechanical keyboard and has a software rider a mile long.

This clearly isn’t what Uncle Bob had in mind, though. The point he’s making is that rushing is never the right thing to do. Try to move quickly, sure. Be mindful of the timescales and deadline, or course. But don’t rush, don’t panic, and don’t make rash decisions.
It reminds me of another quote:

“Worried that TDD will slow down your programmers? Don’t. They probably need slowing down.”

J. B. Rainsberger

We all have deadlines to work to but rushing ahead full-tilt isn’t usually the best way to maximise productivity. The US Navy Seals have a neat, paradoxical mantra, which when the adrenaline is pumping reminds them not to charge headlong into a firefight and get themselves shot:

“Slow is smooth, smooth is fast”

Apparently the motto has its origins in the rifle range, where deliberate, controlled, coordinated action is more effective than desperate fumbling. Calm, considered action is ultimately more effective than going too fast and making costly mistakes.

I remember reading a while back about an interesting experiment where they had volunteers playing Pacman while wired up to sensors that monitored brain activity. The idea was to see how stress affected the brain activity of the subjects, and what the experimenters found was that when the subjects weren’t under much pressure and had plenty of room for manoeuvre, they used areas of the brain associated with higher-order cognitive functions and conscious awareness. However, when the subjects found themselves in a tight spot and had much less time to react, the more conscious parts of the brain shut down and the evolutionarily-older, more instinctive areas took over.

This seems to explain why, when we panic, we get that feeling of being less in control: our conscious thinking gives way to instinct and reflex as the pressure increases, and our decisions start to focus on getting out of the situation as quickly as possible to escape to source of our anxiety, rather that on taking a step back and working things through calmly.

This makes sense from an evolutionary point of view; we probably had potential ancestors who were weeded out of the gene pool when they were faced with a saber-toothed tiger and, instead of running like hell, carefully weighed up their options, carried out a risk assessment and gave due consideration to outsourcing their escape solutions to an external consultancy.

Writing software is a high-order cognitive process. It’s extremely abstract, requires significant concentration, and is therefore very difficult to do under fight-or-flight conditions. It’s more a job for the frontal lobe than the hypothalamus, which is the main reason you find very few lizards with committer status.

As a result, developers will do better work if they’re calm, relaxed and focused. We all know that feeling of being in flow, when you’re in an a nice feedback loop with your tools, nothing is getting in your way or interrupting you, and you suddenly realise you’ve been working for hours and didn’t even notice. Sadly it doesn’t seem to happen that often, but this is the state in which developers should ideally spend most of their working life: in a calm, focused state making steady progress, rather than in a frenzy of panic because the code has to go out tonight.

Stress and pressure causes errors and lead to shortcuts being taken that cause further work. If the house you’re building is on fire, you need to down tools, put out the fire and assess the damage, not try to build faster.

So what can you do? We don’t live in a ideal world. People are messy: we don’t always do the right thing, we don’t always make good choices, and our circumstances are often far from ideal. 

I’ve always liked the following advice:

Grant me the serenity to accept the things I cannot change, courage to change the things I can, and wisdom to know the difference.

Reinhold Niebuhr

What You Can’t Change

  • Estimates are hard, and you’ll get them wrong.
  • Customers will always demand more than you can deliver.
  • Your tools and processes will never be perfect.
  • You will often have to make compromises.
  • You’ll make mistakes.

What You Can

  • Don’t try to do everything. Successfully juggling three balls is a better result than dropping ten on the floor.
  • Take time to think things through – a stack trace isn’t a predator you can defeat with adrenaline and a piece of flint.
  • Leave some slack in the schedule. Accept that developers don’t spend 100% of their day writing code, and that things will come up you didn’t plan for.
  • Leave room for error. Estimating is hard and mistakes will be made.
  • Invest in your tools and processes to give you a safety net and allow you to focus your effort where it counts. Spending a week automating a manual, error prone process that takes a day but needs doing every release is time well spent.
  • Pay down technical debt. Building on shaky foundations never ends well.
  • Minimise interruptions and distractions. Pulling one person into a 1-hour meeting will cost 2 hours when you factor in the cost of context switching.
  • Recognise that quality isn’t an overhead: it’s a cost reduction.
  • Be honest with yourself, your team and your customers.
  • Remember to breathe 🙂

Not a Jerk

Joel Spolsky wrote a long time ago about a simple rule they used at his company when deciding whether to offer an interview candidate a job: Smart and Gets Things Done. It was a rule he’d picked up from his time at Microsoft, but he quickly realised they needed a third rule: Not a Jerk.

Software development is a team game, and no matter how much you know, or how finely-honed your skills are, if you can’t interact with other people without upsetting them, you’ll do more harm than good. This applies to everyone except Linus Torvalds: Linus gets a free pass because he wrote the OS that runs most of the things.

I’ve been working in software development for over 18 years, and I’ve been lucky to work mostly with smart, competent and pleasant people who pass all of Joel’s tests. No one’s perfect though, and I’ve noticed some tendencies in myself and other developers that I suspect we’d all be a lot happier – not to mention more productive – if we tried to avoid.
They say the first step is admitting you have a problem, so here goes:

Hi, I’m Adam, and I can sometimes be a jerk.

Before I get started, I want to clarify that I don’t believe that these tendencies are unique to developers: some might be, others probably apply to anyone doing knowledge work, and some are just examples of general human behavior. However, most of my professional life has been spent working in software development teams, so that’s my frame of reference.

I’m also aware that my own take on these behaviors won’t be universal, and that there’s a chance I might be about to announce a set of unique and appalling character flaws to the world. Oh well. Finally, and most importantly, my objective here is absolutely not to incite people to start accusing their colleagues of being jerks. Warning: this product is for internal use only.

Knowledge Is Power

In software, as in all knowledge work, your skills and knowledge are a big part of what you have to offer to your team, your organisation, and the world in general. As a professional, they form part of your self-image, provide a sense of security and accomplishment, and affect how you’re seen by your peers. They’re your greatest strength, but as the same time your greatest vulnerability: if you cease to know the right things, you cease to be useful, and in software, the things you might need to know are myriad, and change quickly.

As a result, developers can be understandably sensitive when it comes to their skills and knowledge, and this can lead to some unhelpful behaviour.

Technical Posturing

Transferring knowledge and applying our skills are core parts of our job, and most technical folk like to talk nerdy now and then. Other times though, we stray into showing off, asserting superiority or even into outright intimidation. We’re a bit like a peacock, only instead of feathers we have Big O notation and Apache committer status.
A good example of this is a comment I overheard a while back:”How can you call yourself a developer if you’ve never heard of tcpdump?”

There’s a lot to know about software development, and no one knows every language, tool and esoteric computer science fact. Nevertheless, most of us are able to function pretty well, design and write good code, and look stuff up when we need to. Belittling someone on the basis of some arbitrary thing you happen to know is irrational, petty and harmful. Our focus should be on applying and sharing our knowledge, rather than putting it on conspicuous display. In terms of information exchange, the two might be equivalent, but the effect on the people you’re interacting with is fundamentally different. Consider a situation where someone has a problem, and you realise you might have the solution.

Compare:
“Well obviously the answer is to use X. I’m surprised you didn’t consider it, but I can do it for you if you don’t know what you’re doing.”

with:
“Have you considered using X? I think it might work in this case. Happy to give you an overview if it’s not something you’ve needed to use before.”

Fear of Being Wrong

The corollary to Technical Posturing is being overly defensive about criticism, even if the criticism in question is constructive. No one likes to make mistakes, and no one likes being wrong. However, our work is complicated, and even the best developers make mistakes, miss opportunities or overlook solutions.

A few years ago I was having a discussion with another developer about a technology I’d been working with a lot, and they made a point I hadn’t considered. I felt bad that I hadn’t thought of it, and my reflex was to look for reasons to disprove the point, because at an emotional level it would be easier for me if they turned out to be wrong. After a fairly lengthy debate we decided the only way to be sure was to test it. I wrote a simple test, and the other developer was right. If I’d been more open-minded and less concerned with protecting my ego, we would’ve reached the same conclusion a lot quicker.

The trick here is to not beat yourself up about making a mistake, or not knowing something, or not having thought of something. These are all things that happen to everyone, no matter how highly skilled and experienced, and the more you obsess over them, the more likely you are to focus on trying to fight the situation rather than learning, fixing things and moving on.

Try to bear all this in mind when you spot a mistake made by a colleague. Yes, it feels good to track down a bug in someone else’s code, but try to suppress the urge to run over to their desk, yell, “In your face!” and do a little dance. I once worked with someone whose shadenfreudic glee when someone else made an error was positively palpable. It as annoying as it was exhausting.

Not Invented Here

Learning new things takes a lot of effort, and means going through a period of uncertainty that can feel unpleasant. We also have an innate tendency to assume that we could do a better job of solving whatever problem is being tackled, or would at least go about it in a way that would make more sense to us. All of this means that we’re sometimes reluctant to choose solutions that involve technologies or ideas we’re unfamiliar with.

There’s a lot to be said for maintaining a healthy level of skepticism whenever we’re evaluating anything new, but we need to be careful that our intellectual inertia and technical prejudice doesn’t get in the way of choosing the best solutions.

The more subtle variation on this is a tendency to stick to working with parts of the system you’re familiar with or have more control over, and to treat the other parts as black boxes. This can lead to us making unwieldy changes to a part of the system we know well in order to avoid having to dig into an area we’re less familiar with. Often the right answer is to take a deep breath and dive into the code.

Hype Cycling

On the other side of the Not Invented Here coin is the tendency to want to use whatever new and shiny technology is currently generating the biggest buzz among people who do their work on an Macbook Pro in the nearest pop-up artisanal coffee shop*.

Again, there’s a lot of sense in wanting to stay up-to-date and try out the latest tool, language or platform, but you start to get into problems when you’re constantly introducing new technology into the project, or when you’re picking technologies based on whether you think the other developers will tease you in the playground if you’re not using them.

Us vs Them

As well as a need to feel valued and useful, we also have a powerful need to belong, almost certainly stemming from a time when being rejected from the group meant death by sabre- toothed tiger. Sadly our hypothalamus takes a while to catch up, and is still interpreting office spaces and social functions as scenes of life and death struggles for survival. The problem with the need to belong is that it requires us to identify with a particular group, which naturally leads to the identification of the Other, and as history tells us, this more than any other aspect of human nature is the greatest cause of our being complete and utter jerks.

Tribalism

If I identify with a group, I feel protective of it. I want what’s best for that group, and I’m more likely to be suspicious of other groups. This can cause problems when the only group I identify with is my immediate team, or department. The irony is that while its easier to identify with the most immediate group you belong to, usually that group has shared interests with wider groups, extending outward to the super-set we’ll call People. The wider we can cast our identification net, the easier it is to focus on our common goals.

User Blaming

A special case of Us vs Them happens when we allow ourselves to begin resenting our users and stakeholders. It’s easy when you’re battling day to day with the trials and tribulations of writing code and maintaining systems to forget that the entire point of what you’re doing is to make life easier for other people. You start to feel an affinity to the system and the team rather than your customers, which makes you more inclined to dismiss concerns and issues as the fault of the user, rather than as a symptom of something you ought to fix.

A user might raise a support ticket and when you read it, it quickly becomes clear they don’t understand some fundamental part of the system. “Ha, here’s someone who shouldn’t even have an account!” we might say, but really, in all likelihood this is a perfectly intelligent and capable person who’s just lacking information, so the response should really be, “If this is so fundamental, how has this person misunderstood, and what’s the best way to make sure this is as obvious to our users as it is to us?”

In the interests of balance, this also works the other way, too. All developers are also users of other software and depend on other systems, and we’re often the most critical and grumpy of customers.

Here’s the thing though: the person who build that system you’re so angry at is, in all likelihood, just like you, trying to do their best with what time and resources they have. Your snark and vitriol aren’t going to help them do a better job, and will probably make them a lot less likely to want to help you any time soon. So, if you’re having problems, raise a ticket, submit a feature request, or send an email explaining what you’re having trouble with. You’ve worked on resolving support problems before, so you’re well-placed to provide them with exactly what they need to fix things.

Guidelines for Not Being a Jerk

So if this is all so clear, why are we still such jerks a lot of the time? It’s easy to call out these sorts of behaviour, and yet we all do them anyway. I’m not a natural people person, so I tend to try and find useful rules I can stick to that act as guidelines in moments of doubt. Here, then, for what it’s worth, are my Personal Guidelines for Not Being a Jerk, which I need to do better at sticking to:

  1. Give credit where it’s due.
  2. Say please and thank you.
  3. Share knowledge and freely admit to your own ignorance.
  4. Don’t say something behind someone’s back that you wouldn’t be prepared to stand by if you realised they were stood behind you.
  5. Let people know you appreciate their efforts, and that you understand their circumstances.
  6. Let people know you respect them, even if you don’t agree.
  7. Keep an open mind, but not so open your brain falls out.
  8. Unless you have clear evidence to the contrary, assume people are acting in good faith and doing their best.
  9. Don’t pass up an opportunity to make someone feel better about themselves simply by telling them the truth.

Finally, there’s a quote by Hemingway** I try and remember when insecurity starts to get the better of me:

There is no nobility in feeling superior to your fellow man: true nobility is being superior to your former self.

The Dalai Lama is away.

* Gross stereotyping is also bad.

** I’d love to be able to say I came across this quote because I’m all about reading Hemingway; the truth is I got it from the film “Kingsmen”

I’m Not Leaving My Wingman

Top Gun (spurious beach volleyball scene notwithstanding) is an excellent film, and conforms admirably to the 80’s action genre template:

  • Troubled but gifted protagonist
  • Ill-advised love interest
  • Arch rival
  • Wise old mentor
  • Training montage
  • Risky special move / prototype weapon
  • Learning of important personal lesson
  • Moment of crisis overcome by belief in one of either: a) self, b) higher purpose, c) the western free world
  • Rousing rock anthem to close
Image for post
istockphoto/tstajduhar

Of these, it’s the learning of an important personal lesson that concerns us here, which in the case of Top Gun was Maverick’s “I’m not leaving my wingman” epiphany.

Having learned in a previous scene the dangers of breaking formation in order to pursue personal glory, Maverick sticks to his training during the final dog fight with multiple faceless Soviet pilots, and stays with his designated partner aircraft despite pleas from another pilot to help him with the bogeys on his tail.

“I’m not leaving my wingman,” insists Maverick, and as a result he’s able to provide cover for the other plane before going on to save the day to the tune of an awesome guitar solo. I’m not ashamed to admit the scene still gives me goose bumps, although given earlier events in the film, the term “goose bumps” is unfortunate.

As a result of watching this film during my formative years, I associate the phrase “I’m not leaving my wingman” with any occasion where someone sticks to their guns while under pressure as the result of lessons learnt from bitter past experience. Which brings me to software development.

In software development, we generally know what we ought to do, but are often under pressure — either from others or ourselves — to do otherwise. We’ve all checked in the quick fix rather than do the refactoring, telling ourselves we’ll correct things later, only to be bitten by it in the future. It’s hard in the face of delivery pressure to do the right thing, so I propose adopting “I’m not leaving my wingman” as a mantra in times of doubt.

“We can merge the branch and do the regression testing in the next release,” a teammate might say. “I’m not leaving my wingman,” we should respond. No time to set up a CI build? I’m not leaving my wingman. Surely no need for source control so early in the project? I’m not leaving my wingman. Do you really need to pair-program on that feature? I’m literally not leaving my wingman.

The benefits of this are twofold: for one, it helps keep us honest and true to our discipline. Secondly, it makes us appear slightly unhinged, discouraging further suggestions, or approaches of any kind, by anyone. (If this fails, try carrying round a set of dog tags which, when questioned, you can squeeze while closing you eyes and whispering, “Talk to me, Goose…”)

That was “Thought for the Day”, now here’s Cheap Trick with “Mighty Wings”…

Prose Before Codez

Ernest Hemmingway once said that writing is easy: all you have to do is sit at a typewriter and bleed. The same could be said of coding, although you really need a computer rather than a typewriter. Writing code on a typewriter is a very long-winded way of going about developing software, and isn’t generally recommended unless you’re some kind of super-committed hipster with an bespoke typewriter and an artisanal hair clip to keep your epic beard from getting caught in the hammers.

Image for post
iStock.com/doomu

I like writing, and I like writing code. I especially like writing code that kind of reads like writing, but I try and avoid the opposite, because it’s very frustrating and ultimately pointless, like region encoding and DRM.

I’ve been thinking for a while about the similarities and differences between writing and writing code, and I thought it might make an interesting post. Fortunately, as previously stated, I like writing, so here it is.

Know Your Audience

“The best audience is intelligent, well educated and a little drunk.”

Alben W Barkley

It’s well-established that when writing, you should keep your audience in mind. Who are they? Why will they be reading this? What will they be hoping to get out of it? What knowledge can you assume? How easily offended might they be? Is this really the right forum for that dick joke?

The hardest part about writing code is that you’re writing something that necessarily has to be consumed by two completely different audiences at the same time: the machine, and other programmers. The machine is precise, unwavering, pedantic, and utterly refuses to help you out by looking past the specifics of what you said to what you obviously mean, whereas programmers… well maybe the two audiences aren’t completely different, but nevertheless.

Writing good code is the art of giving the machine precise instructions in a highly constrained language while at the same time clearly conveying your intent to a human reader. Most bugs live in the gap between what the programmer intended and what they actually wrote, so it’s really helpful if you can express that intent as part of the code. The downside is that this can feel like a lot of extra work at the time, and it means that you don’t get to name your variables fun things like “foobar”, “l33Tsk1lZ” or “bumsex”†.

However, even if you hate your fellow programmers or work alone, the next person to come along and read your code might be a future instance of yourself, and they’re going to be really pissed off if you make life hard for them: about as annoyed as they are when you set the alarm the night before so they can get up early and exercise.

Don’t Make Me Think

“Thinking is the hardest work there is, which is probably the reason why so few engage in it.”

Henry Ford

Understanding code is hard work, especially code you’ve not written yourself. Even modern programming languages are heavily constrained in terms of how expressive they are for the human reader, so part of your job as a programmer is to make it as easy as possible for someone else to understand what the merry hell they’re looking at.

There are a lot of techniques you can apply here, but the main thing to bear in mind is that you’re trying to reduce the cognitive load on the reader. It might take longer for you to think of and type a precise, descriptive variable name, or to break a function out into several smaller pieces, but your team will recoup all that in time not spent furrowing their brows and cursing you under their breath.

The same is true in writing. If you read what you’ve just written and find yourself stumbling over a sentence, something needs to change. Maybe you need to put a hyphen between two words to clarify something which would otherwise be ambiguous, or maybe you need to reverse the whole sentence because the context at the end would help the reader interpret the point you made at the beginning. Again, all the extra effort you put into crafting and polishing the text makes it easier to absorb, allowing people to focus on what you’re trying to say instead of stumbling over how you’ve said it.

Less is More

“A smaller quantity may, counter-intuitively, prove to have greater impact than if there had been more of whatever it was that there was, in fact, less of.”

Ludwig Mies van der Rohe (early draft)

When writing, you should aim to express yourself as succinctly and simply as possible. No one will thank you for making them read something that didn’t add any value, just as no one will thank you for making them read code that’s duplicated or unused.

That is all.

Read

“I’m one of the few people who’s written more books than I’ve read.”

Garth Marenghi

It would be ill-advised for someone to attempt to write anything of much importance if they hadn’t read that much, but I’m pretty sure when I graduated with my Computer Science degree back in the heady days of 2001 that I really had written more code that I’d read. That’s preposterous. You learn to write well by reading good writing: you learn to code well by reading good code.

Step Away from the Keyboard

“You’re not paid to think! A mindless worker is a happy worker!”

Professor Farnsworth

When writing or coding, most of the really important work happens before your hands touch the keyboard.

There’s no point in sitting down and trying to write something if you’ve given it little prior thought. Sure, there comes a point when you need to actually start typing in order to thrash out the details, but you need some sense of where you’re headed before you start, and it’s easier to work that out if you’re lying in the bath drinking cheap Merlot than if you’re sitting in front of an uncooperative text editor being badgered by the spell-checker. ‡

Likewise, there’s no point in typing frantically into an IDE if you have no idea how your code is going to work. Before you start, you need to understand the problem you’re trying to solve and roughly how you’re going to go about it. At the very least, you need to be able articulate clearly what it is you’re trying to achieve.

Kill Your Darlings

“In writing, you must kill your darlings.”

William Faulkner

Sometimes you can spend a significant portion of time lovingly crafting something, only to find yourself suspecting that what you’ve produced is, in fact, a steaming pile of crap. This is fine: it’s part of the process. It’s not always possible or sensible to try and work out where a line of thinking will take you before you’ve made a start: sometimes the result has to be staring you in the face before you know for sure.

However, just because you spent a lot of time on something doesn’t mean it’s valuable. Don’t be afraid to delete whole paragraphs that add nothing, and don’t feel bad about putting that beautiful-but-ultimately-useless class to one side and doing a git reset — hard.

Don’t Be Clever

“It’s such a fine line between stupid and clever.”

David St. Hubbins

If someone has to be a genius to understand what you’re trying to convey, in most cases, you’ve done a bad job. Likewise, if someone needs to be a Linus Torvalds-grade propeller-head to understand your code, in most cases, something’s gone wrong.

Just because something is clever (an obscure word, or a little-know language feature), that doesn’t necessarily mean it’s a good idea. All else being equal, if there’s a simpler way to do it, do it that way. Your job is to make life easy for everyone else, not to show off.

Always Write Well

“It’s a funny thing, the more I practice the luckier I get.”

Arnold Palmer

One of the best ways to maintain and improve your writing is to always write well, no matter what you’re writing. It doesn’t matter if it’s an email, a comment on a blog post, or a text message: always aim to communicate clearly.

The same is true when writing code, although if I’m honest I find this more difficult to stick to. Just because this code is part of a unit test, that doesn’t mean it shouldn’t still be readable and clear: in fact it might be even more important.

Prose Before Codez

“Without requirements or design, programming is the art of adding bugs to an empty text file.”

Louis Srygley

How may times have you started to write some code only to realise you didn’t fully understand what it was you were trying to do? Likewise, how many times have you started to explain something you thought you understood to someone else, only for it to slowly dawn on you that there were whole aspects you hadn’t thought about, and now you feel kind of silly.

The act of putting ideas into words forces you to think clearly and precisely, which isn’t how the human brain works a lot of the time (at least mine doesn’t). We have a lot to think about, so we tend to bleep over things and make lazy assumptions. However, once you’re putting those fuzzy thoughts into words you’re forced to make choices about how to express them, and those choices force you to crystallise the, you know, fuzzy stuff.

The upshot of this is that it’s often a good idea to write down what it is you’re about to try to do before you start. Do you really know what the requirement is, or are you working off the back of a one-line user story? Can you define the scope and purpose of your system, let alone the change you’re about to make to it?

Conclusion

Conclusion — noun; a concatenation of “concussion” and “illusion”. To browbeat a victim until they hallucinate understanding.

Writing and coding are both hard to do well, but nevertheless very worthwhile and often overlapping and complementary. No matter how long you do either, there’ll always be room for improvement, and I’m starting to suspect there’s a limit to how well you can do the latter without putting effort into getting better at the former.


† This is a real one taken from some code I reviewed quite a while ago. It’s second in it’s inappropriateness only to the name of a test method I wrote while testing a security feature, which in all innocence I decided to call “attemptToDoForbidenThingsOnBackEnd”.

‡ This works for me at any rate: your millage my vary. Also bear in mind that drinking in the bath violates most companies’ open-plan etiquette, so work from home or pick your moment wisely.