General Principles
- Write clean and readable code.
- Prefer clarity over cleverness.
- Keep methods and classes small and focused.
- Avoid unnecessary complexity.
Code should always be understandable for other developers working on the project.
Naming Conventions
Use clear and descriptive names.
Classes
Classes should use PascalCase.
Example:
Methods and Variables
Use camelCase.
Example:
Avoid Repeated Method Chains
Avoid calling the same method chains multiple times within a method.\ Instead, store frequently used objects in local variables.
Repeated calls reduce readability and make the code harder to maintain.
Avoid:
getPlugin().getKitManager().getKit(name).getDisplayName();
getPlugin().getKitManager().getKit(name).getOrderId();
Prefer:
KitManager kitManager = getPlugin().getKitManager();
KnockbackFFAKit kit = kitManager.getKit(name);
kit.getDisplayName();
kit.getOrderId();
This improves:
- readability
- maintainability
- debugging
and prevents long and repetitive method chains
Constants
Constants (static final) should use UPPER_CASE.
Example:
Prefer Early Returns over Nested if / else
Avoid deeply nested if / else if / else structures.\
Instead, use early returns (guard clauses) to handle edge cases first and keep the main logic readable.
Deep nesting quickly makes code harder to read and maintain.
Avoid:
if (args.length >= 1) {
KitManager kitManager = getPlugin().getKitManager();
KnockbackFFAKit kit = kitManager.getKit(args[0]);
if (kit != null) {
if (args.length == 1) {
getPlugin().getManager().openKitEditMenu(player, kit);
} else {
String action = args[1];
kitManager.editKit(player, kit, args, action);}
} else {
player.sendMessage(DisplayData.KIT_DOESNT_EXIST);
}
}
Prefer:
if (args.length < 1) return;
KitManager kitManager = getPlugin().getKitManager();
KnockbackFFAKit kit = kitManager.getKit(args[0]);
if (kit == null) {
player.sendMessage(DisplayData.KIT_DOESNT_EXIST);
return;
}
if (args.length == 1) {
getPlugin().getManager().openKitEditMenu(player, kit);
return;
}
String action = args[1];
kitManager.editKit(player, kit, args, action);
Benefits:
- reduces indentation
- improves readability
- makes error cases explicit
- keeps the main logic easier to follow
Logging
Use proper logging instead of printing to console.
Avoid:
Use:
Null Safety
Always check for possible null values where applicable.
Example:
Avoid assumptions that may cause NullPointerExceptions.
JetBrains Annotations
Use JetBrains annotations to make nullability explicit:
@NotNull@Nullable
They help to:
- improve readability
- prevent null-related bugs
- define clear method contracts
Example:
public void sendMessage(@NotNull Player player, @Nullable Component message) {
if (message == null) return;
player.sendMessage(message);
}
Avoid Static Abuse
Avoid excessive use of static fields or global access patterns such as singleton-style getInstance() methods.
Static access creates strong coupling between classes and makes code harder to maintain, test, and refactor.
Avoid:
or long global chains:
Prefer passing dependencies through constructors or storing them in fields.
Prefer:
public class KitHolder {
private final KitManager kitManager;
public KitHolder(KitManager kitManager) {
this.kitManager = kitManager;
}
public void giveKit(BukkitPixelPlayer player {
kitManager.getKit("archer").applyTo(player);
}
}
Benefits:
- clearer dependencies
- easier testing
- better maintainability
- reduced global state
Static fields should only be used where they are truly appropriate, such as:
- constants
- utility classes without state
Avoid using static access as a shortcut to reach managers or plugin instances.
Comments
Use comments when code is not immediately obvious.
Avoid obvious comments:
Prefer explaining why, not what.
Example:
// Prevent players from claiming the plot again while it is already being claimed
if (plotManager.isClaiming(player)) return;
Performance
Avoid expensive operations in frequently called methods such as:
- event listeners
- tick tasks
- loops over large collections
Cache values where appropriate.
Never execute SQL or Redis operations on the main thread!
Minecraft runs primarily on a single main thread, and blocking operations such as database or Redis calls will cause server lag or tick delays. Even Redis operations can introduce small blocking delays.
All database and external service operations must therefore be executed asynchronously (off-thread).
Testing
Before submitting a merge request:
- test your feature on the [[Dev Server|Development/Dev-Server]]
- verify that it does not break existing systems