DEV Community

Serhiy Kozlov
Serhiy Kozlov

Posted on • Edited on

11 Best Practices and Tools to Improve the Java Code Quality

Usually, if you work on a software project and especially at the beginning of it, the code quality is not the first thing you pay attention to. However, the question of how to improve code quality and efficiency should be one of the main concerns for the java developers, technical team lead, system architect, and even project manager. How to improve the Java code quality?

The code quality improvement is one of the things that require a well-developed strategy and adhering to it throughout the project’s life cycle. It is only a matter of time when it will catch you up and cause the problems if you will just leave it unaddressed. That is why it is much better to manage this problem beforehand.

At Romexsoft, we commonly use Java for our projects and always look at the ways how to improve code quality in Java. We do this by following software quality improvement techniques and using Java Code Quality tools that help us not only to improve our code but also our productivity.

In this article, we will take a look at the most used development methodologies and top-notch tools that we use to create better code. The intent is to consider the common approaches to code quality and help teams choose methodology and tool, that makes their process efficiently.

What is a Software Development Methodology?

The software development methodology is a set of patterns and rules that are used to structure, plan, and control the process of software solutions developing. In order to manage the development process efficiently, the project manager must select the development methodologies that suit the appropriate project the most.

So, let’s run through some of them to understand, why different methodologies exist and which of them are the most commonly used.

Pair Programming

Pair programming is a proven methodology that decreases bugs in your code. It is done by two developers who share one workspace (a keyboard and a screen) and it looks like a flashback from school or university - one developer is coding while another reads the written code and contemplates potential issues. Developers coach each other in coding and can change roles during a session.

The main benefit of pair programming is knowledge sharing and code quality improvement. It also improves communication inside the team.

Pair programming is not only about the code but it can be used for OS command lines, work with DB server, file management, work with cloud and many other cases.

So if you work on the more complex or critical items feel free to team up with your co-workers and use this methodology to prevent bugs/issues in your code. Given the higher costs of bugs/issues that will be found later during development or after the release pair programming saves your time and money.

Considering the common knowledge that ‘two heads are better than one’, the discussion about pair programming seems to have died down and people actually do practice it.

Coding Conventions

Coding conventions are the set of guidelines that are developed by dev teams and include the recommendations for the programming style, practices, and methods for each aspect of a code that is written within the company or certain project. These conventions are usually specific for every programming language and cover file organization, indentation, comments, declarations, statements, white spaces, naming conventions, programming practices and principles, programming rules, architectural best practices, etc. The main advantage of defined standards is that every piece of code looks and feels familiar. It makes it more readable and helps programmers understand code written by another programmer.

If the coding standards are followed by and applied consistently throughout the development process, in the future, it will be easier to maintain and extend the code, refactor it, and resolve integration conflicts. The standard itself matters much less than adherence to it.

Code conventions are important to programmers for a number of reasons:

  • 40% - 80% of the lifetime cost of software goes to maintenance.
  • Hardly any software is maintained for its whole life by its author.
  • Code conventions improve the readability of the software, allowing programmers to understand the new code more quickly.

Frankly speaking, I am a big fan of coding standards. For me, it makes sense to spend time debating and arguing over them, since it is a valuable contribution to save your time and efforts in the future.

Start with arranging a meeting on what should be in the coding standard. It should be only a face to face meeting, but not over email or via the chat systems. Discuss the rules that you decided to include in your code convention. The rules that are agreed by the majority of the team should be accepted as “mandatory" and other rules can be considered as “optional”.

The code convention guidelines should be reviewed frequently. Rules can be moved from “mandatory” to “optional” and vice versa. If some of them do not work as expected, then they need to be reworked or removed from the guidelines.

Programmers are highly recommended to follow these guidelines during the coding and it should be used as part of the code review which is the next one in our list.

Code Review

The next best thing to pair programming is code review. If you do not practice pair programming then it is recommended to consider at least code review. It is a lightweight process that should be applied as soon as possible after the code is written.

Some of the other subjects listed below are not so obvious but are worth to be considered. Let's continue.

