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