When jewelers talk about the quality of a gemstone, they talk about the three Cs: color, cut, and clarity. Programmers have their own three Cs for measuring software quality: complexity, churn, and coverage.
Individually, each is useful. But, together they can provide a roadmap to the hot spots in your code that need your attention. Let's take a look at each C, then dive into how they work together.
Complexity is the measurement of how difficult it is to reason about a piece of code. This number tells you how severe the problem is in a method or file. The higher the number, the more difficult it is to understand the code, making it more likely that a future programmer will introduce a bug.
Two common complexity metrics are:
- Cyclomatic complexity, which looks at the number of code paths through the program; and,
- Assignments, Branches, and Conditionals (ABC), which does just what it says. It is calculated as √(A² + B² + C²).
There are a ton of other complexity metrics, as well. But, cyclomatic complexity and the ABC metric are both great at measuring object-oriented complexity.
Churn is the measurement of how many times a file has been modified. Churn tells you how urgent the problem is. If a file has high churn, that means people are changing the file all the time, making it more susceptible to bugs. It can also indicate that you have a class with too many responsibilities.
You can typically measure churn based on the number of commits to the file in your version control system. If you're unable to determine the number of commits to a file, you can guesstimate churn by looking at the size of the file. The larger the file, the more likely it is that engineers are changing it frequently.
Coverage is a measurement of how well tested your code is. It is calculated while running tests. And, it tells you how risky it is to change the file. The lower the coverage, the higher the risk.
There are two formula for calculating coverage:
- Line coverage, which is the number of lines executed by the tests divided by total lines of code; and,
- Branch coverage, which is the number of branches executed by the tests divided by total branches in the code.
The difference may seem subtle, but generally speaking, line coverage will give you a rosier picture than branch coverage. So, it's good to look at both, if they're available in your toolset.
Putting the three Cs together
So, here's how they all go together:
- Complexity tells you how severe the problem is;
- Churn tells you how urgent the problem is; and,
- Coverage tells you how risky the problem is.
When looking for where to start refactoring an application to improve the code quality, use all three numbers. Multiplying complexity by churn will give you that view into the urgent hot spots that need your attention. Start with the files with the highest score. Coverage will then tell you how to begin — by writing tests or by jumping right into refactoring.