Coding Standard#
Java#
Clean code#
- Clean code is code that other developers can easily read, understand, and add to.
- Developers can easily understand what the code is doing without going into low-level implementation details. Good code is self-documented.
- Clean code is easy to maintain in the long run, easy to update and extend.
- KISS - Keep it stupid simple.
- Single responsibility - a class/function should do only one thing.
- DRY - Don't repeat yourself.
Names#
- The
name
of a variable, function, or class should tell why it exists, what it does, and how it is used. classes and objects
should have noun or noun phrase names → Example: Vehicle, Invoice, ConfigurationPage etc...methods
should have verb or verb phrase names → Example: deleteInvoice, createVehicle, etc...methods names
for principal operations should start with: get, create, update, delete.choosing names
that reveal the intent make it much easier to understand the code and to work on it.-
Don't mislead by using inappropriate naming
-
Avoid using words that can lead other developers to confusion, such as the word
List
.1
private List<Student> students;
1
private List<Student> studentList;
-
Avoid including
the type of a variable
in the variable name.1
private Integer amount;
1
private Integer amountInteger;
-
Don't use
long variable/method or class names
that are very similar to one another.1 2 3 4 5 6 7
public class JwtHandler { public boolean IsValidated(String jwtToken) { ... } }
1 2 3 4 5 6 7
public class PasswordJsonWebTokenValidator { public boolean IsJsonWebTokenPasswordValid(String jwtToken) { ... } }
-
Avoid uppercase
o (O)
and lowercasel (L)
in variable names. - Use names that can be pronounced.
- Use names that can be searched.
Don't use single characters in class, method, and variable names
(example: a, e, b, c etc...). Not only they do not reveal their intention, but when searching for the usage of variable e you will get irreverent results.
-
Modules#
- A new component should be composed of two parts: api and impl.
- api module contains interfaces, dto classes, and exceptions which will be used on impl module.
- Impl module will contain the logic of the new component and the Junit tests.
- Each package should reveal the reason:
- application - service classes
- domain - api → dto classes, impl→ dao classes
- exception - exception classes
- config - configuration classes
- infrastructure - lower-level classes that deal with systems directly: service classes, repository, etc.
- rest - controller classes
Classes#
- Should be small.
- Should have one and only one reason.
Function#
- Should be small and easy to be understood. Up to 20 lines long, preferably smaller.
- Do one thing.
- Blocks inside if, else, while statements should be function calls, keeping the size down and also contributing to code documentation by using descriptive names.
- Avoid nested if statements. Function block-level indentation should only go up to two levels deep.
Argument#
- The rule for the number of arguments a function should have simple, less as possible
- Three arguments should be avoided where possible and more than three requires special justification and should be avoided at all costs.
Flag Arguments#
- Passing a boolean into a function is bad practice.
- It gives the idea that the function does two things if the boolean is false and another if it is true.
Argument objects#
- When a function requires more than three arguments you should consider grouping them into separate classes.
Argument lists#
- Argument lists of the same type, used for example in String.format are considered a single argument since it can be treated as a List.
Verbs and keywords:#
- Function naming should not be dealt with superficially. In the case of a monadic function, for example, the name should form a verb -> noun pair.
- For example: save(user).
Avoid side effects#
- If your function is called save(user), as in the example above, it should only do this one thing, save the user input data.
Error Handling#
- Use exceptions rather than return codes.
- Don't return null.
- Define custom exceptions.
Comments#
- We should avoid using comments because that reveals that the code is not written well comments should be used only when our code cannot express in an easy-to-understand manner what it is doing log comments should be used only where is absolutely necessary.
- A few reasons why comments should be avoided:
- Comments clutter code.
- Comments can encourage bad code.
- Comments can "lie". Code evolves constantly and comments can be outdated and not reflect what the code is actually doing.
- Time invested in writing comments should be directed in writing better code that is easy to understand.
Warning#
- Some comments can be useful to prevent other developers from making changes that would have unwanted consequences. The below comment, for example, could prevent another programmer from using a static initializer.
TODOs#
- TODO comments can be used as:
- Reminders to complete functionality that cannot be completed during the time of writing (for whatever reason).
- Reminders for other developers to look at potential problems.
- Reminders to look for better naming.
- Delete deprecated functionality.
- Whatever the reason for leaving TODOs it is important to regularly check them and eliminate them. TODOs should not be used as excuses to write bad code.
Formatting conventions#
- The most important aspect of formatting is standardization and consistency. Formatting helps good communication between developers, a reason why it should not be ignored.
Vertical formatting#
- Here are a few good principles to follow:
- File names and modules should accurately describe it's high-level purpose.
- At the beginning of a file, we should find high-level details, concepts, and algorithms.
- As we read down into the source file we should go from high-level details to lower-level implementation details.
- Use blank lines only to separate concepts.
- Keep lines of code that are tightly related in functionality together.
- Keep imports and dependency declarations clean and updated.
- Closely related concepts should be kept together.
- Because of (7) try to avoid using protected variables too often.
- Variables should be declared as close as possible to their usage.
- Local variables should appear at the top of the method.
- Loop variables should be declared inside the loop.
- Instance variables should be declared at the top of the class.
- Dependent functions should be vertically close to each other.
- Function call dependency should be ordered from top to bottom.
- Order of declaration should be:
- static variables.
- public variables.
- protected variables.
- no access modifier (package) variables.
- private variables.
- constructors.
- methods.
- Methods should be grouped by functionality rather than by scope or accessibility. For example, a private class method can be in between two public instance methods. The goal is to make reading and understanding the code easier.
Horizontal formatting#
- Each line should be as short as possible. It is easier to read and to follow across the code.
- The rule of thumb is to keep the lines in a file to a length that doesn't force horizontal scrolling. On a typical modern display, this can vary from 80 to 120 characters in normal readable font size.
- Just as in vertical formatting there are a few principles that each developer should follow:
- Use horizontal white spaces to associate or disassociate things that are related or not related.
- Use indentation to accentuate the hierarchy of scopes in a file.
- Avoid collapsing scopes.
- Avoid dummy scopes with no body or use visible braces to make them visible.
Checkstyle#
- For the checkstyle we use SonarLint
- It can be added from IntelliJ IDEA plugins section.
- We use the default configuration.