forked from phacility/phabricator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneral_coding_standards.diviner
147 lines (111 loc) · 5.17 KB
/
general_coding_standards.diviner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
@title General Coding Standards
@group standards
This document is a general coding standard for contributing to Phabricator,
Arcanist, libphutil and Diviner.
= Overview =
This document contains practices and guidelines which apply across languages.
Contributors should follow these guidelines. These guidelines are not
hard-and-fast but should be followed unless there is a compelling reason to
deviate from them.
= Code Complexity =
- Prefer to write simple code which is easy to understand. The simplest code
is not necessarily the smallest, and some changes which make code larger
(such as decomposing complex expressions and choosing more descriptive
names) may also make it simpler. Be willing to make size tradeoffs in favor
of simplicity.
- Prefer simple methods and functions which take a small number of parameters.
Avoid methods and functions which are long and complex, or take an
innumerable host of parameters. When possible, decompose monolithic, complex
methods into several focused, simpler ones.
- Avoid putting many ideas on a single line of code.
For example, avoid this kind of code:
COUNTEREXAMPLE
$category_map = array_combine(
$dates,
array_map(create_function('$z', 'return date("F Y", $z);'), $dates));
Expressing this complex transformation more simply produces more readable code:
$category_map = array();
foreach ($dates as $date) {
$category_map[$date] = date('F Y', $date);
}
And, obviously, don't do this sort of thing:
COUNTEREXAMPLE
if ($val = $some->complicatedConstruct() && !!~blarg_blarg_blarg() & $flags
? HOPE_YOU_MEMORIZED == $all_the_lexical_binding_powers : <<<'Q'
${hahaha}
Q
);
= Performance =
- Prefer to write efficient code.
- Strongly prefer to drive optimization decisions with hard data. Avoid
optimizing based on intuition or rumor if you can not support it with
concrete measurements.
- Prefer to optimize code which is slow and runs often. Optimizing code which
is fast and runs rarely is usually a waste of time, and can even be harmful
if it makes that code more difficult to understand or maintain. You can
determine if code is fast or slow by measuring it.
- Reject performance discussions that aren't rooted in concrete data.
In Phabricator, you can usually use the builtin XHProf profiling to quickly
gather concrete performance data.
= Naming Things =
- Follow language-specific conventions.
- Name things unambiguously.
- Choose descriptive names.
- Avoid nonstandard abbreviations (common abbreviations like ID, URI and HTTP are fine).
- Spell words correctly.
- Use correct grammar.
For example, avoid these sorts of naming choices:
COUNTEREXAMPLE
$PIE->GET_FLAVOR(); // Unconventional.
$thing->doStuff(); // Ambiguous.
$list->empty(); // Ambiguous -- is it isEmpty() or makeEmpty()?
$e = 3; // Not descriptive.
$this->updtHndlr(); // Nonstandard abbreviation.
$this->chackSpulls(); // Misspelling, ungrammatical.
Prefer these:
$pie->getFlavor(); // Conventional.
$pie->bake(); // Unambiguous.
$list->isEmpty(); // Unambiguous.
$list->makeEmpty(); // Unambiguous.
$edge_count = 3; // Descriptive.
$this->updateHandler(); // No nonstandard abbreviations.
$this->getID(); // Standard abbreviation.
$this->checkSpelling(); // Correct spelling and grammar.
= Error Handling =
- Strongly prefer to detect errors.
- Strongly prefer to fail fast and loudly. The maximum cost of script
termination is known, bounded, and fairly small. The maximum cost of
continuing script execution when errors have occurred is unknown and
unbounded. This also makes APIs much easier to use and problems far easier
to debug.
When you ignore errors, defer error handling, or degrade the severity of errors
by treating them as warnings and then dismissing them, you risk dangerous
behavior which may be difficult to troubleshoot:
COUNTEREXAMPLE
exec('echo '.$data.' > file.bak'); // Bad!
do_something_dangerous();
exec('echo '.$data.' > file.bak', $out, $err); // Also bad!
if ($err) {
debug_rlog("Unable to copy file!");
}
do_something_dangerous();
Instead, fail loudly:
exec('echo '.$data.' > file.bak', $out, $err); // Better
if ($err) {
throw new Exception("Unable to copy file!");
}
do_something_dangerous();
But the best approach is to use or write an API which simplifies condition
handling and makes it easier to get right than wrong:
execx('echo %s > file.bak', $data); // Good
do_something_dangerous();
Filesystem::writeFile('file.bak', $data); // Best
do_something_dangerous();
See @{article@libphutil:Command Execution} for details on the APIs used in this
example.
= Documentation, Comments and Formatting =
- Prefer to remove code by deleting it over removing it by commenting it out.
It shall live forever in source control, and can be retrieved therefrom if
it is ever again called upon.
- In source code, use only ASCII printable characters plus space and linefeed.
Do not use UTF-8 or other multibyte encodings.