Skip to content
anlun edited this page Nov 18, 2012 · 5 revisions

1. Вступление

Данный документ определяет набор правил и рекомендаций для того, чтобы:

  • Сделать программы более читабельными и удобными для понимания.
  • Определить некий единый стиль оформления кода, которому будут следовать все исходники.
  • Избежать некоторых типичных ошибок.

Документ содержит только правила, касающиеся форматирования кода и использования некоторых синтаксических конструкций. Вопросы архитектуры или технологии (например, как разрабатывать иерархию наследования или писать юнит-тесты) здесь не рассматриваются.

Некоторые из описанных далее правил обязательны, и им должны следовать все разработчики, некоторые правила несущественны для читабельности или имеют распространённые альтернативы, но зафиксированы в целях единообразия. Для того, чтобы не было религиозных войн, мы фиксируем одну из возможных альтернатив и придерживаемся её по всему проекту.

Если что-то не описано этом документе, то ориентироваться на http://www.python.org/dev/peps/pep-0008/. И да, используется python 2.x.

2. Настройка средств для работы с системой контроля версий

В данный момент в проекте используется система контроля версий git. Для того, чтобы исходные тексты находились в согласованном состоянии и не менялись раз за разом лишь из-за настроек, различающихся у разных участников проекта, вводятся следующие правила.

  1. Для работы под Windows настройка core.autocrlf должна быть выставлена в true, а core.safecrlf должна быть выставлена в false. Для Linux-систем — core.autocrlf нужно установить в input, core.safecrlf в true. Подробнее про autocrlf, например, тут.

  2. Значения user.name и user.email должны быть корректно заполнены, информация должна совпадать с соответствующими полями на гитхабе. Избегайте в значении name символов <, > или @.

3. Оформление исходников

  1. Официальный язык проекта - английский, комментарии в коде должны писаться по-английски в кодировке us-ascii. В коде могут встречаться комментарии на русском, в кодировке UTF-8 (без BOM), их надлежит по возможности переводить.

  2. Здесь место для обсуждения Мы используем символ табуляции, а не пробелы. В некоторых редакторах есть опция "заменять символы пробелов на табуляцию", её полезно держать включённой. Также имеет смысл включить явное отображение символов табуляции и пробелов, если редактор это поддерживает. Участники проекта используют разные настройки табуляции в своих редакторах, нельзя надеяться, что она 4 или 8 пробелов.

  3. Длина строки не должна быть больше 120 символов. Некоторые редакторы умеют отображать "правое поле", эту опцию полезно включить.

  4. В каждом файле должно быть прописано

# -*- coding:utf-8 -*-
__author__ = 'имя_создателя'
  1. Запятые в конце строк должны переноситься на следующую строку. Например, следует писать не
void f(int a,
    int b);

а

void f(int a
    , int b);

4. Соглашения об именовании

  1. Все имена должны соответствовать принципам самодокументированного кода (подробнее см. ниже).

  2. Не используйте распространённые, системные и т.д. имена, например std, boost, CONST.

  3. Имена файлов должны быть оформлены в таком стиле: realRepoClient.py, entity.py. Такие же правила действуют для имён папок.

  4. Все классы должны начинаться с заглавной буквы, например Node, SqlNode.

  5. Имена локальных переменных должны быть оформлены так: var, my_variable, sql_connection. Не используйте имена локальных переменных, похожие на имена полей классов.

  6. Все private-поля классов должны иметь префикс __, например __field. Public-поля классов должны именоваться как локальные переменные, т.е. field, my_field.

  7. Константы должны именоваться как переменные, т.е., например, my_const.

  8. Методы и функции должны быть оформлены так: my_method(...), connect_sql(). Функции, возвращающие булево значение, должны иметь префикс is или has, например is_open(). Другие имена функций должны быть глаголами, описывающими, что делает функция. Не называйте функцию generator(), лучше generate().

  9. Геттеры/сеттеры должны называться в стиле property()/set_property(...) соответственно.

5. Документирование

  1. «The main contributor to code-level documentation isn't comments, but good programming style. Style includes good program structure, use of straightforward and easily understandable approaches, good variable names, good routine names, use of named constants instead of literals, clear layout, and minimization of control-flow and data-structure complexity» (c) Steve McConnell. Надо писать не хорошо документированный код, а хороший код, понятный сам по себе.

  2. Информацию о программе лучше выражать средствами языка, прибегая к комментариям только тогда, когда синтаксиса не хватает. Комментарии должны говорить о коде только то, что он не может сказать о себе сам.

  3. Вообще, чтение комментариев тоже занимает некоторое время, поэтому комментарии должны добавляться только тогда, когда это стоит того. Бессмысленные, очевидные и неправильные комментарии писать нельзя.

  4. Не надо писать комментарий к изменению в коде прямо в исходнике - для этого есть комментарий к коммиту в систему контроля версий. Любой коммит должен сопровождаться комментарием. Если коммит исправляет какой-то баг, о номере бага должно быть упомянуто. Желательно описывать причины изменений и ссылаться на источники дополнительной информации по данному изменению, если таковые есть. Не надо писать, что изменилось, надо писать зачем.

  5. Быстрые фиксы, которые плохо укладываются в основной алгоритм, должны быть комментированы в коде - почему нельзя сделать нормально, и в чём идея быстрого фикса.

  6. Комментарии относятся к коду под ними или слева от них. Желательно не писать комментарии на одной строчке с кодом.

  7. Лучше использовать комментарии вида '//', даже для многострочных комментариев. Комментарии '/* */' используются для того, чтобы быстро закомментировать куски кода. Нежелательно для этих целей использовать #ifdef 0.

  8. Если назначение класса, метода, функции, параметра не ясно из объявления, он должен быть комментирован. Желательно комментировать специальные значения параметров, если есть. Напомним, что осмысленные имена лучше комментариев.

  9. Выглядеть комментарии должны примерно так:

// Some comment
class CaretEmul  
{
public:
    CaretEmul();
    ~CaretEmul();

    // Window should be initialized by caller before calling this method
    HRESULT attachToEditWindow(HWND editWindow, bool enable = true);

    HRESULT detach();
  1. Текст комментария должен быть отделён от '//' как минимум одним пробелом. Комментарий должен быть отделён от кода минимум двумя пробелами, но лучше не писать комментарий на одной строчке с кодом.

6. Форматирование элементов синтаксиса

Далее и методы, и функции называем просто функциями.

6.1. Функции

  1. Тела функций должны быть по возможности короткими. Весьма желательно видеть функцию целиком на экране, т.е. 30-40 строк должны быть верхним пределом её размеров.

  2. Одна функция должна решать одну задачу. Если функция делает что-то и что-то ещё, надо сделать две функции.

  3. Сложные булевы выражения или код инициализации должны быть вынесены в отдельную функцию.

  4. Не должно быть много уровней вложенности. Если уровней вложенности больше 3, стоит подумать о выделении кода в отдельную функцию.

  5. Функции не должны иметь много параметров, как правило, не более 7. Если требуется больше, это знак того, что что-то не так.

6.2. Классы

  1. Если это требуется, надо писать комментарии, особое внимание должно уделяться public-полям и методам.

  2. Объявление метода должно оформляться так:

// Alternative 1
def some_function(x, y)

// Alternative 2
def any_function(
    x
    , y
    , my_window_subclass
    , my_other_window_subclass
)

6.3 Операторы

  1. Каждый оператор должен быть на своей строке.

  2. Вызов функции должен быть оформлен так:

result = someClass.some_method(some_parameter, MAX_LEN);

или

result = someClass.some_method(
    x_position
    , y_position
    , my_window_subclass
    , my_other_window_subclass
);   

7. Общие рекомендации

  1. Всё, что может быть переиспользовано, должно быть переиспользовано.

  2. Отладочный вывод в транке должен присутствовать только в особо важных местах (например, в конструкторах исключений). В бранчах отладочный вывод можно использовать без ограничений, локально тоже, но при коммите в транк или мердже отладочный вывод следует убирать.

7.1. Объявления переменных и полей

  1. Область видимости переменных должна быть как можно более узкой.

8. Использование системы документирования Doxygen

  1. Использование системы основано на применении в исходном тексте программы на С++ специального вида комментариев. Практически любой элемент программы (класс, функция, переменная) может быть задокументирован в системе Doxygen.

  2. Каждый .h или .cpp-файл должен быть описан в основной ветке. При добавлении новой функциональности комментировать вновь добавляемый код обязательно при перекладывании в основную ветку. В своих репозиториях допустимо не комментировать код, если это замедляет разработку.

  3. Предпочтительно анонимное описание сущности в виде

/// Description

Описание такого рода по умолчанию относятся к сущности, следующей сразу после такого комментария. Допускаются и полные описания, с указанием имени сущности.

  1. Объявление функции или метода класса предпочтительнее описывать так:
/// Function description
/// @param arg1 Parameter 1 description
/// @param arg2 Parameter 2 description
/// @param arg3 Parameter 3 description
/// @return Return value description
int someFunction(int arg1, arg2, arg3);

Формат описания аргументов функций применим и для описания элементов перечислений.

  1. Не надо описывать переопределённые унаследованные методы, если они описаны в классе предке и их семантика не изменилась. Документация из класса-предка скопируется при генерации документации автоматически.

На основе стайлгайда github.com/qreal/qreal