Hi, I’m Josh Symonds

I blog about Ruby on Rails, coding, and servers

Don’t Code Defensively

Reading time 4 minutes

As an engineer, we’re responsible for creating things that people care about deeply. Whether you’re programming something as important as a car’s operating system or as silly as an iPhone game, our code touches lives. It’s no wonder, then, that the people who interact with our products feel strongly about them – and possibly about us, as well.

This can sometimes be a good thing. It’s always touching to receive a heartfelt letter of thanks and admiration from a customer. But much more commonly, you’ll hear complaints, demands, and anger.

Under a deluge like that, it’s easy to become disillusioned and bitter. I see it all the time: programmers who hide in their shells at the slightest provocation. They make excuses, shift blame, and refuse to own their actions. I think this attitude is ultimately cowardly – if you’re willing to take credit for the good things you’ve done, you have to “take credit” for the bad stuff too. And cowardice of this sort contributes to making bad code, since your goal is no longer to to solve your organization’s problems, but to shirk responsibility.

That’s what I call coding defensively – an entirely separate subject from defensive programming. Coding defensively mires you in your codebase. It’s hard to go forward because you don’t want more responsibility, and you can’t go back because it would be admitting error. And it’s a self-reinforcing cycle: once you start becoming defensive, it’s difficult to stop.

I was a defensive coder too. I struggled to own the results of my actions: I would refuse to discuss solutions in a sensible, level-headed way. It took me a long time to change my approach, and as part of doing so I wrote a list of maxims summarizing how I wanted to think and act. When I feel myself slipping I go over them to refresh my resolve. I’m publishing them here in the hope that they’ll help someone else as much as they’ve helped me.

No one gets it right all the time

First, you have to realize that people – even you – make mistakes. It’s not productive to pretend that it didn’t happen or that someone else is at fault: if you know in your heart that the responsibility lies with you, then don’t try to shift blame. It was your mistake, and part of being a human is making mistakes, so own that error with all your heart!

I found that achnowledging my fault and being accepting of it removed a lot of the impetus to be defensive. I no longer felt as ashamed of what I’d done or that I had to spend time and energy making excuses. The “excuse” is that mistakes happen: what matters now isn’t that the mistake occurred, but how you’ll go about addressing it.

Please don’t get me wrong – I’m not saying you should be making mistakes left and right flippantly. Avoid them if you can, through proactive testing, code reviews, and sensible QA. But they’ll still happen, even if you’re very good. Since you can’t change whether or not you’ll make mistakes, you may as well change your attitude to them.

Be friendly

In the face of anger or blame, don’t turtle up! Instead, kill them with kindness.

As I said way back at the beginning of this post, what we do naturally inspires passion in those around us. Frequently when people run into an engineering problem, this passion will turn to anger. By the time the problem has percolated to us the anger has found its target: the programmer responsible for creating the code in the first place.

Friendliness reminds the people you’re interacting with that you’re just as dedicated to a solution as they are. Resist when they try to brand you as an antagonist. Their reaction is natural because they believe you made the problem: but in fact, you’re partners together in trying to solve it, and kindness reminds them of this fact.

You’ll be surprised at the turnarounds you see in people’s attitudes when you’re unrelentingly friendly to them in return. And once the anger has dissipated, you can work towards a resolution.

Seriously consider solutions

Or, if you’re a Glengarry Glen Ross fan, “always be solving.”

Always Be Solving

Putting your existing solutions on a pedestal isn’t productive. There’s no inherent value to what you have other than that it works – and sometimes, not even that! Hand-in-hand with this, concentrating only on the potential downsides of new technology blinds you to potentially tremendous upsides.

Dismissing solutions out of hand – particularly if you don’t understand them or it seems like they’d be difficult to implement – is an easy, natural reaction. But what your stakeholders are searching for might exist outside your comfort zone. It might involve using a piece of software with which you have little experience, or, in the worst case, might be implemented in a programming language you don’t even know.

If it’s still more or less perfect despite those flaws, then you have to go for it. Your responsibility is to do what’s right, not what’s easy.

And guess what? Afterwards, you’ll probably feel way more comfortable implementing that solution again in the future, and professional growth is always pretty awesome… and leads to personal growth as well.

Your net effect is positive

Even in the face of overwhelming negativity or horrible problems, you have to remind yourself that your overall effect is a positive one. As humans, we spend an inordinate amount of time concentrating on negative experiences: in the past, perhaps, an embarrassing moment in high school that everyone but you has forgotten, and in your day-to-day job, the errors and problems you feel largely responsible for.

It can be helpful to remind yourself of the good things you’ve done too, and that, in the balance, the good outweighs the bad. Doing so gives you the courage to hold your head high, and gives you the self-confidence to tackle your problems head on, instead of hiding from them.

And that willingness to embrace reality is what prevents defensive coding. In the end, your willingness to act – and the attitude you have towards action – can mean more to people than what you do. By trying to be a proactive, positive force of good, you’re telling the people who care about your code that you care about it as well. More than anything else, that will garner their respect and admiration and lead them to believe you’re coding for them, not coding defensively.

Josh Symonds performs devops and server wrangling on cloud-scale infrastructures, deploys amazing web applications with Ruby on Rails, and creates awesome iOS apps with Objective-C and RubyMotion. He is founder and CTO of Symonds & Son, a development shop focused on quality and excellence.

Josh Symonds