* [2 General Design Philosophy](#2-general-design-philosophy)
* [3 Specific Design Techniques](#3-specific-design-techniques)
* [4 Java](#4-java)
* [5 Logging](#5-logging)
# 1 Introduction
This document contains guidelines (some stricter than others) so we can be consistent and spend more time solving the bigger and more interesting issues.
The guidelines are intended to facilitate working together not to facilitate reviews that criticize without adding value.
Some guidelines are personal opinion. The idea being we make a decision once, document it, and apply it for consistency. Again, we can then spend more time on the interesting issues and less time discussing coding conventions :-)
# 2 General Design Philosophy
The key principles are:
* Keep It Simple
* Idiomatic Java
* YAGNI (You Ain't Gonna Need It)
## 2.1 Keep It Simple
Simple does not mean the fewest lines of code. Simple code is:
* Easy to understand
* Self-documenting and not dependent on comments to explain what it does
* Understandable even to inexperienced Java developers
* Dependent on selecting the right data structures for the task
* Usually the most performant. Without data showing another approach is faster, stick with the simple design
* Providing alternate behaviours via polymorphism instead of having conditional logic scattered through the codebase. For example, `ProtocolSpec` provides a standard interface to blockchain operations and multiple implementations define the different behaviours for each Ethereum milestone.
* Encapsulating behaviour and data together in classes. For example, `Bytes` encapsulates byte data and methods operating on the byte data. `Bytes.isZero()` is an instance method instead of accepting a `Bytes` parameter.
`ProtocolSpec` is an exception and does not hold the blockchain data on which it operates. This is because that blockchain data is widely shared and not specifically owned by `ProtocolSpec`.
* Embracing modern Java features like Optional, Streams and lambdas when they make code simpler and clearer.
- Do use Streams and map with lambdas to convert values in a list to a different form.
- Don't pass lambdas into executors because it makes it harder to identify the threading interactions. The lambda makes the code shorter but not clearer. Instead use a separate class or extract a method.
* For good examples, refer to the APIs the JDK itself exposes.
The Besu design prioritizes meeting current requirements in the simplest, clearest way over attempting to anticipate future functionality. As a result, Besu’s design:
- Be thoughtfully organised in terms of method order, package structure, and module usage
- Follow well-established patterns and conventions
- Be consistent
- Make it easy to follow the control flow by _clicking through_ in an IDE
- Make it easier to use the right way than the wrong way
- Avoid abbreviations. We are a global team and when English is a second language abbreviations reduce readability. The following abbreviations are exceptions:
* tx -> Transaction
* IBFT -> Istanbul Byzantine Fault Tolerant (a consensus protocol)
To automatically reformat the code before creating a pull request, run:
```json
./gradlew spotlessApply
```
### 4.1.1 Install Google Style Settings
The Google style settings can be installed in [Intellij](https://github.com/google/google-java-format#intellij) and [Eclipse](https://github.com/google/google-java-format#eclipse).
## 4.2 Additional Java Style Guidelines
## 4.2.1 Fields
Class-level fields are generally not separated by blank lines but can use a blank line to separate them into logical groupings.
## 4.2.2 Final Keyword
Method parameters must be final. Class level and local fields should be final whenever possible.
## 4.2.3 Common Methods
* Getters follow idiomatic format with `get` prefix. For example, `getBlock()` gets a block property.
* Setters follow idiomatic format with `set` prefix. For example, `setBlock(Block block)` sets a block property.
* Equals and `hashCode()` methods use the `Object.equals` and `Object.hash` methods (this is the _Java 7+_ template in IntelliJ. Don’t accept subclasses and don’t use getters)
## 4.2.4 Testing
* Don't use a fixed prefix (for example, `test`). Do explain the expected behaviour not just the situation
Good: `returnTrueWhenValueIsXyz()`
Bad: `valueIsXyz()`
* Use AssertJ for assertions in preference to JUnit’s Assert class.
To help future-proof the code (avoiding libraries that may be deprecated in the near future), avoid assertions from the `org.assertj.core.api.Java6Assertions` class. Java6 in the name is a concerning signal
## 4.2.5 Miscellaneous
* When creating loggers it should be the first declaration in the class with:
`private static final Logger LOG = getLogger();`
* Ternary operators are acceptable when they make the code clearer but should never be nested
* Avoid TODO comments. Log a ticket instead
* Specify Gradle dependency versions in `versions.gradle`
Logging is important for understanding what Besu is doing at any given time (for example, progress while synchronizing) and investigating defects. During development, add logging to aid in these cases.