Code quality’s singular metric
There are some excellent articles and posts around the internet recently related to a question asked on LinkedIn about metrics and code quality. Specifically, the question asked was:
What are the useful Metrics for Code Quality?
The user goes on to state that
The quality of any software application will depend mostly on its code base and it’s important to know what might be the key metrics that help us to evaluate the stability and quality of the code base.
Many of the answers bring up excellent points, including different ways of viewing the question, such as taking the time to understand what attributes of code are related back to quality. For example, Michael Bolton aptly suggests you ask if the code is:
* testable
* supportable
* maintainable
* portable
* localizable
What’s more, further answers suggest coverage, code size, and other metrics as discrete measurements that can help gauge quality. These are all excellent answers; however, the answer turns out to be quite simple.
We have found time and time again that there is one metric that most appropriately relates to code quality: Cyclomatic complexity. If your code base has highly localized pockets (i.e. methods) of Cyclomatic complexity (or CC) your code will have issues (undoubtedly affecting quality how ever you define it) eventually.
In fact, CC affects arguably every attribute listed above (testable through localizable). Think about it for a minute: a method that has 27 different paths is next to impossible to adequately test, which means you’re going to have a doozy of time supporting it because it isn’t easy to maintain. Code that is littered with high CC is a blast to port as well (hopefully you’ve got deep pockets and customers that absolutely love you). Good luck localizing it too.
It turns out that the other metrics mentioned (such as code size) tend to correlate to each other– in fact, it seems that all complexity-like metrics point back to CC. Classes that have a lot of dependencies are usually big and big classes usually have big methods and big methods usually have lots of conditionals. Lots of conditionals mean a high CC value (CC measures paths through a method, such as from an if/else chain).
Code coverage is an excellent metric for ascertaining what code isn’t touched by tests and it happens to relate directly to CC because in order to reach 100% branch coverage you’d have to have a one to one relationship with CC (i.e. if a method has 27 different paths, you’d need 27 tests to reach full coverage). Plus, coverage can be unfortunately misleading and can provide a false sense of security.
The beauty of CC is that it’s one metric. One number is all you need to understand risk. You can then apply it in many ways. For example, we provide development teams with ratios related to CC (because CC precisely delineates complex methods it’s often helpful to relate it to other normalized metrics) that enable them to gauge quickly the overall health of a code base. When the ratios grow, things are getting worse and when they decrease, happiness ensues.
The definition of quality (and its associated attributes) as it relates to software has traditionally been quite hard to nail down (regardless if you are a customer or a developer); however, one thing is factual– complex code is a house of cards that will eventually collapse (via attrition, bankruptcy, ossification, etc). Finding complexity and proactively reducing it will lead to software that is more testable, maintainable, and supportable. And by the way, that happens to be the kind of software customers like.
Hiendt(theo testearly.com)