Почему важен единый стиль кодирования
Этот проект является проектом с открытым исходным кодом. Чтобы открытый исходный код работал так, как задумано, многие люди должны иметь возможность понимать код. Это означает, что существует хорошо документированный и единообразный поток кода.
Это не обязательно означает, что участник не должен писать оптимизированный, но запутанный код — всегда нужно заботиться о производительности. Однако другим разработчикам необходимо понимать код, а это значит, что сложные части кода должны иметь хорошую документацию.
Почему мы требуем, чтобы всё было задокументировано
То, что просто для одних, может показаться очень сложным другим. Документация помогает этим другим. Любой человек должен иметь возможность улучшить код. Но главная причина в том, что когда участники патчей хотят, чтобы их патчи были добавлены в общую кодовую базу, код должен быть проверен одним или несколькими разработчиками. Документация значительно упрощает проверку.
void ThisIsAFunction()
{
}
int number = 10;
Vehicle *u_first_wagon = v->next;
int value = v->value;
uint32 _global_variable = 3750;
static const char * const _global_array[] = {
"first string",
"second string",
"another string",
"last string followed by comma",
};
protected:
char protected_array[10];
for (int i = 0;;);
bool is_maglev_train = true;
if (!is_maglev_train) DoSomething();
/* Неоптимизированный код:
* foo не затрагивается внутри цикла!
*/
for (uint8 i = 0; i < 100000; i++) {
/* Сделайте что-нибудь */
if (value_to_check == (foo * 4) % 5 + 6) DoSomething();
/* Сделайте ещё что-нибудь */
}
/* Лучше:
* Используемое значение foo вычисляется вне цикла.
*/
const uint32 bar = (foo * 4) % 5 + 6;
for (uint8 i = 0; i < 100000; i++) {
/* Сделайте что-нибудь */
if (value_to_check == bar) DoSomething();
/* Сделайте ещё что-нибудь */
}
Перечисления хранят целые числа, которые логически связаны друг с другом (типы рельсов, идентификаторы строк и т. д.).
В именах перечислений также используется CamelCase.
Нескалярные перечислители — все заглавные буквы с «_» между словами.
Скалярные перечислители используют CamelCase.
Перечисления не используются для хранения отдельных чисел.
У перечислений последовательные числа ИЛИ
У перечислений есть последовательные степени двойки. Степени двойки (биты) записываются в шестнадцатеричном формате или с оператором сдвига.
В перечислениях могут быть специальные перечислители: "_BEGIN", "_END" и "INVALID_"). См. пример.
Значение invalid всегда равно 0xFF, 0xFFFF, 0xFFFFFFFF.
Другие специальные значения последовательно меньше, чем invalid.
Переменные, содержащие перечислители, должны иметь тип перечисления. Причины появления предупреждений в некоторых компиляторах и/или возможные нежелательные побочные эффекты.
C++ определяется с использованием набора символов ASCII. Не используйте другие наборы символов, даже в комментариях.
OpenTTD включает некоторые источники Objective-C (*.mm, используется в OSX), которые имеют специальный синтаксис вызова метода объекта: «[obj doStuff:foo]». Пожалуйста, используйте пробелы внутри скобок, чтобы отличать от синтаксиса массива C.
Мы используем Doxygen для автоматического создания документации из исходного кода. Он сканирует исходные файлы на предмет распознаваемых комментариев.
Сделайте свои комментарии распознаваемыми. Doxygen распознаёт только комментарии, начинающиеся со следующего стиля:
/**
///<
Используйте /** для многострочных блоков комментариев. Используйте ///< для однострочных комментариев для переменных. Используйте //!< для однострочных комментариев в файлах NoAI .hpp. Для блоков комментариев внутри функции всегда используйте /* / или //. Используйте // только если комментарий находится в той же строке, что и инструкция, в противном случае используйте / */.
Поместите команду @file в комментарий в стиле JavaDoc в начале файла, за которым следует описание.
/**
* @file
* Это краткое описание.
* Подробное описание здесь и на следующих строках.
*/
Предупреждение
Если в файле отсутствует блок комментариев файла, то никакие сущности в этом файле не будут задокументированы Doxygen!
Документация должна быть как можно ближе к фактическому коду, чтобы максимизировать вероятность сохранения синхронизации. * Комментарии для функций идут в файле .cpp. * Комментарии для встроенных функций идут в файлах .h/.hpp.
/**
* Краткое объяснение того, что делает функция и/или какую цель она выполняет.
* Затем следует более подробное объяснение функции, которое может занимать несколько строк.
*
* @param foo Объяснение параметра foo
* @param bar Объяснение параметра bar
* @return Сумма foo и bar (@return можно опустить, если тип возврата void)
*
* @see SomeOtherFunc()
* @see SOME_ENUM
*
* @bug Описание одной ошибки
* @bug Ещё одно описание ошибки, которое продолжается в следующей строке
* и заканчивается следующей пустой строкой
*
* @todo Некоторые записи для выполнения
*/
static int FooBar(int foo, int bar)
{
return foo + bar;
}
Документируйте структуры аналогично функциям:
/**
* Короткое описание структуры.
* Более подробное описание её использования.
*
* @см. [ссылку на что-нибудь интересное]
*/
struct foo {
}
В этой таблице показаны команды, которые вы должны использовать с OpenTTD. Полный список здесь.
Команда | Действие | Пример |
---|---|---|
@attention | Начинает абзац, где может быть введено сообщение, требующее внимания. Абзац будет с отступом. | @attention Киты пересекают! |
@brief | Начинается абзац, который служит кратким описанием. Для классов и файлов краткое описание будет использоваться в списках и в начале страницы документации. Для членов класса и файла краткое описание будет помещено при объявлении члена и добавлено к подробному описанию. Краткое описание может занимать несколько строк (хотя рекомендуется делать его кратким!). | @brief Это краткое описание. |
@bug | Начинается абзац, в котором может быть сообщено об одной или нескольких ошибках. Абзац будет с отступом. Несколько соседних команд @bug будут объединены в один абзац. Каждое описание ошибки будет начинаться с новой строки. В качестве альтернативы одна команда @bug может упоминать несколько ошибок. | @bug Утечка памяти здесь? |
@note | Начинается абзац, куда можно ввести примечание. Абзац будет с отступом. | @note Может быть медленным |
@todo | Начинается абзац, описывающий элемент TODO. Описание также добавит элемент в отдельный список задач. Два экземпляра описания будут связаны перекрестными ссылками. Каждый элемент в Список задач будет предваряться заголовком, указывающим происхождение элемента. |
| @todo Улучшить проверку ошибок |
| @warning | Начинает абзац, в котором может быть введено одно или несколько предупреждающих сообщений. Абзац будет с отступом. | @warning Не потокобезопасно! |
|** Команды, связанные с функциями**|
| @return | Начинается описание возвращаемого значения для функции. | @return указатель на символ |
| @param | Начинается описание параметра для параметра функции с именем <имя-параметра>. За ним следует описание параметра. Проверяется наличие параметра, и выдается предупреждение, если документация по этому (или любому другому) параметру отсутствует или не присутствует в объявлении или определении функции.
Команда @param имеет необязательный атрибут, определяющий направление атрибута. Возможные значения: «in» и «out». | @param n Количество байтов для копирования
@param[out] dest Область памяти для копирования в.
@param[in] src Область памяти для копирования из. |
| @see | Начинается абзац, где можно указать одну или несколько перекрестных ссылок на классы, функции, методы, переменные, файлы или URL. Два имени, соединенные либо ::, либо #, понимаются как относящиеся к классу и одному из его членов. Один из нескольких перегруженных методов или конструкторов может быть выбран путем включения списка типов аргументов после имени метода в скобках. Здесь вы можете найти подробную информацию об этой функции. | @see OtherFunc() |
| @b | Отображает следующее слово жирным шрифтом. Эквивалентно <b>word</b>. Чтобы выделить несколько слов жирным шрифтом, используйте <b>несколько слов</b>. | ...@b это и @b то... |
| @c / @p | Отображает параметр <слово> с использованием шрифта пишущей машинки. Вы можете использовать эту команду для ссылки на параметры функции-члена в тексте. Чтобы иметь несколько слов в шрифте пишущей машинки, используйте <tt>несколько слов</tt>. | ... координаты @p x и @p y используются для... |
| @arg / @li | Эта команда имеет один аргумент, который продолжается до первой пустой строки или до другой команды @arg / @li. Команда может использоваться для создания простого, не вложенного списка аргументов. Каждый аргумент должен начинаться с команды @arg / @li. | @arg @c AlignLeft выравнивание по левому краю.
@arg @c AlignCenter выравнивание по центру.
@arg @c AlignRight выравнивание по правому краю |
| @n | Формирует новую строку. Эквивалентен и вдохновлен функцией printf. |@n |
Doxygen знает два разных типа комментариев:
Вы можете опустить любой из них или поместить их в разные места, но для одной и той же сущности допускается только одно краткое и одно подробное описание.
Doxygen знает три режима документирования сущности:
Последний немного сложнее поддерживать, поскольку прототип описываемой им сущности хранится в нескольких местах (например, файл .h и файл с описаниями). Кроме того, хотя это делает код более читаемым, это также упрощает пропуск важного шага обновления описания сущности, если она была изменена - и мы все знаем, почему этого не должно происходить ;)
По этим причинам мы будем использовать только первые две схемы документации.
Doxygen поддерживает стили комментариев Qt и JavaDoc:
Он также поддерживает больше стилей комментариев, но те два, которые стандартизированы. Для OTTD мы будем использовать стиль JavaDoc. Одна из причин заключается в том, что у него есть функция, которой нет у стиля Qt: блоки комментариев в стиле JavaDoc автоматически начинают краткое описание, которое заканчивается при первом Исправить:
Другие советы
Чтобы узнать, есть ли/где у вас конечные пробелы, вы можете использовать следующую команду (unix/bash):
grep -n -R --include "*.[ch]" '[ ]$' * | grep --invert-match ".diff" | grep --invert-match ".patch"
Автоматическое удаление пробелов также возможно с помощью следующего сценария оболочки (обратите внимание, что он проверяет только файлы .c, .cpp, .h, .hpp и .mm):
#!/bin/sh
IFS='
'
for i in Makefile `find . -name \*.c -o -name \*.cpp -o -name \*.h -o -name \*.hpp -o -name \*.mm`
do
(
echo '%s/[ ]\{1,\}$/'
echo w
echo q
) | ed $i 2> /dev/null > /dev/null
done
Клиентские хуки выполняют различные проверки, когда вы фиксируете изменения локально.
Получите хуки:
git clone https://github.com/OpenTTD/OpenTTD-git-hooks.git openttd_hooks
Установите хуки, предполагая, что «openttd» — это папка вашего рабочего дерева:
cd openttd/.git/hooks
ln -s -t . ../../../openttd_hooks/hooks/*
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )