Focusing on Code Quality Can Be Premature Optimisation
Instead focus on product quality, of which code quality is a part.
When I was working on my startup Futurecam, one feedback I got from my colleague is that I set too high a bar for code quality, more than required, making us spend more time improving the code that should have been better spent on improving the then-mediocre product, such as adding features, improving the UX, adding onboarding, and more, which were sorely lacking.
This is a mistake that people like me who’ve worked at giant companies with very high engineering standards can make. I thought that good code quality is necessary for good product quality. But imagine we’re building a car, and I spend years polishing the steering wheel when the car doesn’t even have brakes. You tell me I’m doing it wrong, but I counter saying that we need a good steering wheel to have a good car. Focusing too much on code quality is like this. It’s missing the forest for the trees.
When I launched, I learnt that users’ notion of quality differed from mine. Given the high code quality, I perceived the product as very good, but needing more features and UX improvements. But users perceived it as merely okay. I realised that users can’t see the internals, that it has great code quality. They judge the product by the features, usability, visual design, onboarding, etc — everything but code quality. Your internal notion of quality can’t diverge too much from users’ notion of quality.
The solution is to work top-down rather than bottom-up: look at the overall product quality. Identify what needs to be improved: do you need more features? Are users being asked to make confusing choices? Is the navigation confusing? Are users making mistakes in certain screens? Are you asking the user to pay before demonstrating value? And so on. Evaluate the quality of your product as a whole. As part of this, if you find that the app is too slow, or crashes too often, or things keep breaking frequently when you launch a new version, then that’s the time to improve code quality, not before. It’s a problem when it’s a problem [1]. Premature optimisation is the root of all evil. And takes focus away from more dire needs. In other words, code quality is the solution to some problems. But if those are not the problems you have, you should focus on solving the problems you do have, rather than being the proverbial drunk who’s looking for a lost item under the streetlight because it’s brighter there than where he lost it.
Optimise product quality, by finding the biggest problem, fixing it, and repeating. Maybe the biggest problem is that your product has a confusing first-run experience. Solve that. Then look at your product again with a blank slate, and ask what the biggest problem is. Maybe your features are not being presented in ways users can understand or value. Solve that. Iterate again. And again. Each iteration may involve UX, product, or engineering improvements, whichever turns out to be needed. Let the product drive improvements, rather than having a preconceived plan.
This no different from how you optimise performance of code. In fact, you don’t pick one class and say, “First, I need to optimise this class”. Similarly, saying “First, I’ll optimise code quality” is wrong. Work on product quality top-down.
This requires us to tolerate bad code. Some of us who are excellent engineers have high standards. In fact, these high standards helped us become what we are. But they can also come in the way. So you should be able to tolerate bad code, just as an athelete needs to tolerate pain and push himself forward. For example, one part of Futurecam’s code — layout — is a complete mess. It was a mess earlier, and many rounds of subsequent ad-hoc changes made it worse, to the point where I wasn’t even able to work with it, so I asked the engineers who worked with it to make any required changes. But I learnt to tolerate this, which is a matter of pride for me, since it required getting out of my comfort zone. If you’re a great engineer, you need to get out of your comfort zone, too.
[1] The other situation in which code quality matters is if it’s slowing down your engineering team.
You do need a minimum level of code quality. You don’t want all variables global, named a, b and c, and code being copy-pasted in a dozen places instead of being refactored into a function. Such code may save you a day today, but cost you two days in a month. It’s not just a long-term tradeoff of what happens after three years. Terrible code quality has bitten my team in a month.
So, an engineering team should have a minimum standard of code quality irrespective of schedule pressure.
But this minimum should be as low as possible. If there’s disagreement between two team members as to what the bar should be, choose the lower bar of the two. If it causes trouble, you’ll know, and can raise the bar, but if you set the bar too high, you won’t even know that you made a mistake and so you won’t correct it. In general, when running a startup, make self-correcting mistakes. You’re going to make mistakes anyway — you can’t prevent that — so make decisions that if wrong have a built-in feedback mechanism to let you correct them.