Unit Tests

The next methodology we will talk about is unit testing. Depending on your experience you may or may not have heard something about unit tests, test-driven development or some other type of testing methodology. Usually, these methodologies are applied in the context of large software systems and sometimes in the context of simple web sites.

In computer programming, unit testing is a software development process in which the smallest testable part of source code, called unit, is tested individually and independently to examine whether they are working as expected. This helps you to identify failures in the algorithms and/or logic before the code is released.

One of the benefits that you acquire from creating unit tests is that your team will be motivated to write testable code. Since unit testing requires the appropriate structure of your code it means that code must be divided into smaller more focused functions. Each of which is responsible for a single operation on a set of data rather than on large functions performing a number of different operations.

The second benefit of writing a well-tested code is that you can prevent future failure when the small changes to existing code break functionality. When a failure happens you will be informed that you have written something wrong.

At first, glance, spending time on writing the unit tests during development looks like extra expenses. However, it will save time you might spend on debugging. This should be a step by step process.

Of course, you can not write unit tests for every part of your project but you need to make sure the core components behave as expected. When the project grows you can simply run the tests you have developed to ensure that existing functionality is not broken when new functionality is introduced.

Test-Driven Development

Test-driven development (TDD), also called test-driven design, is a methodology of developing software that combines unit testing, programming, and refactoring of source code. Usually, developers tend to skip the architectural aspect of software development and jump straight into coding. They try to get a rough implementation and only after having a working prototype they think about writing the tests. While this approach can succeed it takes a lot of effort to just make it work.

TDD is one of those practices which contribute to better code quality and decreases bugs. It was introduced as part of a larger software design paradigm known as Scrum and Extreme Programming (XP), which are types of the Agile software development methodology. TDD helps to produce applications of high quality in less time. Proper implementation of TDD requires the developers and testers to accurately anticipate how the application and its features will be used in the real world.

When it is run as part of a continuous integration cycle with frequent automated builds and tests, the practice is Unit Testing on steroids. In order to apply this methodology, developers need specific training and coaching.

In my understanding of TDD, before coding, you need to know (at least) the starting point. First of all, you need to think of the objects and their behavior to solve the given problem. When doing TDD you start from a test and from your dream vision of how the test would look like.

Continuous Integration

Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day (SVN, Subversion, or Git). Each check-in is verified by the automated tests. Although automated tests are not strictly part of CI, they are usually anticipated. Such an approach allows developers to detect problems earlier and, as a result, solve them faster.

This is a valuable practice by itself. You should focus on setting up a simple Continuous Integration process as early as possible. There are many tools that can help you to set up this process and the most known are Jenkins, Bamboo, and Teamcity. They allow you to automate your software deployment and let you focus on building your product.

Demo Session

The demo review meeting usually takes place close to the end of the Sprint. The purpose of this meeting is to show the other team members, customers, and stakeholders the results of the work team have accomplished over the Sprint.

It may not be immediately visible why it leads to a better code but it will. By regularly showing the source code developers need to keep it close to the release state. With demo meetings on a regular basis, you will have a well-organized process of receiving feedback. And this will give you a better understanding of what was done right and will indicate when something went in the wrong direction.

Now, let's move on and check what are some recommended code quality tools to polish the process.

Tools to Improve Java Code Quality

There is no developer who never made a mistake.

Usually, the compiler catches the syntactic and arithmetic issues and lists out a stack trace. But there still might be some issues that compiler does not catch. These could be inappropriately implemented requirements, incorrect algorithms, bad code structure or some sort of potential issues that the community knows from experience.

The only way to catch such mistakes is to have some senior developer to review your code. Such an approach is not a panacea and does not change much. With each new developer in the team, you should have an extra pair of eyes that will look at his/her code. But luckily there are many tools that can help you control code quality including Checkstyle, PMD, FindBugs, SonarQube, etc. All of them are usually used to analyze the quality and build some useful reports. Very often those reports are published by continuous integration servers, like Jenkins.

Here is a checklist of Java static code analysis tools, that we use at RomexSoft in most of our projects. Let's review each of them.

