I'm in the process of moving all articles from my old blog to here. The articles are about code quality, coding best practices, architecture and about all my libraries. For now, read the blog instead.


Cyclomatic complexity

function saveDiscount(User accountOwner, string id, decimal discount)
    if (id == null)
        throw new ArgumentNullException("You must specify account id.");
    if (accountOwner == null)
        throw new ArgumentNullException("You must specify account owner.");

    var account = LoadAccount(id);
    if (account == null)
        throw new InvalidDataException("Failed to load account " + id);

    account.Discount = discount;

The simple function to the right requires four tests to ensure that it works per the requirements, no matter if the tests are in code or done manually by a tester.

It's quite common that only one test case is made for a function, making sure that the successful case works. By not testing the fault paths, the code might continue with invalid data, and those errors can be tough to debug.

The important aspect of cyclomatic complexity isn't as a test indicator, but a comprehension indicator. The higher complexity, the harder for a developer to manage all the different way that the code can take. Complex code is much more prone for errors.

Your team should strive to have at most 20 as complexity in their functions, as the risk of bugs increases too much over that.

Code Coverage

Code coverage measures how large part of your code is covered by unit tests (code tests).

Measuring test coverage is vital to get an indication to learn how well tested the product is. The higher coverage, the less likely that previously built functions stop working when new ones are introduced.

A common goal is that 80% of the code base is covered with tests, which means that 20% of the code is still untested.

What's important is not the actual goal itself (like 80% above), but that the coverage isn't decreasing over time. Therefore, measure in the end of every sprint to ensure your application quality.

Code coverage is a metric which is supported in most development tools.

Acceptance criteria

Every function that you want to develop must have at least one acceptance criteria. These criterias are used to ensure that the newly developed function behaves as expected. Both when everything is OK and how it should act when something is wrong.

The first through as a manager might be that only the the success criterias are important. But that might produce code faster initially, but as the project progresses it will actually slow it down.

Learn why


There is a lot of ways to measure your application quality. In my experience, the metrics above are those that have the most considerable effect on your application quality (as opposed to code quality). It's even possible to have low software quality and high application quality if you manage complexity and test coverage.

High complexity combined with a low (or not measured code coverage) is the worst you can have. In that case, you have several errors in your production environment that you are not aware of.

Having a low unit complexity combined with a high test coverage is the best way to maintain a high application quality over time.

Try our bug estimator to learn what you are missing out on.

Bugs calculator