I like clean code. I like code that has visible quality, and I like predictable codebases which look like they were written by one developer. I like static analysis because it significantly helps to achieve all the aforementioned things. In my last article, I wrote about mistakes in using static analysis in software projects. Now I would like to go a step forward and give advice how to choose the right tool(s). I would say that even with a subset of these tools you will have numerous benefits such as fewer bugs, better maintainability, cleaner and simpler code. Let’s start with theory and motivation.
One Tool Isn't Enough
When it comes to choice static analysis tools, the first line of possibilities are tools widely accepted by the community—in Java landscape PMD, FindBugs and CheckStyle. One of these tools is almost in every project, but rarely are there more than two of them. And that’s wrong, but maybe it's hard to convince anybody who is responsible for that project of that. Maybe it’s even more difficult to make a codebase compliant to all of these tools. Without a doubt, static analysis has proven its usefulness, and we should be very interested in using it. But not just one tool, but several tools at once.
I believe that we are using incorrect, vague arguments and statements about static analysis. When I hear there are pretty much false positives or these tools are checking the same things without particular example, I get a bit angry. So what is my argument when I am talking about SA tools? In my perspective, there are five categories in which are tools distributed:
- tools checking conventions
- tools avoiding using bad practices
- tools finding potential bugs
- tools checking architectural issues
- tools measuring code coverage
Are you an architect, lead developer, project manager, or any other developer interested in a project? Would you like to check rules enforcing code conventions and best practices, clean architecture, good code coverage, and avoid silly technical bugs within each build of your software? Then continue reading. All you need is a static analysis tool for all the aforementioned categories. With these categories in mind, you can spot the tools that are not sufficient, and the ones in each category that complement each other.
These tools aim to check code conventions—naming, format, and usage of comments. Rules are very simple and using them helps with uniform-looking and consistent code. It has no impact on performance or stability, but enables people in a team to work together and get rid of useless discussions—typical tabs or spaces. We need these tools aligned with code conventions of the project and always need to have a custom configuration to spare the team from the avalanche of irrelevant feedback.
Bad Practice Checking
Rules are checking well-known behaviors that systematically lead to difficulties over time, such as dead code or long complex methods. You can think of this tool as a friend who is kindly reminding you that developed code contains something out of place or missing. (For example, a missing hashCode implementation when equals provided.)
Finding Potential Bugs
There are many places in the code needed to be taken into account to spot some buggy behavior. And it’s even harder because, in order to understand the buggy behavior, it means going through sequences of code. Tools for Java are often working on bytecode level, so it can check things that are almost impossible to spot (or it can be easily overseen) at the source level.
While conventional static analysis tools are focusing on checking the source code, the architectural static analysis tools are focused on the overall architecture of the software. For example, not using the data access layer directly inside the UI, or checking usage of some framework-specific annotations only in particular classes. I wasn’t aware of those tools for a long time; instead, I was used to writing something internally called “Quality assurance tests” which has one goal: verify that some annotation is present on the class implementing given interface. Tools for checking architecture issues will do much more work in a standardized way.
Code Coverage Measuring
Code coverage measuring is performed by running unit and integration tests and measuring coverage of executed production code along the way. It would check every condition and every line of code if it were executed and provide a percentage how many code was executed to not executed. Industry standards are very questionable and very different project-to-project. I have seen thresholds on 80 percent and 55 percent, as well. In my opinion, there is one big mistake in using such tools: checking coverage for different kinds of the tests altogether. It’s important to have divided execution of the tests in the build process and code coverage should have different thresholds set for different groups of the test. For example for unit test, it should be close to 100 percent, for integration close to 80 percent and end-to-end test close to 50 percent.
In my experience with static analysis, I include one more category: learning. As tools developers write for other developers become available, you can benefit from using them to learn something new. Instead of treating rules as your enemy, you need to treat them as a friend who is leading you in the right direction. Every time, you are going to have some violations, but you will learn something new. You'll become a better developer. This brings to mind that static analysis is the industry standard, so it’s bad if you are not incorporating it into your project.