Checkstyle

Code reviews are essential to code quality, but usually, no one in the team wants to review tens of thousands of lines of code. But the challenges associated with manually code reviews can be automated by source code analyzers tool like Checkstyle.

Checkstyle is a free and open-source static code analysis tool used in software development for checking whether Java code conforms to the coding conventions you have established. It automates the crucial but boring task of checking Java code. It is one of the most popular tools used to automate the code review process.

Checkstyle comes with predefined rules that help in maintaining the code standards. These rules are a good starting point but they do not account for project-specific requirements. The trick to gain a successful automated code review is to combine the built-in rules with custom ones as there is a variety of tutorials with how-tos.

Checkstyle can be used as an Eclipse plugin or as the part of a built system such as Ant, Maven or Gradle to validate code and create reports coding-standard violations.

PMD

PMD is a static code analysis tool that is capable of automatically detect a wide range of potential bugs and unsafe or non-optimized code. It examines Java source code and looks for potential problems such as possible bugs, dead code, suboptimal code, overcomplicated expressions, and duplicated code.

Whereas other tools, such as Checkstyle, can verify whether coding conventions and standards are respected, PMD focuses more on preemptive defect detection. It comes with a rich and highly configurable set of rules that you can easily configure and choose which particular rules should be used for a given project.

The same as Checkstyle, PMD can be used with Eclipse, IntelliJ IDEA, Maven, Gradle or Jenkins.

Here are a few cases of bad practices that PMD deals with:

  • Empty try/catch/finally/switch blocks.
  • Empty if/while statements.
  • Dead code.
  • Cases with direct implementation instead of an interface.
  • Too complicated methods.
  • Classes with high Cyclomatic Complexity measurements.
  • Unnecessary ‘if’ statements for loops that could be ‘while’ loops.
  • Unused local variables, parameters, and private methods.
  • Override hashcode() method without the equals() method.
  • Wasteful String/StringBuffer usage.
  • Duplicated code – copy/paste code can mean copy/paste bugs, and, thus, bring a decrease in maintainability.

FindBugs

FindBugs is an open-source Java code quality tool similar in some ways to Checkstyle and PMD, but with a quite different focus. FindBugs doesn’t concern the formatting or coding standards but is only marginally interested in best practices.

In fact, it concentrates on detecting potential bugs and performance issues and does a very good job of detecting a variety of many types of common hard-to-find coding mistakes, including thread synchronization problems, null pointer dereferences infinite recursive loops, misuse of API methods, etc. FindBugs operates on Java bytecode, rather than source code. Indeed, it is capable of detecting quite a different set of issues with a relatively high degree of precision in comparison to PMD or Checkstyle. As such, it can be a useful addition to your static analysis toolbox.

FindBugs is mainly used for identifying hundreds of serious defects in large applications that are classified into four ranks:

  • scariest
  • scary
  • troubling
  • of concern

Let's take a closer look at some cases of bugs.

Infinite recursive loop

public String resultValue() { return this.resultValue(); }

Here, the result value() method is called recursive inside itself.

Null Pointer Exception

FindBug examines the code for the statement that will surely cause the NullPointerException.

Object obj = null; obj.doSomeThing(); //code execution will cause the NullPointerException

The below code is a relatively simple bug. If the ‘obj’ variable will contain null and ‘str’ variable has some instance it will surely lead to the NullPointerException.

