title_wip

**4.** Comments should be written in English only.

**5.** If you are writing a library, include detailed comments explaining it in the main header file.

**6.** Do not add comments that do not provide additional information. In particular, do not leave empty comments like this:

```
/*
* 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:
*/
```

The example is borrowed from the resource <http://home.tamk.fi/~jaalto/course/coding-style/doc/unmaintainable-code/>.

**7.** Do not write garbage comments (author, creation date ..) at the beginning of each file.

**8.** Single-line comments begin with three slashes: `///` and multi-line comments begin with `/**`. These comments are considered "documentation".

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.

**9.** Multi-line comments must not have empty lines at the beginning and end (except the line that closes a multi-line comment).

**10.** For commenting out code, use basic comments, not "documenting" comments.

**11.** Delete the commented out parts of the code before committing.

**12.** Do not use profanity in comments or code.

**13.** Do not use uppercase letters. Do not use excessive punctuation.

```
/// WHAT THE FAIL???
```

**14.** Do not use comments to make delimiters.

```
///******************************************************
```

**15.** Do not start discussions in comments.

```
/// Why did you do this stuff?
```

**16.** There's no need to write a comment at the end of a block describing what it was about.

```
/// for
```

## Names[​](#names "Direct link to Names")

**1.** Use lowercase letters with underscores in the names of variables and class members.

```
size_t max_block_size;
```

**2.** For the names of functions (methods), use camelCase beginning with a lowercase letter.

```
std::string getName() const override { return "Memory"; }
```

**3.** For the names of classes (structs), use CamelCase beginning with an uppercase letter. Prefixes other than I are not used for interfaces.

```
class StorageMemory : public IStorage
```

**4.** `using` are named the same way as classes.

**5.** Names of template type arguments: in simple cases, use `T`; `T`, `U`; `T1`, `T2`.

For more complex cases, either follow the rules for class names, or add the prefix `T`.

```
template <typename TKey, typename TValue>
struct AggregatedStatElement
```

**6.** Names of template constant arguments: either follow the rules for variable names, or use `N` in simple cases.

```
template <bool without_www>
struct ExtractDomain
```

**7.** For abstract classes (interfaces) you can add the `I` prefix.

```
class IProcessor
```

**8.** If you use a variable locally, you can use the short name.

In all other cases, use a name that describes the meaning.

```
bool info_successfully_loaded = false;
```

**9.** Names of `define`s and global constants use ALL\_CAPS with underscores.

```
#define MAX_SRC_TABLE_NAMES_TO_STORE 1000
```

**10.** File names should use the same style as their contents.

If a file contains a single class, name the file the same way as the class (CamelCase).

If the file contains a single function, name the file the same way as the function (camelCase).

**11.** If the name contains an abbreviation, then:

- For variable names, the abbreviation should use lowercase letters `mysql_connection` (not `mySQL_connection`).
- For names of classes and functions, keep the uppercase letters in the abbreviation`MySQLConnection` (not `MySqlConnection`).

**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.

```
FileQueueProcessor(
    const std::string & path_,
    const std::string & prefix_,
    std::shared_ptr<FileHandler> handler_)
    : path(path_),
    prefix(prefix_),
    handler(handler_),
    log(&Logger::get("FileQueueProcessor"))
{
}
```

The underscore suffix can be omitted if the argument is not used in the constructor body.

**13.** There is no difference in the names of local variables and class members (no prefixes required).

```
timer (not m_timer)
```

**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`.

```
enum class CompressionMethod
{
    QuickLZ = 0,
    LZ4     = 1,
};
```

**15.** All names must be in English. Transliteration of Hebrew words is not allowed.

not T\_PAAMAYIM\_NEKUDOTAYIM

**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).

`AST`, `SQL`.

Not `NVDH` (some random letters)

Incomplete words are acceptable if the shortened version is common use.

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.

## How to write code[​](#how-to-write-code "Direct link to How to write code")

**1.** Memory management.

Manual memory deallocation (`delete`) can only be used in library code.

In library code, the `delete` operator can only be used in destructors.

In application code, memory must be freed by the object that owns it.

Examples:

- 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.
- For automatic deallocation of a small number of objects that reside in the heap, use `shared_ptr/unique_ptr`.

**2.** Resource management.

Use `RAII` and see above.

**3.** Error handling.

Use exceptions. In most cases, you only need to throw an exception, and do not need to catch it (because of `RAII`).

In offline data processing applications, it's often acceptable to not catch exceptions.

In servers that handle user requests, it's usually enough to catch exceptions at the top level of the connection handler.

In thread functions, you should catch and keep all exceptions to rethrow them in the main thread after `join`.

```
/// If there weren't any calculations yet, calculate the first block synchronously
if (!started)
{
    calculate();
    started = true;
}
else /// If calculations are already in progress, wait for the result
    pool.wait();

if (exception)
    exception->rethrow();
```

Never hide exceptions without handling. Never just blindly put all exceptions to log.

```
//Not correct
catch (...) {}
```

If you need to ignore some exceptions, do so only for specific ones and rethrow the rest.

```
catch (const DB::Exception & e)
{
    if (e.code() == ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION)
        return nullptr;
    else
        throw;
}
```

When using functions with response codes or `errno`, always check the result and throw an exception in case of error.

```
if (0 != close(fd))
    throw ErrnoException(ErrorCodes::CANNOT_CLOSE_FILE, "Cannot close file {}", file_name);
```

You can use assert to check invariant in code.

**4.** Exception types.

There is no need to use complex exception hierarchy in application code. The exception text should be understandable to a system administrator.

**5.** Throwing exceptions from destructors.

This is not recommended, but it is allowed.

Use the following options: