Правила оформления кода — различия между версиями
Root (обсуждение | вклад) м (Общие правила - язык и кодировка) |
Korvin (обсуждение | вклад) м (→Правила именования) |
||
(не показаны 15 промежуточных версий 9 участников) | |||
Строка 52: | Строка 52: | ||
После этого комментария может идти текст лицензии или какие-либо лицензионные предупреждения (некоторые лицензии это требуют). Но такой текст должен идти ПОСЛЕ заголовка, а не до него. | После этого комментария может идти текст лицензии или какие-либо лицензионные предупреждения (некоторые лицензии это требуют). Но такой текст должен идти ПОСЛЕ заголовка, а не до него. | ||
+ | |||
+ | Поля author и e-mail могут быть записаны несколько раз, в случае если авторов/адресов несколько. | ||
Строгость формата заголовка нужна в частности для того, чтобы можно было писать скрипты, собирающие статистику. Например, это будет использоваться скриптами, которые будут анализировать объемы работ различных авторов. | Строгость формата заголовка нужна в частности для того, чтобы можно было писать скрипты, собирающие статистику. Например, это будет использоваться скриптами, которые будут анализировать объемы работ различных авторов. | ||
Строка 61: | Строка 63: | ||
// date : 2008-11-30 | // date : 2008-11-30 | ||
// author : Ivan Ivanov | // author : Ivan Ivanov | ||
+ | // e-mail : ivan.ivanov@example.com | ||
// licence : MIT | // licence : MIT | ||
// | // | ||
Строка 101: | Строка 104: | ||
# '''Классы именуются в стиле MyClassName''', без каких-либо префиксов; | # '''Классы именуются в стиле MyClassName''', без каких-либо префиксов; | ||
# '''Публичные методы и свойства именуются в стиле someMethodName'''; | # '''Публичные методы и свойства именуются в стиле someMethodName'''; | ||
− | # ''' | + | # '''Аргументы функций именуются в стиле argument_name'''; |
+ | # '''Все публичные имена должны быть говорящими, желательно без сокращений, но при этом не слишком длинными'''. Примерное ограничение по длине имени - 20 символов; | ||
# Приватные методы и свойства именуются аналогично публичным; | # Приватные методы и свойства именуются аналогично публичным; | ||
# Локальные переменные именуются в стиле variable_name (все буквы - строчные, символы подчеркивания между словами); | # Локальные переменные именуются в стиле variable_name (все буквы - строчные, символы подчеркивания между словами); | ||
Строка 108: | Строка 112: | ||
Такой подход к именованию имеет множество плюсов. В нем практически не используются префиксы (которые обычно надоедают), но при этом стиль написания имен классов, методов и переменных различается, что облегчает читаемость кода. | Такой подход к именованию имеет множество плюсов. В нем практически не используются префиксы (которые обычно надоедают), но при этом стиль написания имен классов, методов и переменных различается, что облегчает читаемость кода. | ||
− | Обратите внимание, что мы требуем выполнения правил по именованию публичных частей модуля, но по именам "внутренней кухни" даем лишь рекомендации. Это сделано для обеспечения | + | Обратите внимание, что мы требуем выполнения правил по именованию публичных частей модуля, но по именам "внутренней кухни" даем лишь рекомендации. Это сделано для обеспечения единообразия интерфейсов. |
== Правила для C++ кода == | == Правила для C++ кода == | ||
Строка 203: | Строка 207: | ||
* Определения препроцессора именуются по прописной схеме. Кроме того, для всех определений препроцессора ставится два префикса. Первый соответствует модулю и его части (4 символа), второй - смыслу определения. Префиксы отделяются друг от друга и от имени знаком подчеркивания. Пример: '''SEST_IBS_LOADED''' (Soung Engine, STreaming module; Index Buffer State). | * Определения препроцессора именуются по прописной схеме. Кроме того, для всех определений препроцессора ставится два префикса. Первый соответствует модулю и его части (4 символа), второй - смыслу определения. Префиксы отделяются друг от друга и от имени знаком подчеркивания. Пример: '''SEST_IBS_LOADED''' (Soung Engine, STreaming module; Index Buffer State). | ||
+ | * Интерфейсы (классы, в которых все методы - абстрактные) именуются по стандартной схеме, ставится префикс '''I''' (ISomeName). | ||
* Классы именуются по стандартной схеме, ставится префикс '''C''' (CClassName). | * Классы именуются по стандартной схеме, ставится префикс '''C''' (CClassName). | ||
* Структуры именуются по стандартной схеме (StructName). | * Структуры именуются по стандартной схеме (StructName). |
Текущая версия на 17:53, 18 мая 2009
[править] Введение
На этой странице описаны правила оформления кода для библиотек и прикладных программ проекта Deeptown. Соблюдение этих правил не менее важно, чем качество кода: это повышает читаемость кода другими людьми. Несоблюдение этих правил может стать причиной отказа в принятии кода.
Конечно, из любых правил есть исключения, и никто не требует следовать этим правилам до буквы. Но практика показывает, что код, оформленный в едином стиле, легче читается и понимается людьми, занятыми в проекте. В отличие от многих других проектов, наши правила - не очень строгие, и в них обозначены только самые базовые вещи.
В первом разделе приводятся общие правила для всех языков программирования и разметки; в последующих разделах они конкретизируются для различных языков.
[править] Общие правила
[править] Язык и кодировка
Для кода програм следует использовать только английский язык. Все имена в программе и комментарии к ней должны быть составлены на ангийском. Использование транслита в именах строго запрещено. Помните, что Ваш код могут читать не только русские.
Для интернациональных символов в проекте используется кодировка UTF-8. Вы можете использовать строки на русском и других языках прямо в коде программ - для этого нужно сохранить исходный код программы в кодировке UTF-8. Но помните, что это является плохим стилем: в хорошей программе, все интернациональные сообщения находятся в файлах данных.
[править] Подход к написанию кода
Самое главное правило: код должен быть легкочитаем и красив.
Диптаун - это очень большой проект, состоящий из множества модулей. Эти модули завязаны друг на друга, и правильное функционирование одних невозможно без других. Поэтому мы не приемлем write-only код.
Для того, чтобы код получался красивым, прежде всего нужен творческий подход к его написанию. Поэтому мы не приводим каких-либо формальных правил по этому вопросу. Спорные ситуации будут решаться в дискуссиях.
Очень советуем прочитать статью про анти-паттерны в википедии.
[править] Комментарии
Код должен быть откомментирован так, чтобы обеспечить его читаемость, но и не должен быть перегружен комментариями.
Обычно для выполнения этого условия достаточно написать небольшие пояснения к каждому классу и методу в этом классе.
Комментарии должны объяснять, как работает код, но не что он делает. Ответ на второй вопрос должен содержаться в документации, а не в коде; мы не используем в проекте системы вроде doxygen для создания документации из кода, поскольку убеждены, что документация в коде загромождает этот код и делает его трудночитаемым.
Кроме того, все комментарии должны быть на английском языке. У этого правила несколько причин, самые главные из которых - возможность чтения кода иностранцами и в любом редакторе. Комментарии транслитом также не допускаются.
[править] Комментарий в начале файла
В начале каждого исходного файла должна содержаться следующая информация:
// // project : <project name> // date : <current date> // author : <author name> // e-mail : <author email> // licence : <licence name> //
Имя проекта - это название задания в списке задач, переведенное на английский язык, например, - console programs. Дата - текущая дата в формате yyyy-mm-dd. Имя автора записывается в форме Имя Фамилия (также по-английски), например: Vasily Petrov (но не Petrov Vasily). E-mail - это актуальный адрес автора, который может быть использован для писем по вопросам работоспособности данного кода.
Лицензия - это либо название одной из применяемых в проекте лицензий (MIT, LGPL etc), либо имя файла с лицензией. Персональные лицензии должны храниться в файлах, содержащих имя автора в имени файла, например licence-petrov-vasily.txt. Все такие лицензии будут добавлены в репозиторий с кодом.
После этого комментария может идти текст лицензии или какие-либо лицензионные предупреждения (некоторые лицензии это требуют). Но такой текст должен идти ПОСЛЕ заголовка, а не до него.
Поля author и e-mail могут быть записаны несколько раз, в случае если авторов/адресов несколько.
Строгость формата заголовка нужна в частности для того, чтобы можно было писать скрипты, собирающие статистику. Например, это будет использоваться скриптами, которые будут анализировать объемы работ различных авторов.
Пример заголовочного комментария:
// // project : mysql database driver // date : 2008-11-30 // author : Ivan Ivanov // e-mail : ivan.ivanov@example.com // licence : MIT //
[править] Отступы в коде
Прежде всего, в качестве отступов нельзя использовать символы табуляции. Они по-разному отображаются в различных программах просмотра/редакторах, что затрудняет чтение кода. В качестве отступов следует использовать четыре символа "пробел".
[править] Использование операторных скобок { }
Все операторные скобки ставятся на новой строке; к коду, заключенному в операторные скобки, добавляется один отступ. Код начинается со следующей после открывающей скобки строки. Исключение делается для конструкций, где тело операторных скобок состоит из не более чем 10 строк. В этом случае допускается открывающую операторную скобку поставить на ту же строку, что и "породивший" ее оператор:
while(...) { // some stuff }
Кроме того, специальное исключение делается для конструкции if ... else:
if(...) { // stuff... } else { // more stuff... }
Исключение также применимо только для не слишком длинных конструкций.
[править] Правила для K++ кода
[править] Правила именования
(жирным отмечены обязательные правила, остальные - желательны, но не обязательны).
- Модули именуются в стиле MyModuleName;
- Имена файлов в точности совпадают с именами модулей. Например, модуль Proto::HTTP должен находиться в файле Proto/HTTP.kpp;
- Классы именуются в стиле MyClassName, без каких-либо префиксов;
- Публичные методы и свойства именуются в стиле someMethodName;
- Аргументы функций именуются в стиле argument_name;
- Все публичные имена должны быть говорящими, желательно без сокращений, но при этом не слишком длинными. Примерное ограничение по длине имени - 20 символов;
- Приватные методы и свойства именуются аналогично публичным;
- Локальные переменные именуются в стиле variable_name (все буквы - строчные, символы подчеркивания между словами);
- Поля класса именуются аналогично локальным переменным, но с префиксом m_.
Такой подход к именованию имеет множество плюсов. В нем практически не используются префиксы (которые обычно надоедают), но при этом стиль написания имен классов, методов и переменных различается, что облегчает читаемость кода.
Обратите внимание, что мы требуем выполнения правил по именованию публичных частей модуля, но по именам "внутренней кухни" даем лишь рекомендации. Это сделано для обеспечения единообразия интерфейсов.
[править] Правила для C++ кода
Этот раздел скопирован из стандарта кода самого Диптауна. Возможно, некоторым не понравится такой стиль, но так уж исторически сложилось. Если возражений будет слишком много - мы напишем скрипт, который сконвертирует один стиль в другой. Но делать это будем централизованно. Сейчас в проекте принят такой стиль, и холивары по этому поводу очень нежелательны.
[править] Переносимость кода
Весь код проекта должен компилироваться, собираться и работать на любой системе, будь то Windows, Mac, UNIX, Solaris и другие. Использование библиотек также ограничено лишь лицензионными соглашениями и переносимостью их на другие системы. В некоторых случаях допускаются исключения: код может быть написан в нескольких вариантах для разных систем. Но в конечном итоге, должна быть возможность сборки кода на любой системе.
[править] Схемы разыменовывания
Далее по тексту используются следующие определения для имен различных объектов:
- произвольная - объект может быть назван произвольно.
- прописная слитная - объект должен быть назван прописными буквами, слова не должны отделяться друг от друга. Например, OBJECTNAME.
- прописная [раздельная] - объект должен быть назван прописными буквами, слова отделяются друг от друга знаком подчеркивания: OBJECT_NAME.
- строчная слитная, строчная [раздельная] - аналогично: objectname и object_name соответственно.
- основная - название должно начинаться с прописной буквы, и каждое слово должно начинаться с прописной буквы. Остальные буквы - строчные: ObjectName.
[править] Файловая структура верхнего уровня
Весь код проекта представляет собой дерево подпроектов. Каждый подпроект - это логически завершенный модуль, который может либо сам состоять из подпроектов; либо компилироваться в программу, статическую или динамическую библиотеку или скрипт; либо, наконец, содержать в себе и то, и другое. Подпроекты именуются по строчной (иногда раздельной) схеме именования и располагаются в каталогах, соответствующих их именам.
Таким образом, за каждым подпроектом закрепляется его уникальный идентификатор - это путь к подпроекту относительно корневого каталога проекта.
[править] Разыменовывание файлов
Все файлы модуля должны быть названы по строчной схеме именования. Исключение составляют лишь исходные файлы, в которых находятся реализации некоторых классах - они в точности соответствуют именам классов. Об этом будет сказано далее.
[править] Разбиение файлов по каталогам
Все файлы модуля разбиваются по каталогам следующим образом:
- все публичные включаемые файлы должны находиться в корневом каталоге модуля;
- все внутренние включаемые файлы должны находиться в подкаталоге impl;
- все исходные файлы должны находиться в каталоге source.
[править] Разбиение функций и классов по файлам
Внутри каждого модуля или его части, функции и классы разбиваются на внутренние - используемые только данным модулем, и публичные - экспортируемые модулем для "внешнего мира".
Все публичные функции и классы должны быть вынесены в один или несколько заголовочных файлов. На разбиение по файлам ограничений не накладывается.
Внутренние функции и классы не должны быть объявлены в публичных заголовочных файлах, и никоим образом не должны быть доступны для "внешнего мира".
Реализация каждого класса должна быть вынесена в отдельный исходный файл, имя которого совпадает с именем класса.
На разбиение реализаций отдельных функций по файлам ограничений не накладывается.
[править] Пространства имен
Все объявления каждого модуля должны быть внесены в отдельное пространство имен (namespace), имя которого совпадает с именем модуля, записанного по основной схеме разыменовывания.
[править] Стражи включения
Все файлы заголовков должны быть защищены стражем включения. Имя стража включения дается следующему шаблону: __PRFX_FILENAME_H_INCLUDED.
Здесь PRFX - префикс модуля и его части (см. п. 4.1), FILENAME - имя заголовочного файла, записанное прописными буквами.
Пример:
#ifndef __SEST_INDEXBUFFER_H_INCLUDED #define __SEST_INDEXBUFFER_H_INCLUDED // ... // ... #endif // EOF
[править] Правила именования сущностей
Применяются следующие правила разыменовывания:
- Определения препроцессора именуются по прописной схеме. Кроме того, для всех определений препроцессора ставится два префикса. Первый соответствует модулю и его части (4 символа), второй - смыслу определения. Префиксы отделяются друг от друга и от имени знаком подчеркивания. Пример: SEST_IBS_LOADED (Soung Engine, STreaming module; Index Buffer State).
- Интерфейсы (классы, в которых все методы - абстрактные) именуются по стандартной схеме, ставится префикс I (ISomeName).
- Классы именуются по стандартной схеме, ставится префикс C (CClassName).
- Структуры именуются по стандартной схеме (StructName).
- Функции и методы классов также именуются по стандартной схеме.
- Закрытые поля и локальные переменные именуются произвольно.
- Публичные поля классов и аргументы функций именуются по следующей схеме: имя переменной записываеися по основной схеме; добавляется префикс, соответствующий типу переменной (pszIndexName). К публичным полям класса также добавляется префикс m_ (m_pszIndexName).
Префиксы для стандартных типов:
- [unsigned] int: i, u, n
- unsigned char, byte: b
- char: c
- char*, char[] (в смысле строки): sz
- [unsigned] short, word: w
- dword: dw
- qword: qw
- любой указатель: p
Для нестандартных типов, префикс выбирается в соответствии с именем типа. Длина префикса - от одного до двух символов.
Кроме того:
- Публичные имена следует давать осмысленными - из имени должно быть ясно, зачем нужна переменная (функция, ...).
- Предпочтительный диапазон длины имени - от 4 до 20 символов.
- Предпочтительное количество слов, из которых составлено имя - от 1 до 3.
- Имена в объявлении класса не должны содержать имя класса. Например, в объявлении класса CFile не должно быть поля m_dwFileSize; следует использовать имя m_dwSize.
[править] Правила оформления операторов
Для оформления операторов применяются следующие правила:
- Каждому оператору выделяется новая строка.
- Круглые скобки не выделяются пробелами.
- Максимальная длина строки - 80 символов. Если требуется больше, остаток оператора переносится на следующую строку, к нему (остатку) добавляется дополнительный отступ.
- Если тело оператора if или цикла состоит из одного оператора, операторные скобки не ставятся, а оператор записывается с новой строки с дополнительным отступом.
- На использование пробелов ограничений не накладывается.
[править] Запрещенные конструкции
Запрещается использование оператора goto. Единственное исключение - выход из циклов с несколькими уровнями вложенности.
Конструкцию do { ... } while(...); крайне не рекомендуется использовать, особенно если тело цикла больше 10 строк.