Enhancing Software Quality with Checkstyle and PMD: A Practical Guide

It is widely agreed that maintaining a high-quality standard in software development is crucial for any project. However, the approach to achieving this level of quality needs further discussion. One highly effective method for ensuring quality is through software design or architecture governance. In this article, I will explain how you can use two powerful tools — Checkstyle and PMD — to establish and enforce coding standards, thus improving your project’s overall code quality and maintainability.

Understanding Checkstyle and PMD

Checkstyle is a development tool that helps you and your team establish a consistent code style standard across your project. By setting rules for code formatting, naming conventions, and other stylistic aspects, Checkstyle enforces a baseline for code quality that all team members must adhere to. This consistency is crucial, especially in large teams or projects with multiple contributors.

PMD, on the other hand, is a static analysis tool designed to identify potential vulnerabilities, inefficiencies, and problematic patterns in your codebase. PMD scans your code and highlights unused variables, inefficient loops, and possible security flaws. Together, these tools provide a comprehensive approach to maintaining code quality and preventing the gradual decay of your software’s architecture — a phenomenon known as software erosion.

Benefits of Combining Checkstyle and PMD

By integrating Checkstyle and PMD into your development process, you can achieve several key benefits:

Implementing Checkstyle and PMD in a Maven Project

To make integrating these tools into your project easier, especially if you’re using Maven, you can configure both Checkstyle and PMD directly in your pom.xml file. Below is an example of how to set this up.

Checkstyle Configuration

XML
 
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-checkstyle-plugin</artifactId>
    <version>${maven.checkstyle.plugin.version}</version>
    <executions>
        <execution>
            <id>verify-style</id>
            <phase>process-classes</phase>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <excludes>**/module-info.java,${checkstyle.excludes}</excludes>
        <logViolationsToConsole>true</logViolationsToConsole>
        <consoleOutput>true</consoleOutput>
        <checkstyleRules>
            <module name="Checker">
                <!-- Define your rules here -->
            </module>
        </checkstyleRules>
    </configuration>
</plugin>


In this configuration, any defined rule violation will break the build, ensuring issues are addressed promptly. For example, this setup enforces a maximum line length of 180 characters and a maximum file size of 3500 lines.

PMD Configuration

XML
 
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-pmd-plugin</artifactId>
    <version>${apache.pdm.plugin.version}</version>
    <configuration>
        <rulesets>
            <ruleset>pmd/bestpractices.xml</ruleset>
            <ruleset>pmd/codestyle.xml</ruleset>
            <ruleset>/category/java/security.xml</ruleset>
            <ruleset>/category/java/performance.xml</ruleset>
        </rulesets>
        <failOnViolation>true</failOnViolation>
        <printFailingErrors>true</printFailingErrors>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>


PMD comes with various pre-configured rulesets that you can use to enforce best practices, code style, security, and performance standards. You can start with these default configurations and gradually customize them to meet your project’s specific needs.

Practical Example

Consider the following simple code example that triggers Checkstyle and PMD violations:

Java
 
public class Animal {
    public void eat(String food) {
        if("meat".equals(food))
            System.out.println("Animal is eating meat");
    }
}


When Checkstyle and PMD analyze this code, they generate warnings and errors, such as missing braces in the if statement and the usage of System.out.println, which PMD flags as bad practice.

After addressing these issues, the corrected code might look like this:

Java
 
public class Animal {
    private static final Logger LOGGER = Logger.getLogger(Animal.class.getName());

    public void eat(String food) {
        if("meat".equals(food)){
            LOGGER.info("Animal is eating meat");
        }
    }
}


In this improved version, braces have been added to the if statement, and the System.out.println has been replaced with a logger, adhering to best practices.

Applying to Legacy Projects

While starting a new project with these tools is ideal, many developers work on legacy systems. In such cases, it’s wise to gradually introduce Checkstyle and PMD. Begin with Checkstyle to enforce coding standards and then incrementally add PMD checks. This phased approach helps the team adapt to the new standards without feeling overwhelmed, ultimately improving the codebase without discouraging developers.

Conclusion

Integrating Checkstyle and PMD into your development process is a practical step toward achieving higher software quality. These tools not only enforce consistency and best practices but also help in maintaining the long-term health of your codebase. Whether starting a new project or modernizing a legacy one, these tools are invaluable in your journey toward better software governance and quality assurance.

For a practical reference and to see these concepts in action, you can explore a detailed implementation available in this GitHub repository. This repository provides concrete examples of how Checkstyle and PMD are configured and used in a Maven project, offering a valuable resource as you apply these practices to your own work.

Video


 

 

 

 

Top