There are as many ways to implement code as there are developers to implement it, which is one of the things that makes software development such a fun profession. This also means there are many opinions about what makes good, or high-quality, software. What one developer values in terms of code quality may be very different than what another developer values.
A simple example of this is a method written very compactly, using concise syntax and as few lines of code as possible. While this may be seen as high quality code by one developer, it may be seen as terse and esoteric by another developer who prefers to have code laid out in a more verbose and easy to read structure.
This is why it makes sense to start thinking of code in terms of the qualities is has, rather than to try an express a single definition of code quality. When we recognize that code has various qualities, many of which can be measured and analyzed, then we can have a conversation about which qualities of code to optimize for in a given situation.
There are two widely accepted aspects of quality that J.M Juran concisely defined in his book, “Juran’s Quality Control Handbook”. Juran observed:
- Quality consists of those product features which meet the need of customers and thereby provide product satisfaction.
- Quality consists of freedom from deficiencies.
Meeting the Requirements
The first measure of quality to consider is simply whether or not the code meets the requirements that caused it to be written. Under this definition, code expressed beautifully in the eyes of a developer, but failing to accomplish the intended outcomes, can be said to have low quality. The resulting software isn't realizing the most basic measure of fitness: It must actually meet the customer’s needs.
The requirement to provide customer satisfaction is one reason it is so hard to separate the quality of the end software from how it is created. A team that has a close relationship with its customer and shows its work frequently throughout construction is far more likely to provide the customer with what she wants than a team who waits to show their work until all construction is completed.
Of course, software can meet customer requirements and still have poor quality. Billions, if not trillions, of dollars have been made selling poorly crafted software that meet an end user’s needs. This demonstrates that satisfying customer’s requirements may be required for high code quality, but there is more to quality than this single attribute.
Focusing only this minimum level of quality begins to cause problems as software needs to change to meet new requirements. Today, software typically grows as new customer requirements and desires are added and expressed into the code. Therefore, code must also exhibit the quality of being easy to change.
If software is difficult to change, it is considered to be high in technical debt. A code base with high technical debt has a higher total cost of ownership because changes take longer to implement and the risk of introducing new defects while adding new features is high.
Free of Deficiencies
The second aspect of quality Juran refers to is a product’s freedom from deficiencies. Deficiencies in a software context is a very large concept, because there are so many aspects of code that can be observed, measured, quantified, and qualitatively assessed.
We can take “freedom from deficiencies” in code as referring to well-performing non-functional requirements such as maintainability, readability, extensibility, and a myriad of other –ilities. Since there are so many qualities of code to consider, it quickly becomes a matter of deciding which aspects to optimize, and which to monitor less aggressively.
Code gets read far more often than it gets changed. In fact, reading code in a given class file is most often done to gain contextual insight into what another, different class is doing. The amount of time a developer must spend to get enough context to make a change is a necessary waste that we can be referred to as time-to-context. Creating maintainable code is done in the pursuit of reducing time-to-context for the code reader. Things that promise reductions in time-to-context include clean separation of concerns, ensuring each class has a single responsibility, and simple designs.
The Role of Analysis Tools
There are even algorithms (lots of them) that try to empirically measure maintainability of code by looking at such things as code branches, use of operators, and even variable naming. These algorithms are used by numerous code analysis tools that are readily accessible to most developers.
Code analysis tools can check for other considerations such as security, performance, interoperability, language usage, globalization, and should be part of every developer’s toolbox and software build process. Regularly running a static code analysis tool and reading its output is a great way to improve as a developer because the things caught by the software rules can often teach you something.
Maintaining low technical debt and a fast time-to-context for the reader go hand-in-hand in ensuring that code is easily maintained. Further, the simpler code can be, the less likely it will be to contain defects. Thus, maintainability goes a long way to meeting the second requirement that code be free of deficiencies.
Part of the joy of creating software is in the individuality each of us brings to the problem of expressing intent as code. As developers, our challenge is in ensuring that expressions of intent as code are easily understood by others while meeting the first quality bar of delighting the customer as running software.
What is the best way to improve code quality?
According to the State of Code Quality 2016 survey, code review is the number one way for software teams to improve code quality. Find out how teams are improving code quality in 2016, download the State of Code Quality 2016 report.