Chapter 12. Code quality management and monitoring

 

This chapter covers

  • Considerations and mechanics for integrating code analysis into the build
  • Measuring the effectiveness of test code coverage
  • Performing static code analysis
  • Integrating with Sonar to measure software quality over time

The end product of most commercial projects is a binary. Unless your deliverable doesn’t ship with the source code or is the source code itself, users are usually not concerned about the quality of your code. They’re happy as long as the software fulfills the functional requirements and has no defects. So why would you as the software development and delivery team care? In a nutshell, high-quality code results in fewer bugs and influences nonfunctional requirements like maintainability, extensibility, and readability, which have a direct impact on the ROI for your business. In this chapter, we’ll focus on tools that measure code quality and visualize the results to help you pinpoint problem areas in your code. By the time you finish this chapter, you’ll know how to integrate code quality tools with your build.

Earlier, you learned how to write unit, integration, and functional tests to verify the correctness of your To Do application code. Code coverage analysis (also called test coverage analysis) is the process of finding the areas in your code that are not exercised by test cases. Empirical studies show that reasonable code coverage has an indirect impact on the quality of your code.

12.1. Integrating code analysis into your build

Though the outcome of code compilation and testing gives you a basic idea of your project’s health status, it doesn’t provide you with any feedback about code quality characteristics such as maintainability and code coverage. Code analysis tools help you produce metrics that make a statement about these characteristics. Some of these metrics produced by code analysis include

Similar to running integration and functional tests, the process of performing code analysis can take a long time depending on the size of your code base and the number of exercised code quality tools. For that reason, it’s helpful to create a dedicated set of Gradle tasks for invoking code quality tools. These tasks are usually provided by a plugin, so you won’t need to create them yourself. In practice, you’ll want to run particular code quality tasks independently from others. For example, during development you may want to know whether you’ve improved the code coverage of the class you’re currently refactoring without having to run other lengthy code quality processes.

12.2. Measuring code coverage

Code coverage doesn’t determine code quality per se. It uncovers execution paths in your code that aren’t exercised by tests. A frequently discussed metric is the overall percentage of tests covering the production code. While achieving 100% code coverage is an honorable goal, it rarely pays off, nor can it give you the ultimate confidence that the logic is correct or bug-free. A good rule of thumb, though it shouldn’t be followed dogmatically, is to aim for 70 to 80% code coverage with meaningful assertions.

When I talk about code coverage metrics, what exactly do I mean? The following list should give you some basic coverage criteria:

12.3. Performing static code analysis

Members of the software development team perform code reviews to identify architectural problems, security defects, and potential bugs. While this kind of review is extremely helpful in mitigating the risk of technical debt, this process easily becomes expensive and unmanageable for large software projects.

How many of us have had to toil away at code reviews? Sure, they’re useful—you identify problems, security defects, and bugs—but it can easily get expensive and unwieldy. A cheap and automated way of finding issues in code is static code analysis. Static code analysis is the task of analyzing source code without actually executing the software to derive quality metrics. Metrics that can be extracted range from potential bugs and adherence to coding standards, to unnecessary code complexity and bad coding practices. Let’s look at a list of tools producing these metrics.

12.4. Integrating with Sonar

Sonar uses a central database to collect code quality metrics over time. In its default configuration, Sonar comes with an embedded H2 instance, which doesn’t require any additional setup. While H2 is a great way to get started and explore Sonar’s functionality, it’s recommended to configure a more scalable solution for a production setting like MySQL or Oracle. Gradle integrates well with Sonar through its Sonar Runner plugin. The Sonar Runner is a launcher that analyzes your project and pushes the gathered metrics to the Sonar database via JDBC. You can directly open your project’s dashboard and view aggregated quality metrics over time. Figure 12.9 shows the interaction between Gradle and Sonar.

Earlier, you configured your build to produce metrics through Gradle’s static code analysis plugins. You might ask yourself if you can configure the Sonar Runner plugin to reuse these reports. At the time of writing, Sonar doesn’t provide a mechanism to publish these reports to Sonar’s database. Instead, you’ll need to rely on the embedded Checkstyle, PMD, and FindBugs plugins that are configured by a quality profile. The only exception to this rule is code coverage metrics. You can find a discussion of this topic later in this chapter.

12.5. Summary

Poor code quality and technical debt inevitably lead to developer productivity losses, missed deadlines, and a higher bug rate. In addition to design and code reviews through peers, it’s important to introduce coding standards and start monitoring your project’s code quality with the help of static code analysis tools in the early stages of your product. The Java ecosystem offers many open source tooling options to produce code quality metrics. Gradle simplifies the integration of many of these tools into the build process by providing standard or third-party plugins.

Code coverage measures the percentage of code that’s exercised by tests and reveals obvious areas that aren’t covered by tests. A high code coverage rate significantly improves your ability to refactor, maintain, and enhance your code base. We looked at how to apply and configure two code coverage plugins: JaCoCo and Cobertura. While both tools do their jobs in generating adequate coverage reports, JaCoCo shines through better flexibility, performance, and developer support.