Getting It Right versus Being RightPosted: May 8, 2008
My undergraduate degree was in philosophy rather than computer science, and while many people might feel that a philosophy major is incredibly impractical, in many ways it helped me hone a lot of skills that are tremendously useful as a software developer. One of the more important things it taught me was to learn how to be wrong; to do philosophy well, you have to stop caring about being right and start caring about finding the right answer. Trying to be right implies that you care about convincing other people that your position is right, and about having other people agree with you; your goal when writing or discussing things is persuasion. On the other hand, trying to find the right answer means that you don’t care about where the right answer comes from so long as it’s found, or at least you get closer to it; your goal when writing or discussing things then becomes to improve the state of knowledge and the state of the debate, even if it means having people disagree with you or having your arguments shot down.
It might seem like an obvious or silly distinction, but it’s a difficult one to internalize: we all naturally want for other people to agree with us, and we all naturally hold the views we hold because we think they’re the right ones, so the natural tendency is to dismiss contrary viewpoints out of hand and to attempt to, by force of will or rhetoric, convince other people that our beliefs are correct. Truly trying to find the right answer requires not just humility but also self-awareness.
So . . . given that we’re a software development company, what does this have to do with software? In my experience, the same principle is applicable to technical decisions: in an ideal world, developers should keep their ego in check, present alternatives as clearly and fairly as possible despite their own leanings, and be willing to accept criticism and to admit when better alternatives are proposed.
There’s a second half to the “getting it right” bit, though: whereas in philosophy the chance of actually settling on a real answer to a debate is effectively zero, in software there often is, given a problem and a certain set of constraints, a small set of fairly superior choices, and you do have some chance of actually landing on one of them. And once you do get there, you’re effectively done with that question: you’ve nailed it well enough that you don’t have to deal with it again until things change enough to render the decision no longer the best one. I think of that as “getting it right eventually.” An important property of software development is that getting that right answer is far, far more valuable than the kind-of-working answer; something implemented in 1000 lines of straightforward, consistent, flexible code is far more valuable than that same thing implemented in 5000 lines of hacked up, inconsistent, hard to understand code. That matters less at the start of a project, but as a system ages and accumulates code those little differences start to add up, and they can eventually be the difference between getting out version 5.0 and having the entire product ground to a halt under the weight of a thousand tiny bad decisions.
It’s also worth noting that, in my experience, no one remembers how many tries it takes you to get something right. No one remembers the three designs you coded up and threw away, what they remember is that you eventually got to the right answer. Getting to the right answer is hard enough, valuable enough, and persistent enough (i.e. once something’s right you stop having to fuss with it) that it’s all anyone will remember.
That all, of course, presumes that you have an organization that can actually function properly; a common, debilitating organizational pathology is to punish people for being wrong. Naturally, that encourages people to “be right” and try hard to convince everyone else that they’re right even when they’re not. That, naturally, pretty quickly leads to bad decisions and failing products.
So let’s assume that you work at an organization where failure is acceptable and that understands the need to fail a few times in order to really get the right answer. Here’s what you, as a developer, can do to take that idea to heart.
Present Your Ideas Clearly And Alternatives Fairly
Avoid the instinct to present positions you disagree with as some caricature that no reasonable person could possible take seriously; do your best to give them a fair shake. If you’re arguing with someone and they hold a reasonable position that they just happen to explain or defend poorly, do your best to construct a reasonable argument for their position before attempting to explain why it’s wrong, rather than picking on their poor explanation or defense. Likewise, avoiding glossing over flaws in your own proposals or using rhetorical tricks to convince people you’re right; be honest about the drawbacks and point them out yourself, then explain why the idea is still worth pursuing anyway.
Your guiding principle should be that, if all possible positions are given the clearest possible explanation and defense, the right one will be blindingly obvious to all parties, so you don’t need to persuade people or attack straw-men. (In some ways, that’s kind of the same idea as the US legal system, though how well that works in the legal system is an entirely different question). It might not actually work that way in practice, but ideally you should act as if it did.
Don’t Steamroll People
This one also might fall under the “well, duh” category, but it’s worth pointing out that some people have stronger personalities than others; if you’re one of those people, you need to be very careful not to win debates simply by tiring everyone else out or metaphorically beating them into submission. While being right might be satisfying, having people agree with you merely because they don’t have the energy to fight with you doesn’t do anyone any good.
Develop Your Wrong-Detection Instincts
Having a taste for what’s a good idea or a bad idea is a critically important, and quite difficult, skill for a software developer to have. You need to know when you’ve reached the best answer you’re going to get to versus when you’re sure your idea isn’t right but you just don’t know what a better solution is. When the answer feels wrong, keep pushing; maybe it’ll come to you in a month, maybe someone else will think of it, maybe it’ll never come and things will always be difficult. It can take a long time (years, even decades) to develop the instinct, but work on it: if things seem too hard, or too messy, or too inconsistent, keep pushing for a better answer, and be willing to recognize it if someone else presents it.
Don’t Be Afraid To Be Wrong
Developing a taste for what designs/implementations/architectures/etc. are better or worse takes time, and the only way to really get there is to just throw your ideas out there and see what happens. If people tear them apart, try to learn from it. If people don’t, and they agree with you, congratulations; you’ve just made a valuable contribution to the development effort! Even if you’re wrong 95% of the time at first, the 5% of the time that you suggest a better alternative is incredibly valuable, and the rest of the time you’ll be learning a lot. The worst thing you can do is to keep your ideas to yourself because you’re afraid you’ll be shot down. And the worst thing an organization can do is create an environment where it’s not okay to be wrong.
Be Wrong Gracefully
When your ideas are attacked, and the criticisms are valid, accept it gracefully. This one is hard because of the emotions involved; no one likes being wrong or feeling stupid, no one likes to be wrong publicly in front of their peers, and there’s a definite ego and self-esteem hit that results from it. Learn to be secure in your skills and understand that by being willing to put out ideas that could be attacked you’re actually helping to get to the right answers faster.
Optimize For Being Wrong
Getting things right in software is hard, so your development process should try to optimize given the reality of needing to potentially iterate on something multiple times to get it right. That can mean everything from agile development practices and rapid iterations to keeping APIs private until you’re sure they’re right. Assume you’ll do things wrong a few times and plan accordingly.