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. Это нестандартное расширение, но поддерживается всеми
основными компиляторами.
Прочее
File Headers — не используем.
Do not use RTTI or Exceptions — в нашем курсе при необходимости можно использовать RTTI и исключения.