Skip to content

Commit e3ec0fe

Browse files
committed
Add Java style guide.
1 parent 6864549 commit e3ec0fe

File tree

4 files changed

+258
-36
lines changed

4 files changed

+258
-36
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
Please include the following checklist in your PR:
1515

1616
- [ ] The documentation has been updated if necessary.
17-
- [ ] The code conforms to the [Scala](https://github.com/luna/enso/blob/master/doc/scala-style-guide.md) or [Haskell](https://github.com/luna/enso/blob/master/doc/haskell-style-guide.md) style guides as appropriate.
17+
- [ ] The code conforms to the [Scala](https://github.com/luna/enso/blob/master/doc/scala-style-guide.md), [Java](https://github.com/luna/enso/blob/master/doc/java-style-guide.md) or [Haskell](https://github.com/luna/enso/blob/master/doc/haskell-style-guide.md) style guides as appropriate.
1818
- [ ] The code has been tested where possible.
1919

doc/haskell-style-guide.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Haskell Style Guide
22
Like many style guides, this Haskell style guide exists for two primary reasons.
33
The first is to provide guidelines that result in a consistent code style across
4-
all of the Luna codebases, while the second is to guide people towards a style
4+
all of the Enso codebases, while the second is to guide people towards a style
55
that is expressive while still easy to read and understand.
66

77
In general, it aims to create a set of 'zero-thought' rules in order to ease the
@@ -42,7 +42,7 @@ This section explains the rules for visually laying out your code. They provide
4242
a robust set of guidelines for creating a consistent visual to the code.
4343

4444
### Whitespace
45-
The rules for whitespace in the Luna codebases are relatively simple:
45+
The rules for whitespace in the Enso codebases are relatively simple:
4646

4747
- 4 spaces are used for indentation, with no tabs.
4848
- There should not be any trailing whitespace.
@@ -145,7 +145,7 @@ multiple lines, it _no longer counts_ as visually similar, and hence subsequent
145145
lines should not be aligned with it.
146146

147147
### Naming
148-
Luna has some fairly simple general naming conventions, though the sections
148+
Enso has some fairly simple general naming conventions, though the sections
149149
below may provide more rules for use in specific cases.
150150

151151
- Types are written using `UpperCamelCase`.
@@ -183,9 +183,9 @@ module unqualified. This can be seen with `Map` in the examples below.
183183
This example is for a module that re-exports some names:
184184

185185
```hs
186-
module Luna.MyModule (module Luna.MyModule, module X) where
186+
module Enso.MyModule (module Enso.MyModule, module X) where
187187

188-
import Luna.MyModule.Class as X (foo, bar)
188+
import Enso.MyModule.Class as X (foo, bar)
189189

190190
import Prologue
191191

@@ -201,7 +201,7 @@ However, in the context where your module doesn't re-export anything, you can
201201
use the simplified form:
202202

203203
```hs
204-
module Luna.MyModule where
204+
module Enso.MyModule where
205205

206206
import Prologue
207207

@@ -219,8 +219,8 @@ module that hasn't been exported. To that end, we do not allow for restricted
219219
export lists in our modules.
220220

221221
Instead, if you want to indicate that something is for internal use, you need to
222-
define it in an internal module. For a module named `Luna.MyModule`, we can
223-
define internal functions and data-types in `Luna.MyModule.Internal`. This means
222+
define it in an internal module. For a module named `Enso.MyModule`, we can
223+
define internal functions and data-types in `Enso.MyModule.Internal`. This means
224224
that these functions can be imported by clients of the API if they need to, but
225225
that we provide no guarantees about API stability when using those functions.
226226

@@ -277,7 +277,7 @@ Code should be written in such a way that it guides you over what it does, and
277277
comments should not be used as a crutch for badly-designed code.
278278

279279
### Documentation Comments
280-
One of the primary forms of comment that we allow across the Luna codebases is
280+
One of the primary forms of comment that we allow across the Enso codebases is
281281
the doc comment. These are intended to be consumed by users of the API, and use
282282
the standard Haddock syntax. Doc comments should:
283283

@@ -392,12 +392,12 @@ Any good style guide goes beyond purely stylistic rules, and also talks about
392392
design styles to use in code.
393393

394394
### Libraries
395-
The Luna project has many internal libraries that are useful, but we have found
395+
The Enso project has many internal libraries that are useful, but we have found
396396
that maintaining these on Hackage while they are under such active development
397397
is counterproductive.
398398

399399
Instead, libraries live in the `lib/` folder of the primary project with which
400-
they are associated (Luna, Luna Studio, or Dataframes). These libraries may be
400+
they are associated (Enso, Enso Studio, or Dataframes). These libraries may be
401401
freely used by others of our projects by depending on a git commit of the
402402
project that they live in. All of these are safe to use.
403403

@@ -438,7 +438,7 @@ We have our own exception framework based on `ExceptT` that encodes exception
438438
usage at the type level. This ensures that all synchronous exceptions must be
439439
dealt with.
440440

441-
It is defined in [`lib/exception/`](https://github.com/luna/luna/tree/master/lib/exception)
441+
It is defined in [`lib/exception/`](https://github.com/Enso/Enso/tree/master/lib/exception)
442442
and contains utilities for declaring that a function throws an exception, as
443443
well as throwing and catching exceptions.
444444

@@ -468,14 +468,14 @@ in mind:
468468
- When designing a module that exports a type, the module should be named after
469469
that type. If it exports multiple types, there should be a primary type, or
470470
the other types should be factored out into their own modules.
471-
- We import modules as their name. If you have a module `Luna.Space.MyType`, we
471+
- We import modules as their name. If you have a module `Enso.Space.MyType`, we
472472
import it qualified as `MyType`.
473473
- Functions should be named with the assumption of being used qualified. This
474474
means that we rarely refer to the module name in the function name (e.g.
475475
`State.run` rather than `State.runState`).
476476

477477
### Data Declarations
478-
When declaring data types in the Luna codebases, please make sure to keep the
478+
When declaring data types in the Enso codebases, please make sure to keep the
479479
following rules of thumb in mind:
480480

481481
- For single-constructor types:
@@ -515,7 +515,7 @@ following rules of thumb in mind:
515515
+ Monad Transformers: `MonadTrans`.
516516

517517
#### Lenses
518-
The Luna codebases make significant use of Lenses, and so we have some rules for
518+
The Enso codebases make significant use of Lenses, and so we have some rules for
519519
their use:
520520

521521
- Always use the `makeLenses` wrapper exported from `Prologue`.
@@ -556,7 +556,7 @@ in a rigorous fashion.
556556
run, and should use the mechanisms HSpec provides for automatic test
557557
discovery.
558558
- A test file should be named after the module it tests. If the module is named
559-
`Luna.MyModule`, then the test file should be named `Luna.MyModuleSpec`.
559+
`Enso.MyModule`, then the test file should be named `Enso.MyModuleSpec`.
560560

561561
Any performance-critical code should also be accompanied by a set of benchmarks.
562562
These are intended to allow us to catch performance regressions as the code
@@ -598,7 +598,7 @@ of `foo $ bar $ baz $ bam quux`, you should write `foo . bar. baz $ bam quux`
598598
to use function composition.
599599

600600
## Language Extensions
601-
Much like any sophisticated Haskell codebase, Luna makes heavy use of the GHC
601+
Much like any sophisticated Haskell codebase, Enso makes heavy use of the GHC
602602
language extensions. We have a broad swath of extensions that are enabled by
603603
default across our projects, and a further set which are allowed whenever
604604
necessary. We also have a set of extensions that are allowed with care, which
@@ -616,9 +616,9 @@ extension (linked from the extension's table below).
616616

617617
### Default Extensions
618618
The following language extensions are considered to be so safe, or to have such
619-
high utility, that they are considered to be Luna's set of default extensions.
620-
You can find said set of extensions for Luna itself defined in a
621-
[common configuration file](https://github.com/luna/luna/blob/master/config/hpack-common.yaml).
619+
high utility, that they are considered to be Enso's set of default extensions.
620+
You can find said set of extensions for Enso itself defined in a
621+
[common configuration file](https://github.com/Enso/Enso/blob/master/config/hpack-common.yaml).
622622

623623
#### AllowAmbiguousTypes
624624

@@ -698,7 +698,7 @@ are promoted to kinds and the value constructors are promoted to type
698698
constructors.
699699

700700
This is incredibly useful, and used heavily in the type-level programming that
701-
makes the Luna codebase so expressive and yet so safe.
701+
makes the Enso codebase so expressive and yet so safe.
702702

703703
#### DefaultSignatures
704704

@@ -1365,7 +1365,7 @@ cause the typechecker to loop.
13651365

13661366
### Disallowed Extensions
13671367
If a language extension hasn't been listed in the above sections, then it is
1368-
considered to be disallowed throughout the Luna codebases. If you have a good
1368+
considered to be disallowed throughout the Enso codebases. If you have a good
13691369
reason to want to use one of these disallowed extensions, please talk to Ara or
13701370
Wojciech to discuss its usage.
13711371

doc/java-style-guide.md

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# Java Style Guide
2+
Like many style guides, this Java style guide exists for two primary reasons.
3+
The first is to provide guidelines that result in a consistent code style across
4+
all of the Enso codebases, while the second is to guide people towards a style
5+
that is expressive while still easy to read and understand.
6+
7+
In general, it aims to create a set of 'zero-thought' rules in order to ease the
8+
programmer burden; there is usually only _one way_ to lay out code correctly.
9+
10+
<!-- MarkdownTOC levels="2,3" autolink="true" -->
11+
12+
- [Code Formatting](#code-formatting)
13+
- [Naming](#naming)
14+
- [Commenting](#commenting)
15+
- [Documentation Comments](#documentation-comments)
16+
- [Source Notes](#source-notes)
17+
- [TODO Comments](#todo-comments)
18+
- [Other Comment Usage](#other-comment-usage)
19+
- [Program Design](#program-design)
20+
- [Testing and Benchmarking](#testing-and-benchmarking)
21+
- [Warnings, and Lints](#warnings-and-lints)
22+
23+
<!-- /MarkdownTOC -->
24+
25+
## Code Formatting
26+
This section explains the rules for visually laying out your code. They provide
27+
a robust set of guidelines for creating a consistent visual to the code.
28+
29+
Primary code formatting is done using the [Google Java Format](https://github.com/google/google-java-format)
30+
tool, which enforces a clear and consistent style. This is a zero configuration
31+
tool, and hence there is no project-level configuration for this tool. It should
32+
be used for all new Java projects.
33+
34+
All files must be formatted using this tool before being committed, and this
35+
should be set up as either a precommit hook, or using an integration in your
36+
IDE.
37+
38+
### Naming
39+
Enso has some fairly simple general naming conventions, though the sections
40+
below may provide more rules for use in specific cases.
41+
42+
- Types are written using `UpperCamelCase`.
43+
- Variables and function names are written using `camelCase`.
44+
- If a name contains an initialism or acronym, all parts of that initialism
45+
should be of the same case: `httpRequest` or `makeHTTPRequest`.
46+
- Short variable names such as `a` and `b` should only be used in contexts where
47+
there is no other appropriate name, and should _never_ be used to refer to
48+
temporary data in a function.
49+
- Names should be descriptive, even if this makes them longer.
50+
51+
## Commenting
52+
Comments are a tricky area to get right, as we have found that comments often
53+
expire quickly and, in absence of a way to validate them, remain incorrect for
54+
long periods of time. That is not to say, however, that we eschew comments
55+
entirely. Instead, we make keeping comments up to date an integral part of our
56+
programming practice, while also limiting the types of comments that we allow.
57+
58+
When we write comments, we try to follow one general guideline. A comment should
59+
explain _what_ and _why_, without mentioning _how_. The _how_ should be
60+
self-explanatory from reading the code, and if you find that it is not, that is
61+
a sign that the code in question needs refactoring.
62+
63+
Code should be written in such a way that it guides you over what it does, and
64+
comments should not be used as a crutch for badly-designed code.
65+
66+
### Documentation Comments
67+
One of the primary forms of comment that we allow across the Enso codebases is
68+
the doc comment. These are intended to be consumed by users of the API, and use
69+
the standard Javadoc syntax. Doc comments should:
70+
71+
- Provide a short one-line explanation of the object being documented.
72+
- Provide a longer description of the object, including examples where relevant.
73+
- Explain the arguments to a function where relevant.
74+
75+
They should not reference internal implementation details, or be used to explain
76+
choices made in the function's implementation. See [Source Notes](#source-notes)
77+
below for how to indicate that kind of information.
78+
79+
### Source Notes
80+
Source Notes is a mechanism for moving detailed design information about a piece
81+
of code out of the code itself. In doing so, it retains the key information
82+
about the design while not impeding the flow of the code.
83+
84+
Source notes are detailed comments that, like all comments, explain both the
85+
_what_ and the _why_ of the code being described. In very rare cases, it may
86+
include some _how_, but only to refer to why a particular method was chosen to
87+
achieve the goals in question.
88+
89+
A source note comment is broken into two parts:
90+
91+
1. **Referrer:** This is a small comment left at the point where the explanation
92+
is relevant. It takes the following form: `// Note [Note Name]`, where
93+
`Note Name` is a unique identifier across the codebase. These names should be
94+
descriptive, and make sure you search for it before using it, in case it is
95+
already in use.
96+
2. **Source Note:** This is the comment itself, which is a large block comment
97+
placed after the first function in which it is referred to in the module. It
98+
uses the java block-comment syntax `/* ... */`, and the first line names
99+
the note using the same referrer as above: `/* Note [Note Name]`. The name(s)
100+
in the note are underlined using a string of the `~` (tilde) character.
101+
102+
A source note may contain sections within it where necessary. These are titled
103+
using the following syntax: `== Note [Note Name (Section Name)]`, and can be
104+
referred to from a referrer much as the main source note can be.
105+
106+
Sometimes it is necessary to reference a source note in another module, but this
107+
should never be done in-line. Instead, a piece of code should reference a source
108+
note in the same module that references the other note while providing
109+
additional context to that reference.
110+
111+
An example, based on some code in the GHC codebase, can be seen below:
112+
113+
```java
114+
{
115+
public SimplM<SimplEnv, OutExpr> prepRHS(SimplEnv env, OutExpr outExpr) {
116+
var ty1 = coercionKind(env); // Note [Float Coercions]
117+
118+
if (!isUnliftedType(ty1)) {
119+
var newTy1 = convertTy(ty1) // Note [Float Coercions (Unlifted)]
120+
121+
...more code defining prepRHS...
122+
}
123+
}
124+
125+
/* Note [Float Coercions]
126+
~~~~~~~~~~~~~~~~~~~~~~~~~
127+
When we find the binding
128+
x = cast(e, co)
129+
we'd like to transform it to
130+
x' = e
131+
x = cast(x, co) // A trivial binding
132+
There's a chance that e will be a constructor application or function, or
133+
something like that, so moving the coercion to the usage site may well cancel
134+
the coercions and lead to further optimisation.
135+
...more stuff about coercion floating...
136+
137+
== Note [Float Coercions (Unlifted)]
138+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139+
...explanations of floating for unlifted types...
140+
*/
141+
}
142+
```
143+
144+
A source note like this is useful whenever you have design decisions to explain,
145+
but can also be used for:
146+
147+
- **Formulae and Algorithms:** If your code makes use of a mathematical formula,
148+
or algorithm, it should note where the design element came from, preferably
149+
with a link.
150+
- **Safety:** Sometimes it is necessary to use an unsafe API in a context where
151+
it is trivially made safe. You should always use a source note to explain why
152+
its usage is safe in this context.
153+
154+
### TODO Comments
155+
We follow a simple convention for `TODO` comments in our codebases:
156+
157+
- The line starts with `TODO` or `FIXME`.
158+
- It is then followed by the author's initials `[ARA]`, or for multiple people
159+
`[ARA, WD]`, in square brackets.
160+
- It is then followed by an explanation of what needs to be done.
161+
162+
For example:
163+
164+
```java
165+
{
166+
// TODO [ARA] This is a bit of a kludge. Instead of X it should to Y, accounting
167+
// for the fact that Z.
168+
}
169+
```
170+
171+
### Other Comment Usage
172+
There are, of course, a few other situations where commenting is very useful:
173+
174+
- **Commenting Out:** You may comment out code while developing it, but if you
175+
commit any commented out code, it should be accompanied by an explanation of
176+
why said code can't just be deleted.
177+
- **Bugs:** You can use comments to indicate bugs in our code, as well as
178+
third-party bugs. In both cases, the comment should link to the issue tracker
179+
where the bug has been reported.
180+
181+
## Program Design
182+
Any good style guide goes beyond purely stylistic rules, and also talks about
183+
design styles to use in code.
184+
185+
### Testing and Benchmarking
186+
New code should always be accompanied by tests. These can be unit, integration,
187+
or some combination of the two, and they should always aim to test the new code
188+
in a rigorous fashion.
189+
190+
- We tend to use ScalaTest, but also make use of ScalaCheck for property-based
191+
testing.
192+
- Tests should be declared in the project configuration so they can be trivially
193+
run.
194+
- A test file should be named after the module it tests.
195+
196+
Any performance-critical code should also be accompanied by a set of benchmarks.
197+
These are intended to allow us to catch performance regressions as the code
198+
evolves, but also ensure that we have some idea of the code's performance in
199+
general.
200+
201+
- We use Caliper for our benchmarks.
202+
- We measure time, but also memory usage and CPU time where possible.
203+
- Where relevant, benchmarks may set thresholds which, when surpassed, cause the
204+
benchmark to fail. These thresholds should be set for a release build, and not
205+
for a development build.
206+
207+
_Do not benchmark a development build_ as the data you get will often be
208+
entirely useless.
209+
210+
### Warnings, and Lints
211+
In general, we aim for a codebase that is free of warnings and lints, and we do
212+
this using the following ideas.
213+
214+
#### Warnings
215+
New code should introduce no new warnings onto master. You may build with
216+
warnings on your own branch, but the code that is submitted as part of a PR
217+
should not introduce new warnings. You should also endeavour to fix any warnings
218+
that you come across during development.
219+
220+
Sometimes it is impossible to fix a warning (often in situations involving the
221+
use of macros or code-generation). In such cases, you are allowed to suppress
222+
the warning locally, but this must be accompanied by a source note explaining
223+
why you are doing so.

0 commit comments

Comments
 (0)