Coding Standards
General Principles
This library is coded in the pseudo-functional style that has become possible with Java 8. We use these general principles for functional style coding in Java:
- Immutability is the core concept of functional programming
- Use private constructors for most classes
- Use a static “of” method as a builder method if there are one or two attributes. If there are two attributes, they may not be of the same type. A Builder class is preferred with two attributes, but “of” may be used to make the code more compact or readable in some cases.
- Generally use a static Builder class if more than one attribute is required to initialize a class
- Builders only have a zero argument constructor. All attributes set with “with” methods.
- When using a Builder, private class constructors take the Builder as the only argument
- Class constructors using a Builder should check for null if an attribute is required.
- In Builders, Lists should be initialized and then populated with
add
oraddAll
. Classes may directly reference the list in the builder. - In Builders, Maps should be initialized and then populated with
put
orputAll
. Classes may directly reference the map in the builder. - Builders may be mutable, other classes may not be mutable.
- No setters
- Classes never expose a modifiable List. Lists are exposed with an unmodifiable List, or a Stream.
- Classes never expose a modifiable Map. A Map may be exposed with an unmodifiable Map.
- Avoid direct use of null. Any Class attribute that could be null in normal use should be wrapped in a
java.util.Optional
- Avoid for loops (imperative) - use map/filter/reduce/collect (declarative) instead
- Avoid Stream.forEach() - this method is only used for side effects, and we want no side effects
- Avoid Optional.ifPresent() - this method is only used for side effects, and we want no side effects
- The only good function is a pure function. Some functions in the library accept an AtomicInteger which is a necessary evil
- Classes with no internal attributes are usually a collection of utility functions. Use static methods in an interface instead.
- Remember the single responsibility principle - methods do one thing, classes have one responsibility
Clean Code
We are committed to clean code. This means:
- Small methods - less than 5 lines is good, 1 line is ideal
- Small classes - less than 100 lines is good, less than 50 lines is ideal
- Use descriptive names
- Comments are a last resort - don't comment bad code, refactor it
- No nested control structures - ideal cyclomatic complexity of a function is 1
- Maintain 100% test coverage
- Run SonarQube analysis - do not add any technical debt, bugs, code smells, etc.
Test Driven Development
Remember the three rules of TDD:
- You may not write production code until you have written a failing unit test.
- You may not write more of a unit test than is sufficient to fail, and not compiling is failing.
- You may not write more production code than is sufficient to passing the currently failing test.