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.