Для форматирования кода следует использовать astyle
со следущими параметрами командной строки:
astyle --style=java --indent=tab=4 --attach-namespaces --attach-classes --attach-extern-c --indent-switches --indent-namespaces --indent-preproc-block --indent-preproc-cond --indent-preproc-define --pad-oper --pad-comma --pad-header --unpad-paren --fill-empty-lines --align-pointer=name --align-reference=name --add-brackets --remove-comment-prefix --lineend=linux <source code>
Или проще:
astyle --options=.astylerc <source code>
.
Файл опций .astylerc
лежит в этом репозитории.
Оформление конструктора класса должно выглядеть следующим образом:
Constructor::Constructor(int a, int b)
: m_a(a), m_b(b) {
// operators
}
Оформление оператора switch
должно выглядеть следующим образом:
switch (a) {
case 1: {
// operators
break;
}
case 2: {
// operators
break;
}
...
default: {
// operators
}
}
Наличие ветви default
обязательно, ограждать случаи в switch
фигурными скобками также обязательно.
Следует избегать коротких или однобуквенных названий переменных и функций, а так же названий, которые можно трактовать различными способами.
Примеры плохих названий переменных: flag
, x
, cnt
, num
, ans
, val
, date
, f
.
Исключение: допустимо (но не рекомендуется) использование переменной i
в качестве локальной переменной-счётчика простого цикла for
. Например, допустимо использование таких переменных для простого чтения или вывода массивов. В случае, если тело цикла содержит несколько команд или ветвление, использования однобуквенных переменных следует избегать.
Названия полей, методов класса и функций должны писаться в lowerCamelCase: myLittleCamel
.
Названия классов, пространств имен и типов должны писаться в CamelCase: MyBigCamel
.
Названия полей в enum
, констант, а также макросов (которые не рекомендуется использовать), нужно писать БОЛЬШИМИ_БУКВАМИ
.
К названиям полей классов следует добавлять префикс m_
: m_начинатьСБуквыMЧтоЗначитMember
.
К названиям глобальных переменных стоит добавлять префикс g_
: g_начинатьСБуквыGЧтоЗначитGlobal
.
Названия переменных, содержащие цифры, лучше не использовать.
Исключение: в простейщих операторах (например, операторах сравнения), а также простейших функциях типа min
, max
допустимо использование переменных типа item1
, item2
.
Для целочисленных типов лучше использовать int8_t
, uint8_t
, int16_t
, uint16_t
, int32_t
, uint32_t
, int64_t
, uint64_t
, intptr_t
, uintptr_t
и size_t
. Про int
, long long
и т. д. стоит забыть.
Директивы препроцессора #define
и #pragma
лучше избегать. #define
хорошо использовать только для условной компиляции.
Писать using namespace std;
не надо (особенно в заголовочных файлах).
Стоит избегать использования функций в стиле Си, вроде scanf
, printf
, malloc
, free
, gets
и так далее.
Для прохода по контейнерам стоит использовать for each, например, так:
for (ItemType item: items) {
// operators
}
Стоит активно использовать пространства имен, для разных частей системы— разные пространства имен.
На C++ можно писать код, полный трюков, однако так делать не стоит. Код должен быть максимально ясным и понятным. Не стоит делать несколько действий в одну строку. Например, вместо
while (a[i++] = --j);
стоит написать
while (j != 1) {
--j;
a[i] = j;
++i;
}
Предпочитайте префиксный инкремент (++i
вместо i++
).
Для перечислений стоит использовать enum class
вместо enum
.
Не стоит использовать преобразования типов в стиле Си, используйте static_cast<T>
.
Возможно, список будет пополняться.
Заголовочные файлы должны иметь расширение .hpp
, а исходники C++— расширение .cpp
. Заголовочные файлы следует называть в camelCase, например: headerFile.hpp
.
В заголовочном файле должны содержаться следующие строки (пусть файл называется example/myHeader.hpp
):
#ifndef EXAMPLE_MY_HEADER_HPP
#define EXAMPLE_MY_HEADER_HPP
// Здесь код
#endif
В начале каждого файла должен содержаться заголовок лицензии. Выглядит он следующим образом:
/*
This file is part of Taker
Copyright (C) <год> Taker Project Developers
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Ниже должен идти комментарий, который поясняет назначение файла.
Использование литералов в коде нежелательно. Исключения такие: разрешены числовые литералы 0
, 1
, -1
. Все остальные литералы необходимо оформить в виде констант. Например, код
for (int i = 0; i < 12; i++) {
if (values[i] > 4096) {
return 42;
}
}
можно переписать так:
const int valuesCount = 12;
const int maxValue = 4096;
const int statusBadValue = 42;
for (int i = 0; i < valuesCount; i++) {
if (values[i] > maxValue) {
return statusBadValue;
}
}
Конечно, в реальном коде лучше всего дать наиболее осмысленные имена константам. statusBadValue
здесь только для примера, гораздо лучше использование enum class
для подобных целей.
Строковые константы лучше "складывать" в один заголовочный файл, чтобы потом можно было просто переводить систему на другой язык. Исключение составляют строковые константы, которые переводить не требуется, например, название команды или исполняемого файла компилятора.
Для работы над проектом будет использоваться git
. Каждый должен работать в своей ветке, которые потом будут сливаться вместе. Коммитить напрямую в ветку master
можно только в особых случаях (например, исправление мелкого бага в уже существующем коде, которое можно сделать за один небольшой коммит). Перед тем, как коммитить в master
, лучше согласовать это.
Сливать ветки в master
может только главный по проекту. Для того, чтобы предложить слить свою ветку с master
, лучше использовать механизм pull-request.
Коммиты должны быть логически законченными, содержать логически связанные изменения. Если коммитом затрагиваются слабо связанные между собой изменения, лучше разбить его на несколько.
Названия коммитов и pull-requestов должно быть осмысленное и отражать сделанные в них изменения.
Следовать спецификациям в этом репозитории обязательно. Если вы считаете, что какую-то часть этих спецификаций стоит изменить, стоит сначала сделать pull-request в этот репозиторий.
Может получиться и так, что спецификации описывают не все. Если какая-то часть кода реализует незадокументированные в спецификациях возможности, стоит добавить информацию о них сюда.
Если часть спецификации сложна в реализации или оставлена на потом, стоит оставить TODO-комментарий в коде, чтобы эту часть спецификации можно было реализовать потом.