Every startup wants to be quick. First-mover advantage is viewed as key to success, so engineering teams avoid implementing best practices at the outset in an attempt to be more agile. This may work the first time when they develop the prototype, and maybe the second time for an alpha version. Right around this point, most startups get mired in quicksand – code quality becomes a major issue as small changes start causing problems.
Moving quickly and maintaining high quality code is a tricky balancing act. It’s as much art as science. It’s especially important if you’re writing software for large distributed systems; you must get the processes right at the start. Otherwise, you’ll end up with a software product that’s like a house where you paint the living room and the chimney falls off.
We want to be fast and nimble like every other startup, but we also build large distributed system software. Code quality is hugely important when you’re writing software to support thousand-plus node production clusters at some of the largest companies. It is extremely difficult to maintain velocity while developing code for large-scale systems – at least without adopting the right process. At Pepperdata, we’re constantly making changes to the code.
When Pepperdata started out, we each had 15+ years of experience in big and small software companies. We’ve all seen great products go on to fail, thanks to software bloat. Engineers waste hours over complex and confusing source code. Changes are made with no one understanding the effect. Production crashes. More and more time is wasted in blind QA. People write work-around changes. Code gets even more confusing. It’s a dead end.
How do you avoid it? We decided to adopt a few best practices and continue to follow them even as our engineering team has quadrupled in size; we are very happy with the result. The magic is “review, test, and refactor. Now repeat.”
Every change is reviewed.
We take code reviews seriously. Even one-line changes to comment strings get reviewed. We allow a change to be checked in only after reviewers approve it. Reviewers demand the change to be as clean as possible, and as readable as possible. Code review guarantees that at least 2+ people read and understood the change. This significantly increases the chance that it can be understood by the rest. Over time, the difference in code quality is like day and night.
Changes must have unit tests.
Unit tests are an integral part of a code change. Reviewers will reject a change if it lacks unit tests. Each public method of a class expects a unit test exercising the method. Are there multiple code paths? Then each code path should have a test. Error paths should be tested too. We don’t like surprises hidden in our code. With unit tests, all obvious bugs get shaken out.
Coverage reports are created even before a ch