blob: 7afbde246af3591dbf37a7897d2cc0a30d61bc61 [file] [log] [blame] [view]
sullivan1355e182016-03-05 02:34:561# Catapult Style guide
2
3## Base style guide
4
5Unless stated below, we follow the conventions listed in the [Chromium style
6guide](https://www.chromium.org/developers/coding-style) and [Google JavaScript
7style guide](http://google.github.io/styleguide/javascriptguide.xml).
8
eakuefnera8a844e2017-01-06 18:24:509## JavaScript
10
11### Files
sullivan1355e182016-03-05 02:34:5612File names `should_look_like_this.html`.
13
14Keep to one concept per file, always. In practice, this usually means one
15component or class per file, but can lead to multiple if they’re small and
16closely related. If you can, group utility functions into a static class to
17clarify their relationship, e.g. `base/statistics.html`.
18
benjhaydenb11ee722016-09-21 17:08:4619```html
sullivan1355e182016-03-05 02:34:5620<!-- tracing/model/point.html -->
21<script>
22‘use strict’;
23
24tr.exportTo(‘tr.model’, function() {
25 function Point() {}
26
27 return {
28 Point: Point
29 };
30});
31</script>
32```
33
34The exception to this rule is when there are multiple small, related classes or
35methods. In this case, a file may export multiple symbols:
36
benjhaydenb11ee722016-09-21 17:08:4637```html
sullivan1355e182016-03-05 02:34:5638<!-- tracing/base/dom_helpers.html -->
39<script>
40‘use strict’;
41
42tr.exportTo(‘tr.ui.b’, function() {
43 function createSpan() { // … }
44 function createDiv() { // … }
45 function isElementAttached(element) { // … }
46
47 return {
48 createSpan: createSpan,
49 createDiv: createDiv,
50 isElementAttached: isElementAttached
51 };
52});
53</script>
54```
55
56Any tests for a file should be in a file with the same name as the
57implementation file, but with a trailing `_test`.
58
benjhaydenb11ee722016-09-21 17:08:4659```sh
sullivan1355e182016-03-05 02:34:5660touch tracing/model/access_point.html
61touch tracing/model/access_point_test.html
62```
benjhaydenb11ee722016-09-21 17:08:4663
eakuefnera8a844e2017-01-06 18:24:5064### Namespacing and element names
sullivan1355e182016-03-05 02:34:5665
66All symbols that exist in the global namespace should be exported using the
67`exportTo` method.
68
69Exported package names show the file’s location relative to the root `tracing/`
70directory. These package names are abbreviated, usually with a 1 or 2 letter
71abbreviation - just enough to resolve naming conflicts. All files in the same
72directory should share the same package.
73
benjhaydenb11ee722016-09-21 17:08:4674```html
benjhayden50b8d5f2017-01-26 19:32:4375<!-- tracing/extras/chrome/cc/input_latency_async_slice.html →
76tr.exportTo(‘tr.e.cc’, function() {
sullivan1355e182016-03-05 02:34:5677 // ...
78});
79```
80
81Polymer element names should use the convention
82`hyphenated-package-name-element-name`.
83
benjhaydenb11ee722016-09-21 17:08:4684```html
sullivan1355e182016-03-05 02:34:5685<!-- tracing/ui/analysis/counter_sample_sub_view.html -->
benjhaydenb11ee722016-09-21 17:08:4686<dom-module id='tr-ui-a-counter-sample-sub-view'>
sullivan1355e182016-03-05 02:34:5687 ...
benjhaydenb11ee722016-09-21 17:08:4688</dom-module>
sullivan1355e182016-03-05 02:34:5689```
90
eakuefnera8a844e2017-01-06 18:24:5091### Classes and objects
sullivan1355e182016-03-05 02:34:5692
93Classes should expose public fields only if those fields represent a part of the
94class’s public interface.
95
96All fields should be initialized in the constructor. Fields with no reasonable
97default value should be initialized to undefined.
98
99Do not set defaults via the prototype chain.
100
benjhaydenb11ee722016-09-21 17:08:46101```javascript
sullivan1355e182016-03-05 02:34:56102function Line() {
103 // Good
104 this.yIntercept_ = undefined;
105}
106
107Line.prototype = {
108 // Bad
109 xIntercept_: undefined,
110
111
112 set slope(slope) {
113 // Bad: this.slope_ wasn’t initialized in the constructor.
114 this.slope_ = slope;
115 },
116
117 set yIntercept() {
118 // Good
119 return this.yIntercept_;
120 }
121};
122```
123
eakuefnera8a844e2017-01-06 18:24:50124### Blocks
benjhaydenb11ee722016-09-21 17:08:46125
benjhayden0fccc6c2016-09-26 17:35:19126From the [Blocks section of the airbnb style
127guide](https://github.com/airbnb/javascript#blocks):
128Use braces with all multi-line blocks.
129
130```javascript
131// bad
132if (test)
133 return false;
134
135// good
136if (test) return false;
137
138// good
139if (test) {
140 return false;
141}
142
143// bad
144function foo() { return false; }
145
146// good
147function bar() {
148 return false;
149}
150```
151
152If you're using multi-line blocks with `if` and `else`, put `else` on the same
153line as your `if` block's closing brace.
154
155```javascript
156// bad
157if (test) {
158 thing1();
159 thing2();
160}
161else {
162 thing3();
163}
164
165// good
166if (test) {
167 thing1();
168 thing2();
169} else {
170 thing3();
171}
172```
benjhaydenb11ee722016-09-21 17:08:46173
benjhayden0d592b92017-03-24 04:42:13174### Variables
175
176Use `const` and `let` instead of `var` in all new files and functions. Prefer `const` over `let` when a variable can only refer to a single value throughout its lifetime.
177
178```javascript
179// bad
180function() {
181 let hello = ' hello ';
182 return hello.trim();
183}
184
185// good
186function() {
187 const hello = ' hello ';
188 return hello.trim();
189}
190```
191
eakuefnera8a844e2017-01-06 18:24:50192### Polymer elements
sullivan1355e182016-03-05 02:34:56193The `<script>` block for the Polymer element can go either inside or outside of
194the element’s definition. Generally, the block outside is placed outside when
195the script is sufficiently complex that having 2 fewer spaces of indentation
196would make it more readable.
197
benjhaydenb11ee722016-09-21 17:08:46198```html
199<dom-module id="tr-bar">
sullivan1355e182016-03-05 02:34:56200 <template><div></div></template>
201 <script>
202 // Can go here...
203 </script>
benjhaydenb11ee722016-09-21 17:08:46204</dom-module>
sullivan1355e182016-03-05 02:34:56205
206<script>
207'use strict';
208(function(){ // Use this if you need to define constants scoped to that element.
hjda1e9f792017-04-10 16:23:10209Polymer('tr-bar', {
sullivan1355e182016-03-05 02:34:56210 // ... or here.
211});
212})();
213</script>
214```
215
216Style sheets should be inline rather than in external .css files.
217
benjhaydenb11ee722016-09-21 17:08:46218```html
219<dom-module id="tr-bar">
sullivan1355e182016-03-05 02:34:56220 <style>
221 #content {
222 display: flex;
223 }
224 </style>
225 <template><div id=”content”></div></template>
benjhaydenb11ee722016-09-21 17:08:46226</dom-module>
sullivan1355e182016-03-05 02:34:56227```
228
eakuefnera8a844e2017-01-06 18:24:50229### `undefined` and `null`
charliea1082ddd2016-03-23 17:22:40230Prefer use of `undefined` over `null`.
231
benjhaydenb11ee722016-09-21 17:08:46232```javascript
charliea1082ddd2016-03-23 17:22:40233function Line() {
234 // Good
235 this.yIntercept_ = undefined;
236 // Bad
237 this.slope = null;
238}
239```
240
eakuefnera8a844e2017-01-06 18:24:50241### Tests
sullivan1355e182016-03-05 02:34:56242UI element tests that make sure that an element is instantiable should have
243names that start with “`instantiate`”. These tests should, as a general rule,
244should not make assertions.
245
benjhayden81141992017-05-25 19:15:09246Assertions should specify the actual value before the expected value.
247
248```javascript
249assert.strictEqual(value.get(), 42);
250assert.isBelow(value.get(), 42);
251assert.isAbove(value.get(), 42);
252assert.lengthOf(value.get(), 42);
253```
254
255```python
256self.assertEqual(value.Get(), 42)
257self.assertLess(value.Get(), 42)
258```
259
eakuefnera8a844e2017-01-06 18:24:50260### ECMAScript 2015 (ES6) features
sullivan1355e182016-03-05 02:34:56261
petrcermak1ae8e1d2016-04-12 10:22:36262**Use of ES6 features is prohibited unless explicitly approved in the table below.** However, we're currently working to allow them.
sullivan1355e182016-03-05 02:34:56263
charlieab0f205e2016-03-21 20:58:50264| Feature | Status |
265|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
benjhayden2f63c682016-09-09 01:05:40266| [Arrows](https://github.com/lukehoban/es6features#arrows) | [Approved](https://github.com/catapult-project/catapult/issues/2165) |
267| [Classes](https://github.com/lukehoban/es6features#classes) | [Approved](https://github.com/catapult-project/catapult/issues/2176) |
benjhayden63e5a712016-11-09 19:06:51268| [Enhanced object literals](https://github.com/lukehoban/es6features#enhanced-object-literals) | Approved |
269| [Template strings](https://github.com/lukehoban/es6features#template-strings) | Approved |
benjhayden2f63c682016-09-09 01:05:40270| [Destructuring](https://github.com/lukehoban/es6features#destructuring) | Approved |
benshayden237fb2a2018-10-17 17:17:45271| [Default, rest, and spread](https://github.com/lukehoban/es6features#default--rest--spread) | Approved |
272| [`let` and `const`](https://github.com/lukehoban/es6features#let--const) | Approved and required for new code |
petrcermak1ae8e1d2016-04-12 10:22:36273| [Iterators and `for...of`](https://github.com/lukehoban/es6features#iterators--forof) | Approved |
charliea37ee8c72016-06-08 18:45:57274| [Generators](https://github.com/lukehoban/es6features#generators) | Approved |
charlieab0f205e2016-03-21 20:58:50275| [Unicode](https://github.com/lukehoban/es6features#unicode) | To be discussed |
276| [Modules](https://github.com/lukehoban/es6features#modules) | To be discussed |
277| [Module loaders](https://github.com/lukehoban/es6features#module-loaders) | To be discussed |
petrcermak1ae8e1d2016-04-12 10:22:36278| [`Map`, `Set`, `WeakMap`, and `WeakSet`](https://github.com/lukehoban/es6features#map--set--weakmap--weakset) | Approved |
charlieab0f205e2016-03-21 20:58:50279| [Proxies](https://github.com/lukehoban/es6features#proxies) | To be discussed |
280| [Symbols](https://github.com/lukehoban/es6features#symbols) | To be discussed |
benjhayden2f63c682016-09-09 01:05:40281| [Subclassable Built-ins](https://github.com/lukehoban/es6features#subclassable-built-ins) | Approved |
petrcermak1ae8e1d2016-04-12 10:22:36282| [Promises](https://github.com/lukehoban/es6features#promises) | Approved |
charlieab0f205e2016-03-21 20:58:50283| [`Math`, `Number`, `String`, `Array`, and `Object` APIs](https://github.com/lukehoban/es6features#math--number--string--array--object-apis) | To be discussed |
284| [Binary and octal literals](https://github.com/lukehoban/es6features#binary-and-octal-literals) | To be discussed |
285| [Reflect API](https://github.com/lukehoban/es6features#reflect-api) | To be discussed |
sullivan1355e182016-03-05 02:34:56286
eakuefnera8a844e2017-01-06 18:24:50287### ECMAScript 2016 (ES7) features
charlieae88f2af2016-11-16 00:46:59288
289**Use of ES7 features is prohibited unless explicitly approved in the table below.** However, we're currently working to allow them.
290
291| Feature | Status |
292|--------------------------|-----------------|
charliea489ef352017-03-22 16:10:02293| [Array.prototype.includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) | [Approved](https://github.com/catapult-project/catapult/issues/3424) |
charlieae88f2af2016-11-16 00:46:59294| [Exponentiation operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation_(**)) | To be discussed |
295
eakuefnera8a844e2017-01-06 18:24:50296### ECMAScript 2017 (ES8) features
charlieae88f2af2016-11-16 00:46:59297
298**Use of ES8 features is prohibited unless explicitly approved in the table below.** Generally, ES8 features are still experimental and liable to change and therefore not fit for use in Catapult. However, in a few rare cases, features may be stable enough for use.
299
300| Feature | Status |
301|--------------------------|-----------------|
charlieab38578d2016-11-30 14:52:00302| [Object.entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) and [Object.values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values) | Approved |
benjhaydeneef0bb12017-03-21 16:53:54303| [async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) | Approved |
charlieae88f2af2016-11-16 00:46:59304
charlieab0f205e2016-03-21 20:58:50305### Possible feature statuses
306 - **Approved**: this feature is approved for general use.
307 - **Testing in progress**: there's agreement that we should use this feature, but we still need to make sure that it's safe. "Testing in progress" statuses should link to a Catapult bug thread tracking the testing.
308 - **Discussion in progress**: there's not yet agreement that we should use this feature. "Discussion in progress" statuses should link to a Catapult bug thread about whether the feature should be used.
309 - **To be discussed**: this feature hasn't been discussed yet.
sullivan1355e182016-03-05 02:34:56310
petrcermak1ae8e1d2016-04-12 10:22:36311Use of an ES6 features shouldn't be considered until that feature is [supported](https://kangax.github.io/compat-table/es6/) in both Chrome stable and [our current version of D8](/third_party/vinn/third_party/v8/README.chromium).
charlieab0f205e2016-03-21 20:58:50312
313If you see that Catapult’s version of D8 is behind Chrome stable's, use
sullivan1355e182016-03-05 02:34:56314[this script](/third_party/vinn/bin/update_v8) to update it.
315
charliea90967962016-03-31 16:26:43316## Avoid defensive programming (and document it when you can't)
sullivan1355e182016-03-05 02:34:56317
charliea90967962016-03-31 16:26:43318Don't silently handle unexpected conditions. When such conditions occur, you
319should:
sullivan1355e182016-03-05 02:34:56320
charliea90967962016-03-31 16:26:43321 1. Emit a clear warning and continue if the error is non-catastrophic
322 2. Fail loudly if the error is catastrophic
323
324If fixing the problem is hard but a simple workaround is possible, then using
325the workaround is OK so long as:
326
charlieadcd2de12016-11-03 18:59:54327 1. An issue is created to track the problem.
328 2. The defensive patch is wrapped in a `// TODO` linking to that issue.
329 3. The todo and defensive patch are removed after the problem is fixed.