Skip to content

Commit 720b315

Browse files
authored
Merge pull request #1317 from graphql-java/update-coding-guidelines
coding guidelines update
2 parents 6ddb87f + bd960df commit 720b315

1 file changed

Lines changed: 96 additions & 3 deletions

File tree

coding-guidelines.md

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ We have a mix of Optional and allowing null values because GraphQL Java was orig
2525

2626
We are aiming to not use Optional moving forward in order to be consistent overall.
2727

28-
29-
3028
### Unit testing and dependencies
3129
All tests are written in [Spock](http://spockframework.org).
3230

@@ -80,7 +78,7 @@ Every public data class should be:
8078

8179
- Immutable
8280
- having a Builder class
83-
- having a transform method
81+
- having a `transform` method
8482

8583

8684
Every data class should be immutable and contain a `public static class Builder {..}` with a static factory method `newFoo` (not `newBuilder`).
@@ -91,3 +89,98 @@ The class should also contain a `public Foo transform(Consumer<Builder> builderC
9189

9290
Private classes should follow the same design, but they don't have to.
9391

92+
### Default Collections idiom
93+
94+
The default pattern for using Set, Map and List is:
95+
- `List<Foo> fooList = new ArrayList<>()`
96+
- `Set<Foo> fooSet = new LinkedHashSet<>()`
97+
- `Map<Foo> fooMap = new LinkedHashMap<>()`
98+
99+
By using the generic interface instead of using an implementation we are making sure we
100+
don't rely on anything impl specific.
101+
The default implementations for `Set` and `Map` should be the `LinkedHashSet` and `LinkedHashMap`
102+
because it offers stable iteration order.
103+
104+
### Stream API vs for, index loop etc
105+
Using the Stream API is ok in general, but it must kept simple. Stream maps inside
106+
maps should be avoided and the inner logic should be refactored into a method.
107+
108+
It also ok to use the traditional for loop or other constructs: sometimes it is more readable than
109+
the modern Stream API. The Stream API is not a replacement for all other loops/iterations.
110+
111+
112+
### Maximum Indentation is two
113+
One of the most important rules is to keep the number of indentations as low as possible.
114+
In general the max number should be two. This means a for loop inside a condition is ok.
115+
A condition inside a for loop inside a for loop is not.
116+
117+
Extracting a method is the easy way out.
118+
119+
### Early method exit
120+
Exit the method early to avoid an indentation:
121+
122+
```java
123+
public void foo() {
124+
if(cond) {
125+
return;
126+
}
127+
...do something
128+
}
129+
```
130+
is better than:
131+
132+
```java
133+
public void foo() {
134+
if(!cond) {
135+
...do something
136+
}
137+
}
138+
```
139+
140+
### Maximum line length and multi line statements
141+
142+
We don't have a strict max line length.
143+
But of course every statement should be limited. Not so much in terms of length but much more in terms
144+
of what the statement does.
145+
146+
If a statement is multiple lines long it should be broken down into the same indentation level.
147+
148+
For example this is ok:
149+
```java
150+
return myMap
151+
.entrySet()
152+
.stream()
153+
.map(entry -> mapEntry(entry))
154+
.collect(Collectors.toList());
155+
```
156+
This is not ok:
157+
```java
158+
return fooListOfList.stream().map(
159+
fooList -> fooList.stream()
160+
.sorted((x,y) -> sort(x,y))
161+
.map(foo -> foo.getMyProp())
162+
.collect(toList())
163+
```
164+
It has a lambda in streams in streams. The inside stream should be extracted in a extra method and each
165+
method call should be on a new line:
166+
```java
167+
return fooListOfList
168+
.stream()
169+
.map(this::mapFooList)
170+
.collect(toList());
171+
```
172+
173+
### Every class its own file: avoid inner classes and interfaces
174+
Every class/interface should have its one file in general.
175+
Inner classes are almost never ok (especially public ones). Every class should have its own file to make it easier to read and explore the code.
176+
177+
### Use `graphql.Assert` instead of `Objects`
178+
We maintain our own small set of Assert util methods. Don't use `Objects.requireNonNull` and others in order
179+
to be consistent.
180+
181+
### `FooEnvironment` method arguments for public API
182+
Don't use specific arguments for interface methods but rather a `FooEnvironment` argument. This ensures future
183+
backwards compatibility when new inputs are added.
184+
185+
186+

0 commit comments

Comments
 (0)