
The (False) Tradeoff Between Speed and Quality
As an engineering leader who has hired my share of people and likes to participate in the engineering community, I get to talk to a lot of people about what they are doing- and more importantly, how. There are a lot of trends across these conversations, but one just keeps standing out for me. The conversation usually goes like this-
So, how does your team think about testing?
< Oh, we don't really have time for all of that. Things are always changing and we're trying to get stuff out the door as fast as possible. I know we should be doing it, but we're hoping to get there when things slow down.
There are a lot of things in that statement that I believe to be fallacies. Things that a lot of people believe to be true, but aren't really. Lets work backwards-
"We'll do it when things slow down"
This is actually one of my favorites (along with "we'll do a better job of planning next time"). I am sure it has happened, somewhere, but I have certainly never been a part of a project where things slowed down over time. More likely, things get more complicated over time as you add more people, features, and users to whatever project you're working on. (Or, the project just doesn't work- but in that case, you'll generally be moving to something else, not fixing up this one). It is very easy to look around at all the problems you are currently dealing with and dream about when all those problems have been overcome. Don't do it though! In reality, problems will arise as quickly as you solve them (usually more quickly). Instead of optimizing for a situation that will almost certainly never come, take steps today to make it easier to deal with the problems you have and will continue to have.
"I know we should be doing it, but..."
Maybe this is not a real sentiment. After all, if I am doing a job interview and ask about testing and you don't do it, its probably obvious that I think its important- maybe people are just patronizing me. I don't think that's the case though. I think people actually feel guilt over the lack of testing in their projects. In this case, I like to follow up with the question - "Why?" If you are doing any practice, such as testing or code reviews or whatever, it should be to accomplish a specific goal. I'll talk a bit later about why I think various practices are a good idea, but my opinions are not universal, and there are a lot of different situations. If you think that testing your current project won't make it better, you should NOT be doing it! Even more importantly, "better" should be pretty clearly defined. If you're going to add unit testing or pair programming, what benefit do you hope to get from it? How will that benefit affect delivering features to customers? Remember, tests are not a particularly good way to catch bugs. There are a lot of positive things they can do, but basically none of them are customer facing. So, there is no magical code quality standard that you should be striving for because it is "better" - you should be following the practices that allow you to most efficiently deliver software. If you're not doing something it should be because you don't think it would help, and you shouldn't feel guilt about that!
"Things are always changing and we're trying to deliver as fast as possible"
This is where I am going to start really making the point of my argument. There is supposedly always a trade off between speed and quality. Think of all the discussion of "technical debt". However, there is not a lot of evidence that this is a real trade off. If you want a much longer and more scientific treatment of this topic, try the book ***Accelerate ***(https://www.amazon.com/Accelerate-Software-Performing-Technology-Organizations-ebook/dp/B07B9F83WM). They did a lot of research on the results of devops practices and found that teams that delivered more rapidly also delivered with higher quality. Change boards and review processes and QA departments wound up not meaningfully moving the needle on reducing bugs.
I've seen the same thing with pure software projects. A project with no testing or automation was releasing once a month or so. After adding a good amount of automation and rudimentary testing, the release cadence had increased to multiple times per week. Of course, there were growing pains- but its much easier to fix bugs when you are releasing twice a week as well.
The truth is that software is COMPLICATED. Even seemingly simple things can be nearly impossible for a person to get right by reasoning about it. Rather, most of the time when an engineer changes code, she will have to try three or four times to get it quite right. The difference is that in a project that has gone "slow" that try/fix loop can take seconds by running the test suite- vs hours to test some corner case of a running system. Even worse, the running system will often be impossible to check error handling code. I can't count the number of times that I have added tests to some procedure just to find that the error handling didn't actually work- so good thing we hadn't been hitting that error!
Automation has an up front cost, true. Getting it working is really something you just have to do once though- later projects can just use the existing setup. At that point, the pain point is writing the actual tests. I am not pretending that testing is some zero effort practice. I know I have had plenty of tests that were way harder to write then the code under test. But every change you make to the code base after that test is added will be a little bit faster- either the engineer doesn't have to re-check some functionality manually or your users don't catch regressions. If things are always changing that is when a test suite and clean coding standards will pay off the most- by letting you make those changes without fear.
"Oh, we don't really have time for all of that"
All of this is not to argue for some abstract concept of code quality. It is an observation that most "clean coding" practices aren't indulgences- they actually make writing code faster and easier overall. If your project isn't going to have to change- a quick POC, a script for some obscure task- then this stuff probably wouldn't help. Don't waste your time making it easier to change code that doesn't have to change. However, if your code does have to change, making a little bit of investment in the beginning along with an ongoing commitment to keep it changeable is the best way to keep your velocity high!