if((str == null && obj == null) || str.equals(obj)) { //do something }

A method whose return value should not be ignored

The string is an immutable object. So ignoring the return value of the method will be reported as a bug.

String str = "Java"; str.toUpper(); if (str.equals("JAVA"))

Suspicious equal() comparison

The method calls equals(Object) on references of different class types with no common subclasses.

Integer value = new Integer(10); String str = new String(“10”); if (str != null && !str.equals(value)) { //do something; }

The objects of different classes should always compare as unequal, therefore !str.equals(value) comparison will always return false.

Hash equals mismatch

The class that overrides equals(Object) but does not override hashCode() and uses the inherent implementation of hashCode() from java.lang.The object will likely violate the invariant that equal objects must have equal hashcodes.

Class does not override equals in the superclass

Here’s a case: the child class that extends a parent class (which defines an equals method) adds new fields but does not override an equals method itself. Thereby, equality on instances of child class will use the inherited equals method and, as a result, it will ignore the identity of the child class and the newly added fields.

To sum up, FineBug is distributed as a stand-alone GUI application but there are also plugins available for Eclipse, NetBeans, IntelliJ IDEA, Gradle, Maven, and Jenkins. Additional rule sets can be plugged in FindBugs to increase the set of checks performed.

SonarQube

SonarQube is an open-source platform that was originally launched in 2007 and is used by developers to manage source code quality. Sonar was designed to support global continuous improvement strategy on code quality within a company and therefore can be used as a shared central system for quality management. It makes the management of code quality possible for any developer in the team. As a result, in recent years it has become a world’s leader in Continuous Inspection of code quality management systems.

Sonar currently supports a wide variety of languages including Java, C/C++, C#, PHP, Flex, Groovy, JavaScript, Python, and PL/SQL (some of them via additional plugins). And Sonar is very useful as it offers fully automated analysis tools and integrates well with Maven, Ant, Gradle, and continuous integration tools.

Sonar uses FindBugs, Checkstyle and PMD to collect and analyze source code for bugs, bad code, and possible violation of code style policies. It examines and evaluates different aspects of your source code from minor styling details, potential bugs, and code defects to the critical design errors, lack of test coverage, and excess complexity. In the end, Sonar produces metric values and statistics, revealing problematic areas in the source that require inspection or improvement.

Here is a list of some of SonarQube‘s features:

  • It doesn’t show only what’s wrong. It also offers quality management tools to help you put it right.
  • SonarQube addresses not only bugs but also coding rules, test coverage, code duplications, complexity, and architecture providing all the details in a dashboard.
  • It gives you a snapshot of your code quality at a certain moment of time as well as trends of lagging and leading quality indicators.
  • It provides you with code quality metrics to help you take the right decision.
  • There are code quality metrics that show your progress and whether you're getting better or worse.

SonarQube is a web application that can be installed standalone or inside the existing Java web application. The code quality metrics can be captured by running mvn sonar:sonar on your project.

Your pom.xml file will need a reference to this plugin because it is not a default maven plugin.

<build>                …                <plugins>                               <plugin>                                              <groupId>org.sonarsource.scanner.maven</groupId>                                              <artifactId>sonar-maven-plugin</artifactId>                                              <version>3.3.0.603</version>                               </plugin>                </plugins>                … </build>

Also, Sonar provides an enhanced reporting via multiple views that show certain metrics (you can configure which ones you want to see) for all projects. And what’s most important, it does not only provide metrics and statistics about your code but translates these nondescript values to real business values such as risk and technical debt.

Time for conclusions

Over the years of working on different software development projects, we have accumulated our own experience of making the good code better. And here’re things we recommend to do during the whole process  to improve the code quality:

  • Follow the programming language style guide.
  • Adhere to SOLID principles in your design.
  • Give descriptive names for methods and variables.
  • Do not overdesign.
  • Use design patterns.
  • Do not reinvent a wheel and use third-party frameworks.
  • Use efficient data structures and algorithms.
  • Create Unit tests.
  • Document all aspects of your project.
  • Keep all elements of your project under the version control system.

By doing all these points and using the code quality analysis tools in conjunction with development methodology in your everyday programming practices you will eventually create more readable, more thoroughly tested, more likely to run correctly, and much simpler to revise the code. You will also save yourself, your team and your customers from a lot of headaches, time and, therefore, money.

If this is what you would like to experience within all development process, don’t hesitate to contact Romexsoft. We know how to ship quality code and bring the best experience for our clients.

Written by Romexsoft on September 13, 2017
Originally published at Romexsoft Blog 11 Best Practices and Tools to Improve the Java Code Quality

Author: Yura Bondarenko

Top comments (0)