mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Update CODING_STYLE.md
This commit is contained in:
parent
6055bc250f
commit
f56afa21c4
138
CODING_STYLE.md
138
CODING_STYLE.md
@ -3,20 +3,22 @@
|
||||
GOLDEN RULE: Follow the style of the existing code when you make changes.
|
||||
|
||||
a. Use tabs for leading indentation
|
||||
- tab stops are every 4 characters.
|
||||
- tab stops are every 4 characters (only relevant for line length).
|
||||
- One indentation level -> exactly one byte (i.e. a tab character) in the source file.
|
||||
- If you have run-on lines, indent as you would for a block.
|
||||
b. Line widths:
|
||||
- Don't worry about having lines of code > 80-char wide.
|
||||
- Lines should be at most 99 characters wide to make diff views readable and reduce merge conflicts.
|
||||
- Lines of comments should be formatted according to ease of viewing, but simplicity is to be preferred over beauty.
|
||||
c. Don't use braces for condition-body one-liners.
|
||||
c. Single-statement blocks should not have braces, unless required for clarity.
|
||||
d. Never place condition bodies on same line as condition.
|
||||
e. Space between first paren and keyword, but *not* following first paren or preceding final paren.
|
||||
f. No spaces when fewer than intra-expression three parens together; when three or more, space according to clarity.
|
||||
g. No spaces for subscripting or unary operators.
|
||||
h. No space before ':' but one after it, except in the ternary operator: one on both sides.
|
||||
i. Space all other operators.
|
||||
j. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
|
||||
e. Space between keyword and opening parenthesis, but not following opening parenthesis or before final parenthesis.
|
||||
f. No spaces for unary operators, `->` or `.`.
|
||||
g. No space before ':' but one after it, except in the ternary operator: one on both sides.
|
||||
h. Add spaces around all other operators.
|
||||
i. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
|
||||
j. If lines are broken, a list of elements enclosed with parentheses (of any kind) and separated by a
|
||||
separator (of any kind) are formatted such that there is exactly one element per line, followed by
|
||||
the separator, the opening parenthesis is on the first line, followed by a line break and the closing
|
||||
parenthesis is on a line of its own (unindented). See example below.
|
||||
|
||||
(WRONG)
|
||||
if( a==b[ i ] ) { printf ("Hello\n"); }
|
||||
@ -25,6 +27,7 @@ foo->bar(someLongVariableName,
|
||||
anotherLongVariableName,
|
||||
anotherLongVariableName,
|
||||
anotherLongVariableName);
|
||||
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;
|
||||
|
||||
(RIGHT)
|
||||
if (a == b[i])
|
||||
@ -36,6 +39,11 @@ foo->bar(
|
||||
anotherLongVariableName,
|
||||
anotherLongVariableName
|
||||
);
|
||||
cout <<
|
||||
"some very long string that contains completely irrelevant " <<
|
||||
"text that talks about this and that and contains the words " <<
|
||||
"\"lorem\" and \"ipsum\"" <<
|
||||
endl;
|
||||
|
||||
|
||||
|
||||
@ -43,7 +51,8 @@ foo->bar(
|
||||
|
||||
a. No "using namespace" declarations in header files.
|
||||
b. All symbols should be declared in a namespace except for final applications.
|
||||
c. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
|
||||
c. Use anonymous namespaces for helpers whose scope is a cpp file only.
|
||||
d. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
|
||||
|
||||
(WRONG)
|
||||
#include <cassert>
|
||||
@ -90,16 +99,16 @@ All other entities' first alpha is lower case.
|
||||
a. Leading underscore "_" to parameter names.
|
||||
- Exception: "o_parameterName" when it is used exclusively for output. See 6(f).
|
||||
- Exception: "io_parameterName" when it is used for both input and output. See 6(f).
|
||||
b. Leading "c_" to const variables (unless part of an external API).
|
||||
c. Leading "g_" to global (non-const) variables.
|
||||
d. Leading "s_" to static (non-const, non-global) variables.
|
||||
b. Leading "g_" to global (non-const) variables.
|
||||
c. Leading "s_" to static (non-const, non-global) variables.
|
||||
|
||||
|
||||
|
||||
5. Error reporting:
|
||||
|
||||
- Prefer exception to bool/int return type.
|
||||
5. Assertions:
|
||||
|
||||
- use `solAssert` and `solUnimplementedAssert` generously to check assumptions
|
||||
that span across different parts of the code base, for example before dereferencing
|
||||
a pointer.
|
||||
|
||||
|
||||
6. Declarations:
|
||||
@ -108,15 +117,14 @@ a. {Typename} + {qualifiers} + {name}.
|
||||
b. Only one per line.
|
||||
c. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)).
|
||||
d. Favour declarations close to use; don't habitually declare at top of scope ala C.
|
||||
e. Always pass non-trivial parameters with a const& suffix.
|
||||
f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
|
||||
g. Never use a macro where adequate non-preprocessor C++ can be written.
|
||||
h. Make use of auto whenever type is clear or unimportant:
|
||||
- Always avoid doubly-stating the type.
|
||||
- Use to avoid vast and unimportant type declarations.
|
||||
- However, avoid using auto where type is not immediately obvious from the context, and especially not for arithmetic expressions.
|
||||
i. Don't pass bools: prefer enumerations instead.
|
||||
j. Prefer enum class to straight enum.
|
||||
e. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move.
|
||||
f. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments.
|
||||
g. Use parameters of pointer type only if ``nullptr`` is a valid argument, use references otherwise. Often, ``boost::optional`` is better suited than a raw pointer.
|
||||
h. Never use a macro where adequate non-preprocessor C++ can be written.
|
||||
i. Only use ``auto`` if the type is very long and rather irrelevant.
|
||||
j. Do not pass bools: prefer enumerations instead.
|
||||
k. Prefer enum class to straight enum.
|
||||
l. Always initialize POD variables, even if their value is overwritten later.
|
||||
|
||||
|
||||
(WRONG)
|
||||
@ -134,13 +142,18 @@ enum class Accuracy
|
||||
Approximate,
|
||||
Exact
|
||||
};
|
||||
struct MeanSigma
|
||||
{
|
||||
float mean;
|
||||
float standardDeviation;
|
||||
};
|
||||
double const d = 0;
|
||||
int i;
|
||||
int j;
|
||||
char* s;
|
||||
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v, Accuracy _a);
|
||||
auto x = dynamic_cast<Derived*>(base);
|
||||
for (auto i = x.begin(); i != x.end(); ++i) {}
|
||||
MeanAndSigma ms meanAndSigma(std::vector<float> const& _v, Accuracy _a);
|
||||
Derived* x = dynamic_cast<Derived*>(base);
|
||||
for (auto i = x->begin(); i != x->end(); ++i) {}
|
||||
|
||||
|
||||
7. Structs & classes
|
||||
@ -169,17 +182,10 @@ f. For a property 'foo'
|
||||
|
||||
9. Naming
|
||||
|
||||
a. Collection conventions:
|
||||
- -s means std::vector e.g. using MyTypes = std::vector<MyType>
|
||||
- -Set means std::set e.g. using MyTypeSet = std::set<MyType>
|
||||
- -Hash means std::unordered_set e.g. using MyTypeHash = std::unordered_set<MyType>
|
||||
b. Class conventions:
|
||||
- -Face means the interface of some shared concept. (e.g. FooFace might be a pure virtual class.)
|
||||
c. Avoid unpronouncable names;
|
||||
- If you need to shorten a name favour a pronouncable slice of the original to a scattered set of consonants.
|
||||
- e.g. Manager shortens to Man rather than Mgr.
|
||||
d. Avoid prefixes of initials (e.g. DON'T use IMyInterface, CMyImplementation)
|
||||
e. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
|
||||
a. Avoid unpronouncable names
|
||||
b. Names should be shortened only if they are extremely common, but shortening should be generally avoided
|
||||
c. Avoid prefixes of initials (e.g. do not use IMyInterface, CMyImplementation)
|
||||
c. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
|
||||
- A dictionary and thesaurus are your friends.
|
||||
- Spell correctly.
|
||||
- Think carefully about the class's purpose.
|
||||
@ -194,8 +200,9 @@ a. Prefer 'using' to 'typedef'. e.g. using ints = std::vector<int>; rather than
|
||||
b. Generally avoid shortening a standard form that already includes all important information:
|
||||
- e.g. stick to shared_ptr<X> rather than shortening to ptr<X>.
|
||||
c. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently.
|
||||
- e.g. using Guard = std::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it's clear in meaning and used commonly.
|
||||
- e.g. using Guard = std::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it is clear in meaning and used commonly.
|
||||
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
|
||||
e. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time.
|
||||
|
||||
|
||||
|
||||
@ -207,40 +214,41 @@ b. Document the interface, not the implementation.
|
||||
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports).
|
||||
- Be careful to scrutinise documentation that extends only to intended purpose and usage.
|
||||
- Reject documentation that is simply an English transaction of the implementation.
|
||||
|
||||
c. Avoid in-code comments. Instead, try to extract blocks of functionality into functions. This often already eliminates the need for an in-code comment.
|
||||
|
||||
|
||||
12. Include Headers
|
||||
|
||||
Includes should go in increasing order of generality (libethereum -> libethcore -> libdevcrypto -> libdevcore -> boost -> STL). For example:
|
||||
Includes should go in increasing order of generality (libsolidity -> libevmasm -> libdevcore -> boost -> STL).
|
||||
The corresponding .h file should be the first include in the respective .cpp file.
|
||||
Insert empty lines between blocks of include files.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#include <libsolidity/codegen/ExpressionCompiler.h>
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/codegen/CompilerContext.h>
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/codegen/LValue.h>
|
||||
|
||||
#include <libevmasm/GasMeter.h>
|
||||
|
||||
#include <libethereum/Defaults.h>
|
||||
#include <libdevcrypto/SHA3.h>
|
||||
#include <libdevcore/Log.h>
|
||||
#include <libdevcore/Exceptions.h>
|
||||
#include <libdevcore/CommonData.h>
|
||||
#include <libdevcore/Common.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <string>
|
||||
#include <libdevcore/SHA3.h>
|
||||
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
```
|
||||
|
||||
See http://stackoverflow.com/questions/614302/c-header-order/614333#614333 for the reason: this makes it easier to find missing includes in header files.
|
||||
|
||||
|
||||
|
||||
13. Logging
|
||||
|
||||
Logging should be performed at appropriate verbosities depending on the logging message.
|
||||
The more likely a message is to repeat (and thus cause noise) the higher in verbosity it should be.
|
||||
Some rules to keep in mind:
|
||||
|
||||
- Verbosity == 0 -> Reserved for important stuff that users must see and can understand.
|
||||
- Verbosity == 1 -> Reserved for stuff that users don't need to see but can understand.
|
||||
- Verbosity >= 2 -> Anything that is or might be displayed more than once every minute
|
||||
- Verbosity >= 3 -> Anything that only a developer would understand
|
||||
- Verbosity >= 4 -> Anything that is low-level (e.g. peer disconnects, timers being cancelled)
|
||||
|
||||
|
||||
14. Recommended reading
|
||||
13. Recommended reading
|
||||
|
||||
Herb Sutter and Bjarne Stroustrup
|
||||
- "C++ Core Guidelines" (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
|
||||
|
Loading…
Reference in New Issue
Block a user