Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Commit 2bb8a45

Browse files
committed
Update CODING_STYLE
1 parent 848b0b8 commit 2bb8a45

File tree

3 files changed

+204
-204
lines changed

3 files changed

+204
-204
lines changed

CODING_STYLE.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# C++ Ethereum Coding Style
2+
3+
## Code Formatting
4+
5+
Use clang-format tool to format your changes, see [CONTRIBUTING](CONTRIBUTING.md) for details.
6+
7+
8+
## Namespaces
9+
10+
1. No "using namespace" declarations in header files.
11+
2. All symbols should be declared in a namespace except for final applications.
12+
3. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
13+
14+
// WRONG:
15+
#include <cassert>
16+
using namespace std;
17+
tuple<float, float> meanAndSigma(vector<float> const& _v);
18+
19+
// CORRECT:
20+
#include <cassert>
21+
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
22+
23+
24+
## Preprocessor
25+
26+
1. File comment is always at top, and includes:
27+
- Copyright.
28+
- License.
29+
30+
2. Never use #ifdef/#define/#endif file guards. Prefer #pragma once as first line below file comment.
31+
3. Prefer static const variable to value macros.
32+
4. Prefer inline constexpr functions to function macros.
33+
34+
35+
## Capitalization
36+
37+
GOLDEN RULE: Preprocessor: ALL_CAPS; C++: camelCase.
38+
39+
1. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions.
40+
2. The following entities' first alpha is upper case:
41+
- Type names.
42+
- Template parameters.
43+
- Enum members.
44+
- static const variables that form an external API.
45+
3. All preprocessor symbols (macros, macro arguments) in full uppercase with underscore word separation.
46+
47+
48+
All other entities' first alpha is lower case.
49+
50+
51+
## Variable prefixes
52+
53+
1. Leading underscore `_` to parameter names.
54+
- Exception: `o_parameterName` when it is used exclusively for output.
55+
See also Declarations.6.
56+
- Exception: `io_parameterName` when it is used for both input and output.
57+
See also Declarations.6.
58+
2. Leading `c_` to const variables (unless part of an external API).
59+
3. Leading `g_` to global (non-const) variables.
60+
4. Leading `s_` to static (non-const, non-global) variables.
61+
62+
63+
64+
## Error reporting
65+
66+
Prefer exception to bool/int return type.
67+
68+
69+
## Declarations
70+
71+
1. {Typename} + {qualifiers} + {name}. (**TODO**: Against [NL.26](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#nl26-use-conventional-const-notation))
72+
2. Only one per line.
73+
3. Favour declarations close to use; don't habitually declare at top of scope ala C.
74+
4. Always pass non-trivial parameters with a const& suffix.
75+
5. To return multiple "out" values, prefer returning a tuple or struct.
76+
See [F.21].
77+
6. Never use a macro where adequate non-preprocessor C++ can be written.
78+
7. Make use of auto whenever type is clear or unimportant:
79+
- Always avoid doubly-stating the type.
80+
- Use to avoid vast and unimportant type declarations.
81+
- However, avoid using auto where type is not immediately obvious from the context, and especially not for arithmetic expressions.
82+
8. Don't pass bools: prefer enumerations instead.
83+
9. Prefer enum class to straight enum.
84+
85+
// WRONG:
86+
const double d = 0;
87+
int i, j;
88+
char *s;
89+
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
90+
Derived* x(dynamic_cast<Derived*>(base));
91+
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
92+
93+
// CORRECT:
94+
enum class Accuracy
95+
{
96+
Approximate,
97+
Exact
98+
};
99+
double const d = 0;
100+
int i;
101+
int j;
102+
char* s;
103+
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v, Accuracy _a);
104+
auto x = dynamic_cast<Derived*>(base);
105+
for (auto i = x.begin(); i != x.end(); ++i) {}
106+
107+
108+
## Structs & classes
109+
110+
1. Structs to be used when all members public and no virtual functions.
111+
- In this case, members should be named naturally and not prefixed with 'm_'
112+
2. Classes to be used in all other circumstances.
113+
114+
115+
116+
## Members
117+
118+
1. One member per line only.
119+
2. Private, non-static, non-const fields prefixed with m_.
120+
3. Avoid public fields, except in structs.
121+
4. Use override, final and const as much as possible.
122+
5. No implementations with the class declaration, except:
123+
- template or force-inline method (though prefer implementation at bottom of header file).
124+
- one-line implementation (in which case include it in same line as declaration).
125+
6. For a property 'foo'
126+
- Member: m_foo;
127+
- Getter: foo(); also: for booleans, isFoo()
128+
- Setter: setFoo();
129+
130+
131+
## Naming
132+
133+
1. Collection conventions:
134+
- ~s means `std::vector` e.g. `using MyTypes = std::vector<MyType>`
135+
- ~Set means `std::set` e.g. `using MyTypeSet = std::set<MyType>`
136+
- ~Hash means `std::unordered_set` e.g. `using MyTypeHash = std::unordered_set<MyType>`
137+
2. Class conventions:
138+
- ~Face means the interface of some shared concept. (e.g. FooFace might be a pure virtual class.)
139+
3. Avoid unpronounceable names:
140+
- If you need to shorten a name favour a pronouncable slice of the original to a scattered set of consonants.
141+
- e.g. Manager shortens to Man rather than Mgr.
142+
4. Avoid prefixes of initials (e.g. DON'T use IMyInterface, CMyImplementation)
143+
5. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
144+
- A dictionary and thesaurus are your friends.
145+
- Spell correctly.
146+
- Think carefully about the class's purpose.
147+
- Imagine it as an isolated component to try to decontextualise it when considering its name.
148+
- Don't be trapped into naming it (purely) in terms of its implementation.
149+
150+
151+
152+
## Type-definitions
153+
154+
1. Prefer `using` to `typedef`. E.g. `using ints = std::vector<int>` rather than
155+
`typedef std::vector<int> ints`.
156+
2. Generally avoid shortening a standard form that already includes all important information:
157+
- e.g. stick to `shared_ptr<X>` rather than shortening to `ptr<X>`.
158+
3. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently.
159+
- e.g. `using Guard = std::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it's clear in meaning and used commonly.`
160+
4. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
161+
162+
163+
164+
## Commenting
165+
166+
1. Comments should be doxygen-compilable, using @notation rather than \notation.
167+
2. Document the interface, not the implementation.
168+
- Documentation should be able to remain completely unchanged, even if the method is reimplemented.
169+
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports).
170+
- Be careful to scrutinise documentation that extends only to intended purpose and usage.
171+
- Reject documentation that is simply an English transaction of the implementation.
172+
173+
174+
175+
## Logging
176+
177+
Logging should be performed at appropriate verbosities depending on the logging message.
178+
The more likely a message is to repeat (and thus cause noise) the higher in verbosity it should be.
179+
Some rules to keep in mind:
180+
181+
- Verbosity == 0 -> Reserved for important stuff that users must see and can understand.
182+
- Verbosity == 1 -> Reserved for stuff that users don't need to see but can understand.
183+
- Verbosity >= 2 -> Anything that is or might be displayed more than once every minute
184+
- Verbosity >= 3 -> Anything that only a developer would understand
185+
- Verbosity >= 4 -> Anything that is low-level (e.g. peer disconnects, timers being cancelled)
186+
187+
188+
## Recommended reading
189+
190+
Herb Sutter and Bjarne Stroustrup
191+
- "C++ Core Guidelines" (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
192+
193+
Herb Sutter and Andrei Alexandrescu
194+
- "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices"
195+
196+
Scott Meyers
197+
- "Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)"
198+
- "More Effective C++: 35 New Ways to Improve Your Programs and Designs"
199+
- "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14"
200+
201+
202+
[F.21]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f21-to-return-multiple-out-values-prefer-returning-a-tuple-or-struct

0 commit comments

Comments
 (0)