Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Added Coding Conventions #342

Merged
merged 4 commits into from
Dec 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 220 additions & 0 deletions CODING-CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# Contents
* [1 Introduction](#1-introduction)
* [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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not restrict people from writing comments. Self-Documenting is fine, but avoiding comments is a terrible idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't say don't write comments. It says we prefer to write code that doesn't need them to explain it.

* 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
* Not simplistic:

- Ethereum is complex and Pantheon must handle this complexity and operate correctly and securely
- Pantheon code should align with well-established Ethereum abstractions and terminology used in Ethereum specifications
- Aim to make the code as simple as possible but no simpler

## 2.2 Idiomatic Java

Pantheon embraces typical Java idioms including using an Object Oriented approach to design. This includes:
* 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, `BytesValue` encapsulates byte data and methods operating on the byte data. `BytesValue.isZero()` is an instance method instead of accepting a `BytesValue` 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.

>**Note** If you're not sure what idiomatic Java looks like, start by following the typical patterns and naming used in Pantheon.

## 2.3 You Ain't Gonna Need It (YAGNI)

The Pantheon design prioritizes meeting current requirements in the simplest, clearest way over attempting to anticipate future functionality. As a result, Pantheon’s design:
* Is not set in stone as a big upfront design. The design is adjusted through constant refactoring as new requirements are added and understood.
* Uses abstraction only where it aids understanding of the current code. Abstraction is not used where it only supports future needs.
* Avoids over-engineering.

# 3 Specific Design Techniques

# 3.1 Creating Understandable, Self-documenting Code

To create understandable, self-documenting code:
- Use clear naming for variables, methods, and classes
- Use US spelling instead of UK. For example, synchronize instead of synchronise
- Keep methods and classes short and focused on a single responsibility. Preferable maximum lengths:
* Lambdas: 1 - 3 lines
* Methods: less than 50 lines
* Anonymous classes: less than a 50 lines
* Inner classes: not much more than 50 lines
* Classes: a few hundred lines
- 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)
* EVM -> Ethereum Virtual Machine

# 3.2 Creating Code for Constant Refactoring and Evolving Design

So the code can cope with constant refactoring and evolving design, write code that:
* Is well tested.

Avoid test cases requiring detailed interactions with mocks because these are often brittle.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line need more details or examples


* Avoids duplication.

* Follows the Single Responsibility Principle where each class is responsible for one thing.

>**Note** It is important to scope the responsibility wisely. Responsibilities that are:
> * Too small lead to an explosion of classes making things hard to follow
> * Too large lead to the class becoming big and unwieldy

* Favors composition over inheritance. You can use inheritance, but prefer composition

* Uses dependency injection
- Constructors should be simple, with dependencies passed in rather than built in the constructor
- Pantheon does not use a dependency injection framework

* Validates method parameters for public methods using the Guava `Preconditions` class. Avoid validating parameters in private methods

* Generally avoids interfaces with a single implementation unless they are explicitly being used to narrow the exposed API

* Uses the most general applicable type. For example, `List` or `Collection` instead of `ArrayList`

## 3.3 Additional Design Elements


* Use Optional rather than returning null when not having a value is a normal case

* Consider exception and error handling as part of the overall design. Pantheon avoids checked exceptions

* Give threads meaningful names. For example:
`Executors.newFixedThreadPool(1, new ThreadFactoryBuilder().setNameFormat(“Ibft”).build())`


# 4 Java

## 4.1 Style Guide

Pantheon follows the [Google code style](https://google.github.io/styleguide/javaguide.html) and uses spotless to ensure consistency of formatting.

To automatically reformat the code before creating a pull request, run:

```json
./gradlew spotlessApply
```

### 4.1.1 Install Google Style Settings
MadelineMurray marked this conversation as resolved.
Show resolved Hide resolved

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.
* For `toString methods`, use the Guava 18+ `MoreObjects.toStringHelper`
* 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`

* Don't use two or more blank lines in a row

# 5 Logging

Logging is important for understanding what Pantheon is doing at any given time (for example, progress while synchronizing) and investigating defects. During development, add logging to aid in these cases.

## 5.1 Log Messages

Make log messages:
* Not so frequent they are overwhelming in the log output
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed as it is handled by the next line.

* At the appropriate level
* Detailed enough to understand what actually happened. For example:

`Insufficient validators. Expected 10 but found 4`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest more detail like: Insufficient validators. Expected 10 but found 4, and here they are: [list of validators]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practical experience actually including the full list of validators was completely overwhelming in log output.


* As succinct as possible while still being clear.

* Bad: `Insufficient validators. Expected 10 but got: [address, address, address, address, address, address]`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No! This is an excellent. This should absolutely be there. It is far easier to track down what is missing when the data is printed in the log message.


## 5.2 Log Levels

* _Trace_

Extremely detailed view showing the execution flow. Likely only useful to developers

* _Debug_

Information that is diagnostically helpful to a wider group than just developers (for example, sysadmins)

* _Info_

Generally useful information to log (for example, service start/stop, configuration assumptions). Default logging level

* _Warn_

Anything that can potentially cause application oddities but from which Pantheon automatically recovers

* _Error_

Any error which is fatal to the operation, but not Pantheon itself (for example, missing data)

* _Fatal_

An error that forces a shutdown of Pantheon
15 changes: 6 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ Welcome to the Pantheon repository! The following is a set of guidelines for co
* [Code Reviews]

[Style Guides](#style-guides)
* [Git Commit Messages & Pull Request Messages](#git-commit-messages--pull-request-messages)
* [Java Style Guide](#java-code-style-guide)

* [Coding Conventions](#coding-conventions)
* [Git Commit Messages & Pull Request Messages](#git-commit-messages--pull-request-messages)

[Issue and Pull Request Labels](#issue-and-pull-request-labels)

## Code of Conduct
Expand Down Expand Up @@ -145,6 +146,7 @@ Please follow these steps to have your contribution considered by the approvers:
While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. Please refer to [Code Reviews].

# Style Guides

## Java Code Style Guide

We use Google's Java coding conventions for the project. To reformat code, run:
Expand All @@ -155,13 +157,8 @@ We use Google's Java coding conventions for the project. To reformat code, run:

Code style will be checked automatically during a build.

### Other Java Code Conventions
We have a set of coding conventions that we try to adhere to. These are not strictly enforced during the build, but should be adhered to and called out in code reviews.
* Avoid abbreviations in variable names (ie, use message instead of msg)
* never 2 blank lines in a row

Exceptions:
* Allowed abbreviation: Tx instead of Transaction (it's historical)
## Coding Conventions
We have a set of [coding conventions](CODING-CONVENTIONS.md) to which we try to adhere. These are not strictly enforced during the build, but should be adhered to and called out in code reviews.

## Git Commit Messages & Pull Request Messages
* Use the present tense ("Add feature" not "Added feature")
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ User and reference documentation available on the Wiki includes:
## Pantheon Developers

* [Contribution Guidelines](CONTRIBUTING.md)
* [Coding Conventions](CODING-CONVENTIONS.md)
* [Wiki] for running and using Pantheon

### Development
Expand Down