This style guide is to help as a reference for code review (both for those making PRs and reviewing them) and to ensure consistency across the project code base. It is based off the which is highly recommended reading, as it includes far more detail. None of the style guide is set in stone, if disagree with the notes here, please suggest changes with a pull request from a new style-guide
branch.
A source file consists of, in order:
- License or copyright information, if present
- Package statement
- Import statements
- Exactly one top-level class
Exactly one blank line separates each section that is present.
Imports should import the class used, not the entire package. For example this:
import java.awt.*;
Should be replaced with this:
import java.awt.Color;
import java.awt.Font;
As importing all of the awt package pollutes the namespace; imagine we designed our own Button class, this would now be in conflict with awt.Button
without us even knowing!
- All static imports in a single block.
- All non-static imports in a single block.
- Imports grouped by higher level package
Incorrect. Note how all the imports are mixed up
import javafx.application.Application;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import java.awt.Color;
import javafx.scene.Scene;
import java.awt.Font;
import javafx.stage.Stage;
Correct
import java.awt.Font; // Order alphabetically if possible
import java.awt.Color;
import java.io.IOException;
import javafx.application.Application; // No splits between high level packages
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
Each file should have only one top level class (or Interface/Enum) which should be the same name as the file. If you design a sub class, it should be testable and reusable in the rest of the code base. Classes should be named in UpperCamelCase
.
Methods should be ordered in a sensible way, there is no hard and fast rule for this, however it is suggested that common sense is applied such that if asked, some sort of ordering can be explained. A good guide can be found in the book Clean Code with a brief example below:
public class MyClass
{
public MyClass()
{
// Constructor always first
}
public String keyMethod()
{
// This is the main job of the class; the user should see this right away
secondaryMethod()
}
public void secondaryMethod() {...} // This is called above, so makes sense to have
// it right below where it is called
public int getAttribute(){...} // All public getters and setters together
public void setAttribute(int n){...}
private void doSomething(){...} // Private methods are where we do internal implementation that
// users shouldn't worry about; thus last
}
If your ordering method is chonological ( i.e. "I just add it in at the bottom" ) then go look in the mirror and think about what you have done ...
- Every variable declaration (field or local) declares only one variable: declarations such as
int a, b;
are not used. - Variable are named in
lowerCamelCase
in the case of local or field varaibles - Constant variables (when the
final
keyword is used) should be inCONSTANT_CASE
- Local variables are not habitually declared at the start of their containing block or block-like construct. Instead, local variables are declared close to the point they are first used (within reason), to minimize their scope. Local variable declarations typically have initializers, or are initialized immediately after declaration.
- Class variables should, wherever possible be private and modified using a getter and setter method
I don't want to start any wars, so formatting will not be used as a reason to stop a pull request. However, all methods in the same class MUST use the same format. So if you add a single method to a class, either follow the format of the class, or reformat the whole class to your style!
For an in depth view of the different indentation styles, see , I personally prefer the Allman style of braces as I believe that this is clearer to read:
while(x == y)
{
doSomething();
doSomethingElse();
}
This is due to the addition of multiple arguments:
void MyFunction(int parameterOne,
int parameterTwo) { // This is not clearly a second argument
Class localOne = new Class();
Class localTwo = new Class();
}
And the ease of identifying the contents of a block when nesting as this:
if (you.hasAnswer())
{
if(x == y)
{
you.postAnswer();
}
}
else
{
you.doSomething();
}
Is far more readable than:
if (you.hasAnswer()) {
if(x == y){
you.postAnswer();
}
} else {
you.doSomething();
}
Should be terminated on the same line.
private void doNothing(){}
+4 spaces for each indented block, the level of indentation should be reduced as much as possible through the use of sub-methods so that the example below
public void doSomething(int n)
{
for(int i = 0; i < n; i++)
{
if(i % 2 == 0)
{
try
{
doSomethingElse();
{
...
}
}
catch(Exception e)
{
...
}
}
}
}
should be refactored into seperate methods like this:
public void tryToDoSomthing(int n)
{
try
{
doSomething(int n);
}
catch(Exception e)
{
// handle exception
}
}
public void doSomething(int n) throws Exception
{
for(int i = 0; i < n; i++)
{
doSomethingIfEven(i);
}
}
private void doSomethingIfEven(int n)
{
if(i % 2 == 0)
{
doSomethingElse();
}
}
A single blank line should be left between the closing backets of a method and the opening declaration of a new method. Correct:
public void methodOne()
{
...
}
public void methodTwo()
{
Incorrect:
public void methodOne()
{
...
}
public void methodTwo() // WRONG!
{
A single blank line may also appear anywhere it improves readability, for example between statements to organize the code into logical subsections. A blank line before the first member or initializer, or after the last member or initializer of the class, is neither encouraged nor discouraged.
Beyond where required by the language or other style rules, and apart from literals, comments and Javadoc, a single ASCII space also appears in the following places only.
- Separating any reserved word, such as
if
,for
orcatch
, from an open parenthesis(
that follows it on that line - Separating any reserved word, such as
else
orcatch
, from a closing curly brace}
that precedes it on that line - Before any open curly brace
{
, with exception:String[][] x = {{"foo"}}; //no space is required between {{
- On both sides of any binary operator.
a + b
orint i = 0;
orif(a && b)
- On both sides of the double slash
//
that begins an end-of-line comment.addComment() // note the space on each side!
- Between the type and variable of a declaration:
List<String> list
- After a comma in a list:
new int[] {5, 6}
This rule is never interpreted as requiring or forbidding additional space at the start or end of a line; it addresses only interior space.
The intent of functional programming is that a function, given a certain input, will always output the same result. This reduces the amount of 'state' knowledge that needs to be held and reduces the number of side effects of the code when you call it.
When calling a method, it should be either explicitly stated the one action that occurs, or even better should return a new value instead:
// BAD!
public int getNPlusOne()
{
n++; // Increments n, but doesn't tell the user that this happens!
return n;
}
// Better ...
public int incrementN()
{
n++; // Better naming; less suprises
return n;
}
// Best!
public int nPlusOne()
{
return n + 1; // Doesn't modify the state, just returns a new local copy
}
The number of parameters of a good function should be 0, this isn't always possible, but the ideal function gets called and always does the right thing regardless of state:
public void toggle()
{
if(b)
b = false;
b = true;
}
Avoid having large numbers of parameters, condense them into an object or ask why the function needs to know so many things? Is it becoming too big?
public int startGame(int boardSize,
int playerCount,
Player[] players,
Player startingPlayer,
Color[] colours,
JFrame view,
JPanel Board)
{...}
If we add all the settings into a Settings
data class and allow the view to call the board, we reduce to two parameters
public int startGame(Settings settings, JFrame view) {...}
Lombok allows you to reduce the Boilerplate code you write and makes classes cleaner
The intent is that only useful code is shown to the end user of the class. For example, creating an immutable Vector class can be done as follows:
Where default constructor, all args constructor and to string method are all wrapped in 6 lines of code. Contrast this with the original:
It must be remembered that Lombok is there to reduce boilerplate code that is required but completely self explainatory. If any changes to the default implementation are made, this should be done without using the Lombok annotations
Class annotations should be listed with each on a new line:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class DataClass
{
...
}
For field variables, in line definitions are preferred:
@Getter private String thisIsOkay;
@Getter @Setter private thisIsAlsoOkay;
However for more than two annotations, a new line should be used:
@Getter @Setter @NotNull
private int number;
Class definitions can be used to cover all filed variables, however consider the impact of refactoring in the case of future users if the class may be partially developed