This style guide outlines the conventions and best practices for writing clean, maintainable, and consistent code. Following these guidelines will help ensure that our codebase remains easy to read and collaborate on.
All source files must use UTF-8 encoding.
The source file must exactly match the public class name (case-sensitive) contained within it and end with the .java extension (e.g. Main.java).
All source files must use Unix-style line endings (\n).
To ensure consistency, configure your git client to use core.autocrlf set to input on Unix/Linux/MacOS systems and true on Windows systems.
To set this configuration, run the following command:
$ git config --global core.autocrlf input # for Unix/Linux/MacOS
$ git config --global core.autocrlf true # for WindowsYou must use tabs for indentation. A single tab character is used for every level of indentation.
In IntelliJ, you can find the indentation settings under: Settings > Editor > Code Style > Java.
Select the Tabs and Indentations tab and ensure that the Use tab character option is checked.
You can set your tab size via the Tab size field (commonly set to 4).
The same applies for indentation in xml (e.g. pom.xml) files.
There is no hard limit on line length, but lines should be kept reasonably short for readability. If lines must be wrapped, do so according to the guidelines in section TODO.
The projects top-level package is de.unistuttgart.einf.moviemanager.
All packages must be named in all lowercase and avoid underscores, hyphens, or other special characters.
Class, interface, enum and record names must be written in PascalCase (UpperCamelCase).
- Classes: Nouns describing the object (e.g.
Movie,MovieManager) - Interfaces: Nouns (e.g.
Storage) or adjectives (e.g.Watchable) - Enums: Nouns describing a set of related constants (e.g.
Genre,Rating) - Records: Nouns describing the data they hold (e.g.
MovieData,UserInfo)
Method names must be written in camelCase and should generally be verbs or verb phrases describing the action (e.g. openWindow, calculateRating).
- Getters: Must start with
get(e.g.getTitle(),getReleaseDate()).- Booleans: Must start with
is,hasorcan(e.g.isAvailable(),hasSubtitles(),canPlay()).
- Booleans: Must start with
- Setters: Must start with
set(e.g.setTitle(String title)).
Variables names must be written in camelCase and be meaningful.
Avoid single-letter names unless used as loop counters (e.g. i, j, k).
Constant names (fields that are static final) must be written in UPPER_SNAKE_CASE (all uppercase letters with words separated by underscores) (e.g. MAX_RETRIES, DEFAULT_TIMEOUT).
Type parameter names must be single uppercase letters (e.g. <T> for Type, <E> for Element, <K, V> for Key/Value).
We use the K&R style for braces: the opening brace { is placed at the end of the current line, and the closing brace } is placed on a new line aligned with the beginning of the line containing the corresponding opening brace.
A single tab is used for every level of indentation (after opening braces {).
Empty lines should not contain any whitespace characters (spaces or tabs).
In IntelliJ, you can enforce this under Settings > Editor > Code Style > Java. Select the Tabs and Indents tab and make sure the option Keep indents on empty lines is unchecked.
If a block (e.g. method, class, control structure) is empty, opening and closing braces may be placed on the same line.
- Binary Operators: Always surround binary operators (e.g.
=,+,-,*,/,==,!=,<,>,<=,>=,&&,||, etc.) with a single space (e.g.a + b,x == y). - Keywords: Always follow keywords (e.g.
if,for,while,switch,return,catch, etc.) with a single space (e.g.if (condition),for (int i = 0; i < n; i++)). - Method/Constructor calls: Do not put a space between the method/constructor name and the opening parenthesis
((e.g.myMethod(arg1, arg2)). - Commas: Always follow a comma
,with a single space (e.g.arg1, arg2, arg3). - Semicolons: Do not put a space before a semicolon
;.
Layout static imports and regular imports separately.
Ensure that all source files end with a single newline character.
In IntelliJ, you can do this by selecting the Ensure every saved file ends with a line break option under Settings > Editor > General.
When a line exceeds a reasonable length, break it at logical points such as after commas, before operators, or after opening parentheses.
This is a simple non-exhaustive example demonstrating the above formatting rules:
public class FooBar {
public static final int MAX_COUNT = 100;
private int count;
public FooBar() {
this.count = 0;
}
public FooBar(int initialCount) {
this.count = initialCount;
}
public void incrementCount() {
if (count < MAX_COUNT) {
count++;
} else {
System.out.println("Maximum count reached.");
}
}
public int getCount() {
return count;
}
public boolean canIncrement() {
return count < MAX_COUNT;
}
public boolean isMaxedOut() {
return count >= MAX_COUNT;
}
}All public, protected and package-private members, classes, interfaces, enums and records must be documented using Javadoc comments.
Use tags such as @param, @return, and @throws where appropriate and in this following order:
@param@return@throws@see
Generally, implementation comments should be avoided in favor of clear and self-explanatory code. However, if a complex or non-obvious piece of code requires explanation, comments should be used judiciously to clarify intent.
Before adding a comment, consider whether the code can be refactored to be more understandable, e.g. by extracting methods with descriptive names or using well-named variables.
Use // for brief and /* ... */ for longer comments.
If not possible otherwise, use // TODO: to indicate tasks that need to be completed later.
Avoid wildcard imports (e.g. import java.util.*;), unless the number of imported classes from the same package is reasonably high (e.g. more than 5).
This can be automatically configured in IntelliJ under the Settings > Editor > Code Style > Java > Imports tab by setting the Class count to use import with '*' value to 5.
Prefer early exits in methods to reduce nesting and improve readability, e.g.
if (!isValid(input)) {
return;
}
// proceed with valid inputin favor of
if (isValid(input)) {
// proceed with valid input
}- Catch specific exceptions instead of generic ones (e.g.
IOExceptioninstead ofException). - Throw exceptions that are meaningful and provide context about the error (e.g.
throw new IllegalArgumentException("number must be non-negative")).
Use the diamond operator <> to infer generic types where possible (e.g. List<String> list = new ArrayList<>();).
Prefer interfaces (e.g. List, Map, Set) over concrete implementations (e.g. ArrayList, HashMap, HashSet) when declaring variables, return types, and parameters.