Skip to content

Instantly share code, notes, and snippets.

@antongus
Created March 12, 2024 07:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antongus/66fa5c91a1b8857f63289e3f1ad323ce to your computer and use it in GitHub Desktop.
Save antongus/66fa5c91a1b8857f63289e3f1ad323ce to your computer and use it in GitHub Desktop.

Правила оформления кода

0. Область применения

Весь новый код должен следовать нижеследующим правилам.

Если вы делаете изменения в файле, который ещё не следует этим правилам, ваши изменения всё равно должны им следовать.

1. Расположение фигурных скобок

1.1. Тела функций, определения классов/структур, пространства имён

int myFunction(int a)
{
    // код
}

void myFunction() 
{   // пустое тело функции
}

MyClass::MyClass(int *parent)
    : m_parent(parent)
{
    // инициализация
}

int MyClass::myMethod(int a)
{
    // код
}

class MyOtherClass
{
public:
    // код

protected:
    // код

private:
    // код
};

namespace Name
{
    // код
}

// Лямбды
[](int arg1, int arg2) -> bool { return arg1 < arg2; }

[this](int arg)
{
    this->acc += arg;
}

1.2. Остальные блоки кода

if (condition) 
{
    // код
}

for (auto a = 0; a < b; ++b) 
{
    // код
}

switch (a) 
{
case 1:
    // код
    break;

case 2:
    // код
    break;

default:
    // код
}

1.3. Блоки в switch

switch (var) 
{
case 1: 
    {
        // объявление локальных переменных
        // код
    }
    break;
case 2: 
    {
        // объявление локальных переменных
        // код
    }
    break;
default:
    // код
}

1.4. Выражения if-else

else if/else должны распологаться на отдельных строках:

if (condition)
{
    // код
}
else if (condition) 
{
    // код
}
else 
{
    // код
}

1.5. блоки if с одиночными выражениями

Блоки if с одиночными выражениями должны выглядеть так:

if (condition)
    a = a + b;

Допустимое исключение: return, break или continue, когда условие не слишком длинное и занимает одну строчку. Однако даже в этом случае можно использовать предыдущее правило.

if (a > 0) return;

while (p) 
{
    // ...
    if (!b) continue;
}

1.6. Когда можно не писать скобки

Скобки можно опустить, если условие в if/else занимает одну строчку, и если тело if/else состоит из одного выражения. Это же правило применимо к циклам.

Если одна из веток if - else нуждается в скобках, вторую ветку тоже нужно обернуть в скобки.

if (a < b)  // условие
    do(a);  // тело - одно выражение. Можно без скобок

if (a < b)
    do(a);
else if (a > b)
    do(b);
else
    do(c);

if (a < b) 
{
    do(a);
}
else if (a > b) 
{  // здесь нужны скобки, поэтому все остальные ветки тоже в скобках
    do(b);
    do(d);
}
else 
{
    do(c);
}

1.7. Инициализаторы в фигурных скобках (универсальные инициализаторы)

Это не функции. Пробелы внутри скобок не нужны. Пробел перед скобками - нужен:

MyType obj {}; // пустой инициализатор
MyType obj {expr};
MyType obj {expr1, /*...,*/ exprN};

2. Оступы и выравнивание

Для отступов использовать табуляцию, для выравнивания - пробелы (ссылка):

void my_func(void)
{
>---do_something();
>---if (everything_ok()){
>--->---int var1.........= 0,
>--->---....another_var..= 1,
>--->---....third_var....= 2;
 
>--->---do_something_different();
>---}
}

3. Кодировка файлов и переводы строк

Кодировка файлов: UTF-8 Переводы строк: unix (LF).

4. Списки инициализации

Списки инициализации должны быть вертикальными. Это даёт более читабельные diff-ы. Двоеточие в списке инициализации должно быть с отступом и располагаться в строке перед первым элементом. Запятые - перед каждым следующим элементом (тоже с отступом).

myClass::myClass(int a, int b, int c, int d)
    : m_a(a)
    , m_b(b)
    , m_c(c)
    , m_d(d)
{
    // код
}

5. Enum-ы

Enum-ы должны быть вертикальными. Это даёт более читабельные diff-ы.

enum Days
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

6. Имена

Имена должны быть в camelCase.

6.1. Типы и пространства имён

Имена типов и пространств имён должны начинаться с заглавной буквы.

class ClassName {};

struct StructName {};

enum EnumName {};

using SomeList = List ;

namespace NamespaceName
{
}

6.2. Имена переменных

Имена переменных должны начинаться со маленькой буквы.

int myVar;

6.3. Имена приватных переменных-членов класса

Имена приватных переменных-членов класса начинаются с маленькой буквы и должны иметь префикс m_.

class MyClass
{
    int m_myVar;
}

7. Порядок включения заголовочных файлов

Заголовочные файлы должны включаться в следующем порядке:

  1. Системные заголовочные файлы;
  2. Заголовочные файлы стандартной библиотеки C/C++
  3. Заголовочный файл модуля
  4. Заголовочные файлы проекта

Заголовки внутри каждой группы должны распологаться в алфавитном порядке.
Если какой-то заголовочный файл включается условно, то его помещать в конце группы.

Пример:

// file: MyModule.cpp

// Системные заголовочные файлы
#include <intrinsics.h>

// Заголовочные файлы стандартной библиотеки C/C++
#include <cstdint>
#include <cstdio>

// Заголовочный файл модуля
#include "MyModule.h"

// Заголовочные файлы проекта
#include "MyAnotherModule.h"

8. Include guard

Вместо "include guard" можно использовать #pragma once:

// example_module.h

#pragma once

#include 

class ExampleModule : public BaseModule
{
    // (some code omitted)
};

9. Прочее

  • Разбиение длинных строк:

  • Пробелы в выражениях

// До и после оператора присваивания и другого бинарного или тернарного оператора нужны пробелы. Не нужны пробелы между операторами инкремента/декремента и их операндами.

a += 20;
a = (b <= maxVal ? b : maxVal);
++a;
--b;

for (int a = 0; a < b; ++b) 
{
}

// Цикл по диапазону, пробелы перед и после двоеточия
for (auto i : container) 
{
}

// Наследование, пробелы до и после двоеточия
class Derived : public Base
{
};
  • Предпочитать пре-декремент/инкремент пост-инкременту/декременту
++i, --j;  // Так лучше
i++, j--;  // Так только при необходимости

10. Commit-сообщение git

  1. Первая строка (заголовок сообщения коммита) - краткое описание коммита. Длина до 80 символов. Краткое описание не должно содержать лишних деталей;
  2. Затем пустая строка (в GUI обычно формируется автоматически);
  3. Затем более подробное описание (тело сообщения коммита), если это необходимо.
  4. В теле сообщения коммита описать, что делает коммит и зачем.
  5. Если коммит закрывает какую-то задачу, нужно указать это в теле коммита (закрывает задачу #123)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment