Building Superior Code ... Is It Achievable?
I’ve made stops in a lot of software development shops in my career, both as an employee and as a consultant. This has afforded me the opportunity to learn that some questions and concerns are universal in the industry. One such question, asked by Fortune 500 CTOs and tiny startups alike, is “How do I make sure we have good code?” If that seems like it’d be hard to answer, rest assured that it definitely is. As much collective practice as the world has writing software, we’ve not managed to agree on the answer to a deceptively difficult question: what is good code?
David Starr wrote about this topic some time back in an excellent article entitled “Defining Code Quality.” It’s hard to opine about how a software group can have and maintain superior code quality when, as David points out, it’s difficult even to reach consensus on what it means to have superior code quality. So let’s talk about that first.
A World of Trade-Offs
As David points out, two developers might look at a compact method, with one liking it and the other thinking it’s terse and hard to understand. So instead of arguing about which stylistic preference is better, let’s agree that different approaches have different qualities. Both developers could agree that the code, as written, is compact. And even if it’s possible to cite empirical research suggesting that, say, compact code correlates with smaller defect counts, that won’t alter the fact that one of those developers doesn’t like that code and doesn’t think of it as being of high quality.
People have different preferences. Instead of trying to think in terms of “better,” let’s think in terms of trade-offs. Just as both developers would agree that the code is compact and terse, I think both developers would be likely to agree that compacting code tends to make it denser, from a readability perspective. And both would agree that making code read more like prose might elongate methods somewhat. So the question is no longer, “What sort of code is better?” but, rather, “Which qualities do we want to target and which qualities are we willing to give up in this situation?”
Have the Trade-Off Conversation
No doubt you’ve experienced trade-offs in the past. Perhaps one project you worked on was a simple little web app that just needed to be hurried to market. Maybe another was an application that handled sensitive health information. In those cases, you’d definitely have discussions about whether you were willing to exchange quick time-to-market for rigorous application security or not.
There are other kinds of trade-offs that you can discuss as well. For instance, are you writing code that’s going to be maintained by a seasoned crew of language experts? If so, you might consider favoring terse, compact methods. On the other hand, if the application will be handed over to a team of junior developers that are new to the language, you might favor verbosity at the expense of longer methods.
Reach A Consensus
Have these discussions and reach a consensus. It’s going to be up to any given project team to decide which properties they value in their code base, which properties they don’t, and which they’re willing to concede, grudgingly. Take into account everyone’s professional experience and industry-wide consensus – you don’t necessarily want to deviate too far from what’s usually considered good software practice. But you are going to need to navigate trade-offs and decide what superior code quality means for your given project.
And by all means, include your customers, users, stakeholders, product owners, and analysts in this discussion as appropriate. They won’t necessarily know what cyclomatic complexity and unit test coverage mean, but it’s vital to get their input on subjects they understand. Defining the particulars of success is a whole-group effort.
Once Decided, Automate
You’ve avoided boiling the ocean with a discussion of “What does software quality mean?” by narrowing the scope to your own team and its software. But there’s still the matter of actually producing software that meets those qualities and then maintaining it. That’s not an easy task, either. Fortunately, as software developers, we have something in our tool chest that is perfect for this job: automation.
David Starr offered a definition of quality that included meeting user requirements and being free from deficiencies. Checking for those properties can be automated via user acceptance tests and regression tests, respectively. Adding automated tests ensures that your software satisfies and will continue to satisfy both functional and structural needs.
But you can go even further with code analysis tools. If you wind up deciding that having compact, short methods is extremely important for your project’s maintainability, use an analysis tool to create a check for that and integrate that check into your team’s build. This will guard against problems with every commit and enforce the properties of code that your team values in the same way that automated regression tests guard against defects.
For any property of a code base that your team collectively values, it’s worth automating a check. If you don’t, checks for conformance to that property will become so cumbersome that they’ll probably be done spottily, if at all. Code review is a valuable tool for education, knowledge transfer, and design philosophy discussion. Use it for those important, collaborative activities and let code analysis handle the aspects of code inspection that can be automated.
It may not be possible to have code that is universally regarded as “high quality,” but it certainly is possible to agree on a set of desirable characteristics for your code and to make sure that your code continues to conform to them If you do that, your development team, project stakeholders, and users will all agree that the code is of high quality, and, in the end, that is what really matters.