2018-08-10 14:44:49 +00:00
# How to Write C++ Code
2017-12-28 15:13:23 +00:00
2018-08-10 14:44:49 +00:00
## General Recommendations
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**1.** The following are recommendations, not requirements.
**2.** If you are editing code, it makes sense to follow the formatting of the existing code.
**3.** Code style is needed for consistency. Consistency makes it easier to read the code, and it also makes it easier to search the code.
**4.** Many of the rules do not have logical reasons; they are dictated by established practices.
2017-12-28 15:13:23 +00:00
## Formatting
2018-04-23 22:16:40 +00:00
**1.** Most of the formatting will be done automatically by `clang-format` .
2017-12-28 15:13:23 +00:00
2018-04-28 07:58:16 +00:00
**2.** Indents are 4 spaces. Configure your development environment so that a tab adds four spaces.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**3.** Opening and closing curly brackets must be on a separate line.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
inline void readBoolText(bool & x, ReadBuffer & buf)
{
char tmp = '0';
readChar(tmp, buf);
x = tmp != '0';
}
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**4.** If the entire function body is a single `statement` , it can be placed on a single line. Place spaces around curly braces (besides the space at the end of the line).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
inline size_t mask() const { return buf_size() - 1; }
inline size_t place(HashValue x) const { return x & mask(); }
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**5.** For functions. Don't put spaces around brackets.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
void reinsert(const Value & x)
2018-09-04 11:18:59 +00:00
```
```cpp
2018-04-23 22:16:40 +00:00
memcpy(& buf[place_value], & x, sizeof(x));
```
2017-12-28 15:13:23 +00:00
2018-12-25 15:25:43 +00:00
**6.** In `if` , `for` , `while` and other expressions, a space is inserted in front of the opening bracket (as opposed to function calls).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```cpp
for (size_t i = 0; i < rows ; i + = storage . index_granularity )
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**7.** Add spaces around binary operators (`+`, `-` , `*` , `/` , `%` , ...) and the ternary operator `?:` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
UInt16 year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
UInt8 month = (s[5] - '0') * 10 + (s[6] - '0');
UInt8 day = (s[8] - '0') * 10 + (s[9] - '0');
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**8.** If a line feed is entered, put the operator on a new line and increase the indent before it.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
if (elapsed_ns)
message < < " ("
2018-09-04 11:18:59 +00:00
< < rows_read_on_server * 1000000000 / elapsed_ns < < " rows / s . , "
2018-04-23 22:16:40 +00:00
< < bytes_read_on_server * 1000 . 0 / elapsed_ns < < " MB / s . ) " ;
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**9.** You can use spaces for alignment within a line, if desired.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
dst.ClickLogID = click.LogID;
dst.ClickEventID = click.EventID;
dst.ClickGoodEvent = click.GoodEvent;
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**10.** Don't use spaces around the operators `.` , `->` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
If necessary, the operator can be wrapped to the next line. In this case, the offset in front of it is increased.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**11.** Do not use a space to separate unary operators (`--`, `++` , `*` , `&` , ...) from the argument.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**12.** Put a space after a comma, but not before it. The same rule goes for a semicolon inside a `for` expression.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**13.** Do not use spaces to separate the `[]` operator.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**14.** In a `template <...>` expression, use a space between `template` and `<` ; no spaces after `<` or before `>` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
template < typename TKey , typename TValue >
struct AggregatedStatElement
{}
```
2017-12-28 15:13:23 +00:00
2018-12-25 15:25:43 +00:00
**15.** In classes and structures, write `public` , `private` , and `protected` on the same level as `class/struct` , and indent the rest of the code.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
template < typename T >
class MultiVersion
{
public:
/// Version of object for usage. shared_ptr manage lifetime of version.
using Version = std::shared_ptr< const T > ;
...
}
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**16.** If the same `namespace` is used for the entire file, and there isn't anything else significant, an offset is not necessary inside `namespace` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**17.** If the block for an `if` , `for` , `while` , or other expression consists of a single `statement` , the curly brackets are optional. Place the `statement` on a separate line, instead. This rule is also valid for nested `if` , `for` , `while` , ...
But if the inner `statement` contains curly brackets or `else` , the external block should be written in curly brackets.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
/// Finish write.
for (auto & stream : streams)
stream.second->finalize();
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**18.** There shouldn't be any spaces at the ends of lines.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**19.** Source files are UTF-8 encoded.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**20.** Non-ASCII characters can be used in string literals.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
< < ", " < < (timer.elapsed() / chunks_stats.hits) < < " μsec/hit.";
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**21** Do not write multiple expressions in a single line.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**22.** Group sections of code inside functions and separate them with no more than one empty line.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**23.** Separate functions, classes, and so on with one or two empty lines.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**24.** `A const` (related to a value) must be written before the type name.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
//correct
const char * pos
const std::string & s
//incorrect
char const * pos
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**25.** When declaring a pointer or reference, the `*` and `&` symbols should be separated by spaces on both sides.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
//correct
const char * pos
//incorrect
const char* pos
const char *pos
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**26.** When using template types, alias them with the `using` keyword (except in the simplest cases).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
In other words, the template parameters are specified only in `using` and aren't repeated in the code.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
`using` can be declared locally, such as inside a function.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
//correct
using FileStreams = std::map< std::string , std::shared_ptr < Stream > >;
FileStreams streams;
//incorrect
std::map< std::string , std::shared_ptr < Stream > > streams;
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**27.** Do not declare several variables of different types in one statement.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
//incorrect
int x, *y;
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**28.** Do not use C-style casts.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
//incorrect
std::cerr < < (int)c < < ; std::endl;
//correct
std::cerr < < static_cast < int > (c) < < std::endl ;
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**29.** In classes and structs, group members and functions separately inside each visibility scope.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**30.** For small classes and structs, it is not necessary to separate the method declaration from the implementation.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
The same is true for small methods in any classes or structs.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
For templated classes and structs, don't separate the method declarations from the implementation (because otherwise they must be defined in the same translation unit).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**31.** You can wrap lines at 140 characters, instead of 80.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**32.** Always use the prefix increment/decrement operators if postfix is not required.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
for (Names::const_iterator it = column_names.begin(); it != column_names.end(); ++it)
```
2017-12-28 15:13:23 +00:00
## Comments
2018-04-23 22:16:40 +00:00
**1.** Be sure to add comments for all non-trivial parts of code.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
This is very important. Writing the comment might help you realize that the code isn't necessary, or that it is designed wrong.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
/** Part of piece of memory, that can be used.
* For example, if internal_buffer is 1MB, and there was only 10 bytes loaded to buffer from file for reading,
* then working_buffer will have size of only 10 bytes
2018-09-04 11:18:59 +00:00
* (working_buffer.end() will point to position right after those 10 bytes available for read).
*/
2018-04-23 22:16:40 +00:00
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**2.** Comments can be as detailed as necessary.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**3.** Place comments before the code they describe. In rare cases, comments can come after the code, on the same line.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
/** Parses and executes the query.
*/
void executeQuery(
ReadBuffer & istr, /// Where to read the query from (and data for INSERT, if applicable)
WriteBuffer & ostr, /// Where to write the result
Context & context, /// DB, tables, data types, engines, functions, aggregate functions...
2018-09-04 11:18:59 +00:00
BlockInputStreamPtr & query_plan, /// Here could be written the description on how query was executed
QueryProcessingStage::Enum stage = QueryProcessingStage::Complete /// Up to which stage process the SELECT query
2018-04-23 22:16:40 +00:00
)
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**4.** Comments should be written in English only.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**5.** If you are writing a library, include detailed comments explaining it in the main header file.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**6.** Do not add comments that do not provide additional information. In particular, do not leave empty comments like this:
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
/*
* Procedure Name:
* Original procedure name:
* Author:
* Date of creation:
* Dates of modification:
* Modification authors:
* Original file name:
* Purpose:
* Intent:
* Designation:
* Classes used:
* Constants:
* Local variables:
* Parameters:
* Date of creation:
* Purpose:
*/
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
The example is borrowed from the resource [http://home.tamk.fi/~jaalto/course/coding-style/doc/unmaintainable-code/ ](http://home.tamk.fi/~jaalto/course/coding-style/doc/unmaintainable-code/ ).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**7.** Do not write garbage comments (author, creation date ..) at the beginning of each file.
2017-12-28 15:13:23 +00:00
2018-12-25 15:25:43 +00:00
**8.** Single-line comments begin with three slashes: `///` and multi-line comments begin with `/**` . These comments are considered "documentation".
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Note: You can use Doxygen to generate documentation from these comments. But Doxygen is not generally used because it is more convenient to navigate the code in the IDE.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**9.** Multi-line comments must not have empty lines at the beginning and end (except the line that closes a multi-line comment).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**10.** For commenting out code, use basic comments, not “documenting” comments.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**11.** Delete the commented out parts of the code before committing.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**12.** Do not use profanity in comments or code.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**13.** Do not use uppercase letters. Do not use excessive punctuation.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
/// WHAT THE FAIL???
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**14.** Do not use comments to make delimeters.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```cpp
2018-04-23 22:16:40 +00:00
///******************************************************
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**15.** Do not start discussions in comments.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```cpp
2018-04-23 22:16:40 +00:00
/// Why did you do this stuff?
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**16.** There's no need to write a comment at the end of a block describing what it was about.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```cpp
2018-04-23 22:16:40 +00:00
/// for
```
2017-12-28 15:13:23 +00:00
## Names
2018-12-25 15:25:43 +00:00
**1.** Use lowercase letters with underscores in the names of variables and class members.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
size_t max_block_size;
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**2.** For the names of functions (methods), use camelCase beginning with a lowercase letter.
2017-12-28 15:13:23 +00:00
2019-05-17 00:12:19 +00:00
```cpp
std::string getName() const override { return "Memory"; }
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**3.** For the names of classes (structs), use CamelCase beginning with an uppercase letter. Prefixes other than I are not used for interfaces.
2017-12-28 15:13:23 +00:00
2019-05-17 00:12:19 +00:00
```cpp
class StorageMemory : public IStorage
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**4.** `using` are named the same way as classes, or with `_t` on the end.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**5.** Names of template type arguments: in simple cases, use `T` ; `T` , `U` ; `T1` , `T2` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
For more complex cases, either follow the rules for class names, or add the prefix `T` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
template < typename TKey , typename TValue >
struct AggregatedStatElement
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**6.** Names of template constant arguments: either follow the rules for variable names, or use `N` in simple cases.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
template < bool without_www >
struct ExtractDomain
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**7.** For abstract classes (interfaces) you can add the `I` prefix.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
class IBlockInputStream
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**8.** If you use a variable locally, you can use the short name.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In all other cases, use a name that describes the meaning.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
bool info_successfully_loaded = false;
```
2017-12-28 15:13:23 +00:00
2018-12-25 15:25:43 +00:00
**9.** Names of `define` s and global constants use ALL_CAPS with underscores.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
#define MAX_SRC_TABLE_NAMES_TO_STORE 1000
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**10.** File names should use the same style as their contents.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If a file contains a single class, name the file the same way as the class (CamelCase).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If the file contains a single function, name the file the same way as the function (camelCase).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**11.** If the name contains an abbreviation, then:
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
- For variable names, the abbreviation should use lowercase letters `mysql_connection` (not `mySQL_connection` ).
2018-09-04 11:18:59 +00:00
- For names of classes and functions, keep the uppercase letters in the abbreviation`MySQLConnection` (not `MySqlConnection` ).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**12.** Constructor arguments that are used just to initialize the class members should be named the same way as the class members, but with an underscore at the end.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
FileQueueProcessor(
const std::string & path_,
const std::string & prefix_,
std::shared_ptr< FileHandler > handler_)
: path(path_),
prefix(prefix_),
handler(handler_),
log(& Logger::get("FileQueueProcessor"))
{
}
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
The underscore suffix can be omitted if the argument is not used in the constructor body.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**13.** There is no difference in the names of local variables and class members (no prefixes required).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
timer (not m_timer)
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**14.** For the constants in an `enum` , use CamelCase with a capital letter. ALL_CAPS is also acceptable. If the `enum` is non-local, use an `enum class` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
enum class CompressionMethod
{
QuickLZ = 0,
LZ4 = 1,
};
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**15.** All names must be in English. Transliteration of Russian words is not allowed.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```
2018-04-23 22:16:40 +00:00
not Stroka
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**16.** Abbreviations are acceptable if they are well known (when you can easily find the meaning of the abbreviation in Wikipedia or in a search engine).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```
`AST` , `SQL` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Not `NVDH` (some random letters)
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Incomplete words are acceptable if the shortened version is common use.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
You can also use an abbreviation if the full name is included next to it in the comments.
**17.** File names with C++ source code must have the `.cpp` extension. Header files must have the `.h` extension.
2017-12-28 15:13:23 +00:00
2018-08-10 14:44:49 +00:00
## How to Write Code
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**1.** Memory management.
2018-09-04 11:18:59 +00:00
Manual memory deallocation (`delete`) can only be used in library code.
2018-04-23 22:16:40 +00:00
2018-09-04 11:18:59 +00:00
In library code, the `delete` operator can only be used in destructors.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
In application code, memory must be freed by the object that owns it.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Examples:
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
- The easiest way is to place an object on the stack, or make it a member of another class.
- For a large number of small objects, use containers.
2018-09-04 11:18:59 +00:00
- For automatic deallocation of a small number of objects that reside in the heap, use `shared_ptr/unique_ptr` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**2.** Resource management.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Use `RAII` and see above.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**3.** Error handling.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Use exceptions. In most cases, you only need to throw an exception, and don't need to catch it (because of `RAII` ).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
In offline data processing applications, it's often acceptable to not catch exceptions.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
In servers that handle user requests, it's usually enough to catch exceptions at the top level of the connection handler.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In thread functions, you should catch and keep all exceptions to rethrow them in the main thread after `join` .
2018-04-23 22:16:40 +00:00
```cpp
2018-09-04 11:18:59 +00:00
/// If there weren't any calculations yet, calculate the first block synchronously
2018-04-23 22:16:40 +00:00
if (!started)
{
calculate();
started = true;
}
2018-09-04 11:18:59 +00:00
else /// If calculations are already in progress, wait for the result
2018-04-23 22:16:40 +00:00
pool.wait();
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
if (exception)
exception->rethrow();
```
2018-09-04 11:18:59 +00:00
2018-04-23 22:16:40 +00:00
Never hide exceptions without handling. Never just blindly put all exceptions to log.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```cpp
//Not correct
catch (...) {}
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
If you need to ignore some exceptions, do so only for specific ones and rethrow the rest.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
catch (const DB::Exception & e)
{
if (e.code() == ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION)
return nullptr;
else
throw;
}
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
When using functions with response codes or `errno` , always check the result and throw an exception in case of error.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
if (0 != close(fd))
throwFromErrno("Cannot close file " + file_name, ErrorCodes::CANNOT_CLOSE_FILE);
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
`Do not use assert` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**4.** Exception types.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
There is no need to use complex exception hierarchy in application code. The exception text should be understandable to a system administrator.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**5.** Throwing exceptions from destructors.
2017-12-28 15:13:23 +00:00
This is not recommended, but it is allowed.
2018-04-23 22:16:40 +00:00
Use the following options:
2018-09-04 11:18:59 +00:00
- Create a function (`done()` or `finalize()` ) that will do all the work in advance that might lead to an exception. If that function was called, there should be no exceptions in the destructor later.
2018-04-23 22:16:40 +00:00
- Tasks that are too complex (such as sending messages over the network) can be put in separate method that the class user will have to call before destruction.
- If there is an exception in the destructor, it’ s better to log it than to hide it (if the logger is available).
2018-09-04 11:18:59 +00:00
- In simple applications, it is acceptable to rely on `std::terminate` (for cases of `noexcept` by default in C++11) to handle exceptions.
2018-04-23 22:16:40 +00:00
**6.** Anonymous code blocks.
You can create a separate code block inside a single function in order to make certain variables local, so that the destructors are called when exiting the block.
```cpp
Block block = data.in->read();
{
std::lock_guard< std::mutex > lock(mutex);
data.ready = true;
data.block = block;
}
ready_any.set();
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**7.** Multithreading.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In offline data processing programs:
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
- Try to get the best possible performance on a single CPU core. You can then parallelize your code if necessary.
2018-03-25 02:04:22 +00:00
2018-04-23 22:16:40 +00:00
In server applications:
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
- Use the thread pool to process requests. At this point, we haven't had any tasks that required userspace context switching.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Fork is not used for parallelization.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**8.** Syncing threads.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Often it is possible to make different threads use different memory cells (even better: different cache lines,) and to not use any thread synchronization (except `joinAll` ).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If synchronization is required, in most cases, it is sufficient to use mutex under `lock_guard` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In other cases use system synchronization primitives. Do not use busy wait.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Atomic operations should be used only in the simplest cases.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Do not try to implement lock-free data structures unless it is your primary area of expertise.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**9.** Pointers vs references.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
In most cases, prefer references.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**10.** const.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Use constant references, pointers to constants, `const_iterator` , and const methods.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Consider `const` to be default and use non-`const` only when necessary.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
When passing variables by value, using `const` usually does not make sense.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**11.** unsigned.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Use `unsigned` if necessary.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**12.** Numeric types.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Use the types `UInt8` , `UInt16` , `UInt32` , `UInt64` , `Int8` , `Int16` , `Int32` , and `Int64` , as well as `size_t` , `ssize_t` , and `ptrdiff_t` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Don't use these types for numbers: `signed/unsigned long` , `long long` , `short` , `signed/unsigned char` , `char` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**13.** Passing arguments.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Pass complex values by reference (including `std::string` ).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If a function captures ownership of an object created in the heap, make the argument type `shared_ptr` or `unique_ptr` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**14.** Return values.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In most cases, just use `return` . Do not write `[return std::move(res)]{.strike}` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
If the function allocates an object on heap and returns it, use `shared_ptr` or `unique_ptr` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
In rare cases you might need to return the value via an argument. In this case, the argument should be a reference.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
```cpp
2018-04-23 22:16:40 +00:00
using AggregateFunctionPtr = std::shared_ptr< IAggregateFunction > ;
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
/** Allows creating an aggregate function by its name.
*/
2018-04-23 22:16:40 +00:00
class AggregateFunctionFactory
{
public:
2018-09-04 11:18:59 +00:00
AggregateFunctionFactory();
AggregateFunctionPtr get(const String & name, const DataTypes & argument_types) const;
2018-04-23 22:16:40 +00:00
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**15.** namespace.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
There is no need to use a separate `namespace` for application code.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Small libraries don't need this, either.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
For medium to large libraries, put everything in a `namespace` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In the library's `.h` file, you can use `namespace detail` to hide implementation details not needed for the application code.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
In a `.cpp` file, you can use a `static` or anonymous namespace to hide symbols.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Also, a `namespace` can be used for an `enum` to prevent the corresponding names from falling into an external `namespace` (but it's better to use an `enum class` ).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**16.** Deferred initialization.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If arguments are required for initialization, then you normally shouldn't write a default constructor.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
If later you’ ll need to delay initialization, you can add a default constructor that will create an invalid object. Or, for a small number of objects, you can use `shared_ptr/unique_ptr` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
Loader(DB::Connection * connection_, const std::string & query, size_t max_block_size_);
2018-04-23 06:20:21 +00:00
2018-09-04 11:18:59 +00:00
/// For deferred initialization
2018-04-23 22:16:40 +00:00
Loader() {}
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**17.** Virtual functions.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
If the class is not intended for polymorphic use, you do not need to make functions virtual. This also applies to the destructor.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**18.** Encodings.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Use UTF-8 everywhere. Use `std::string` and`char *`. Do not use `std::wstring` and`wchar_t`.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**19.** Logging.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
See the examples everywhere in the code.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Before committing, delete all meaningless and debug logging, and any other types of debug output.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Logging in cycles should be avoided, even on the Trace level.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Logs must be readable at any logging level.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Logging should only be used in application code, for the most part.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Log messages must be written in English.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
The log should preferably be understandable for the system administrator.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Do not use profanity in the log.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Use UTF-8 encoding in the log. In rare cases you can use non-ASCII characters in the log.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**20.** Input-output.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Don't use `iostreams` in internal cycles that are critical for application performance (and never use `stringstream` ).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Use the `DB/IO` library instead.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**21.** Date and time.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
See the `DateLUT` library.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**22.** include.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Always use `#pragma once` instead of include guards.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**23.** using.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
`using namespace` is not used. You can use `using` with something specific. But make it local inside a class or function.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**24.** Do not use `trailing return type` for functions unless necessary.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
2018-09-04 11:18:59 +00:00
[auto f() -> void;]{.strike}
2018-04-23 22:16:40 +00:00
```
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**25.** Declaration and initialization of variables.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
2018-09-04 11:18:59 +00:00
//right way
2018-04-23 22:16:40 +00:00
std::string s = "Hello";
std::string s{"Hello"};
2018-09-04 11:18:59 +00:00
//wrong way
auto s = std::string{"Hello"};
2018-04-23 22:16:40 +00:00
```
2018-09-04 11:18:59 +00:00
**26.** For virtual functions, write `virtual` in the base class, but write `override` instead of `virtual` in descendent classes.
2017-12-28 15:13:23 +00:00
2018-08-10 14:44:49 +00:00
## Unused Features of C++
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**1.** Virtual inheritance is not used.
**2.** Exception specifiers from C++03 are not used.
2017-12-28 15:13:23 +00:00
## Platform
2018-04-23 22:16:40 +00:00
**1.** We write code for a specific platform.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
But other things being equal, cross-platform or portable code is preferred.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**2.** Language: C++17.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**3.** Compiler: `gcc` . At this time (December 2017), the code is compiled using version 7.2. (It can also be compiled using `clang 4` .)
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
The standard library is used (`libstdc++` or `libc++` ).
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**4.**OS: Linux Ubuntu, not older than Precise.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**5.**Code is written for x86_64 CPU architecture.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
The CPU instruction set is the minimum supported set among our servers. Currently, it is SSE 4.2.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**6.** Use `-Wall -Wextra -Werror` compilation flags.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**7.** Use static linking with all libraries except those that are difficult to connect to statically (see the output of the `ldd` command).
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**8.** Code is developed and debugged with release settings.
2017-12-28 15:13:23 +00:00
## Tools
2018-09-04 11:18:59 +00:00
**1.** KDevelop is a good IDE.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**2.** For debugging, use `gdb` , `valgrind` (`memcheck`), `strace` , `-fsanitize=...` , or `tcmalloc_minimal_debug` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**3.** For profiling, use `Linux Perf` , `valgrind` (`callgrind`), or `strace -cf` .
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**4.** Sources are in Git.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**5.** Assembly uses `CMake` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**6.** Programs are released using `deb` packages.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**7.** Commits to master must not break the build.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Though only selected revisions are considered workable.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**8.** Make commits as often as possible, even if the code is only partially ready.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Use branches for this purpose.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If your code in the `master` branch is not buildable yet, exclude it from the build before the `push` . You'll need to finish it or remove it within a few days.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**9.** For non-trivial changes, use branches and publish them on the server.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**10.** Unused code is removed from the repository.
2017-12-28 15:13:23 +00:00
## Libraries
2018-09-04 11:18:59 +00:00
**1.** The C++14 standard library is used (experimental extensions are allowed), as well as `boost` and `Poco` frameworks.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**2.** If necessary, you can use any well-known libraries available in the OS package.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
If there is a good solution already available, then use it, even if it means you have to install another library.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
(But be prepared to remove bad libraries from code.)
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**3.** You can install a library that isn't in the packages, if the packages don't have what you need or have an outdated version or the wrong type of compilation.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**4.** If the library is small and doesn't have its own complex build system, put the source files in the `contrib` folder.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**5.** Preference is always given to libraries that are already in use.
2017-12-28 15:13:23 +00:00
2018-08-10 14:44:49 +00:00
## General Recommendations
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**1.** Write as little code as possible.
**2.** Try the simplest solution.
**3.** Don't write code until you know how it's going to work and how the inner loop will function.
2018-09-04 11:18:59 +00:00
**4.** In the simplest cases, use `using` instead of classes or structs.
2018-04-23 22:16:40 +00:00
2018-09-04 11:18:59 +00:00
**5.** If possible, do not write copy constructors, assignment operators, destructors (other than a virtual one, if the class contains at least one virtual function), move constructors or move assignment operators. In other words, the compiler-generated functions must work correctly. You can use `default` .
2018-04-23 22:16:40 +00:00
**6.** Code simplification is encouraged. Reduce the size of your code where possible.
2017-12-28 15:13:23 +00:00
2018-08-10 14:44:49 +00:00
## Additional Recommendations
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**1.** Explicitly specifying `std::` for types from `stddef.h`
2018-04-23 22:16:40 +00:00
2018-09-04 11:18:59 +00:00
is not recommended. In other words, we recommend writing `size_t` instead `std::size_t` , because it's shorter.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
It is acceptable to add `std::` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**2.** Explicitly specifying `std::` for functions from the standard C library
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
is not recommended. In other words, write `memcpy` instead of `std::memcpy` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
The reason is that there are similar non-standard functions, such as `memmem` . We do use these functions on occasion. These functions do not exist in `namespace std` .
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
If you write `std::memcpy` instead of `memcpy` everywhere, then `memmem` without `std::` will look strange.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
Nevertheless, you can still use `std::` if you prefer it.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
**3.** Using functions from C when the same ones are available in the standard C++ library.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
This is acceptable if it is more efficient.
2017-12-28 15:13:23 +00:00
2018-09-04 11:18:59 +00:00
For example, use `memcpy` instead of `std::copy` for copying large chunks of memory.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
**4.** Multiline function arguments.
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
Any of the following wrapping styles are allowed:
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
function(
2018-09-04 11:18:59 +00:00
T1 x1,
T2 x2)
2018-04-23 22:16:40 +00:00
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
function(
2018-09-04 11:18:59 +00:00
size_t left, size_t right,
const & RangesInDataParts ranges,
size_t limit)
2018-04-23 22:16:40 +00:00
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
function(size_t left, size_t right,
2018-09-04 11:18:59 +00:00
const & RangesInDataParts ranges,
size_t limit)
2018-04-23 22:16:40 +00:00
```
```cpp
function(size_t left, size_t right,
2018-09-04 11:18:59 +00:00
const & RangesInDataParts ranges,
size_t limit)
2018-04-23 22:16:40 +00:00
```
2017-12-28 15:13:23 +00:00
2018-04-23 22:16:40 +00:00
```cpp
function(
2018-09-04 11:18:59 +00:00
size_t left,
size_t right,
const & RangesInDataParts ranges,
size_t limit)
2018-04-23 22:16:40 +00:00
```
2018-10-16 10:47:17 +00:00
[Original article ](https://clickhouse.yandex/docs/en/development/style/ ) <!--hide-->