Introduction

This page outlines the coding conventions used in HtmlUnit. If you wish to contribute code to this project then the code will be expected to follow these conventions.

The purpose of having common coding conventions is to make the code easier to understand and therefore more easily maintained. I have worked on far too many projects where over time the code became brittle or difficult to maintain. The conventions in this document are the best practices that I have adopted over time to keep the code easily maintainable and robust.

We use checkstyle to check as many coding conventions as possible. Things covered by checkstyle are only documented below if we feel that they require explanation. You can run checkstyle with the following target:

mvn checkstyle:checkstyle

Unit tests

All code must have 100% automated test coverage using the JUnit testing framework. It is strongly suggested that you write the code test-first, but it is fine as long as there are full tests for everything. Run the tests with the following target:

mvn test

Abbreviations

Abbreviations obscure meaning, and therefore they are not to be used in variable/method names. If you saw the following code, would you have any idea what it was doing?

cob.getTrh()

I didn't either - this was code that I have had to maintain..

There are some abbreviations that are so common that it doesn't make sense to exclude them. The following list contains all those abbreviations that are allowed. If it isn't in this list, it isn't allowed.

Abbreviation Description Comments
Util Utility Used only in class names. i.e. StringUtil
e Exception Used only in catch blocks. i.e. catch( MyException e )
i Loop variable

How do you add an abbreviation to the list? Bring it up on the mailing list and if none of the other maintainers object to it then it gets added.

The final keyword

The final keyword should be used wherever possible. It provides information to the compiler about your intended use of the code. This allows the compiler to generate move efficient code and identify potential errors.

Declare a variable to be final to indicate that it will only be assigned a value once. Final instance variables must have been given a value by the end of the last constructor. Final static variables must have been given a value by the end of the last static block. Final local variables must have been given a value before being used.

private final int fooCount = 12;

Declare method parameters method final to indicate that they will not be changed.

public void setFooList(final List fooList) {

Declare a method final to indicate that it may not be overridden

public final int getFooCount() {

Declare a class final to indicate that it may not be subclassed

public final class FooCounter {

Import statements

Use fully qualified import statements not wildcards. In other words, use

import java.util.List;
import java.util.ArrayList;
            

Instead of

import java.util.*;

Fully qualified import statements make it much easier to maintain the source. When I'm trying to learn someone else's code, one of the first things I do is expand all the .* imports so that I can figure out what class came from where. If they're already expanded then it makes it much easier to understand the code.

A common complaint about this convention is "how will I know if an import isn't needed anymore?". The answer is, use a tool that warns you about this. Eclipse and IDEA can be configured to warn you about unused imports. If your editor doesn't perform this check then the maven build will check it for you.

Indenting

Indent by using spaces, not tabs. Indent four (4) spaces at a time.

Deprecation

From time to time code needs to be removed from public APIs. When possible we will deprecate the existing API (using the javadoc @deprecated tag). Code deprecated in this way should be left in the source for at least 6 months and at least 2 releases, meaning the time could be longer than 6 months if there are not 2 releases in a 6 month' period but never less than 6 months. When deprecation is not possible a change log message containing "INCOMPATIBLE CHANGE" should be added to make these changes easy to find.