Code Style

Писать с нуля кодстайл по C++ для учебного курса — нерационально. С другой стороны, полное заимствование сторонних соглашений также не всегда оправдано, поскольку в них встречаются рекомендации, специфичные для конкретных компаний или проектов.

За основу мы принимаем LLVM Coding Standards, а ниже изложены отличия для нашего курса.

Форматирование

Стиль форматирования должен быть зафиксирован в конфиге .clang-format и остается на ваше усмотрение (в пределах разумного). Сгенерируйте конфиг командой clang-format -dump-config и адаптируйте на свой вкус.

Ширину отступа рекомендуется установить в 2 или 4 пробела. Символы табуляции не использовать.

Рекомендации для diff-friendly форматирования:

# Отключаем все вертикальное выравнивание.
# Если выравнивание включено, то логические изменения в одной строке
# могут привести к физическим изменениям в соседних строках, что усложняет
# чтение diff-ов.
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands:   DontAlign
AlignTrailingComments: false

# Также отключаем упаковку аргументов и параметров функций.
# Остается минимум вариантов форматирования:
#  - Все аргументы функции на одной строке с ее именем.
#    foo(a, b, c);
#  - Все аргументы функции на одной строке, перенос после открывающей скобки.
#    foo(
#      a, b, c);
#  - Каждый аргумент на отдельной строке
#    foo(
#      a,
#      b,
#      c);
#
# Упаковка может приводить к изменениям форматирования в случае рефакторинга
# (переименование функции или аргумента, изменение списка аргументов, и т. д.)
BinPackArguments: false
BinPackParameters: false

Имена идентификаторов

  • lower_case_with_underscores: объекты, функции, пространства имен;

  • data_member_: поля структур, классов и объединений — с нижним подчеркиванием в конце;

  • c_name — для глобальных констант используется префикс c_;

  • UpperCamelCase: классы, структуры, объединения, перечисления, синонимы;

  • UPPER_CASE_WITH_UNDERSCORES: макросы.

Следует давать переменным содержательные имена. Различные типы объявлений подчиняются следующим правилам:

  • Имена типов и переменных должны быть существительными.

  • Имена функций должны содержать глаголы.

Неудачные имена:

// Слишком общее имя.
bool flag = false;

// Непонятно назначение буфера.
char buf[BUFSIZE];

// Герундий в имени функции.
int* finding_element(const int* begin, const int* end);

// Что конкретно проверяет эта функция?
bool check(const Triangle* triangle);

Лучше:

// Название флага отражает смысл.
bool found = false;

// Понятно, какие данные хранятся в буфере.
char error_message[MAX_MESSAGE_LENGTH];

// Ок - глагол.
int* find_element(const int* begin, const int* end);

// Семантика функции понятна без документации.
// Для предиката используется префикс is_, в точке вызова
// будет очевиден тип возвращаемого значения.
bool is_equilateral(const Triangle* triangle);

Include Guard

Для защиты от повторого включания заголовочных файлов следует использовать #pragma once. Это нестандартное расширение, но поддерживается всеми основными компиляторами.

Прочее