Coding Standards

Материал из BrSTU Robotics Wiki
Перейти к: навигация, поиск

Черновик

Стандарты кодирования СНИЛ "Робототехника" - перечень рекомендаций по оформлению кода и документирующих комментариев для программ на С++.

Правила кодирования с использованием Qt

Ниже представлен обзор соглашений по написанию кода с использованием Qt. Эта информация была собрана здесь из разных источников: документации по Qt, тематических форумов, e-mail списков рассылки и опыта различных разработчиков. На основе http://qt-project.org/wiki/Qt_Coding_Style_Russian

Отступы

  • Для обозначения отступа используйте 4 пробела подряд
  • Используйте пробелы, а не табуляцию!

Объявление переменных

  • Объявляйте по одной переменной в строке.
  • Избегайте, если это возможно, коротких и запутанных названий переменных (Например: “a”, “rbarr”, “nughdeget”).
  • Односимвольные имена переменных подходят только для итераторов циклов, небольшого локального контекста и временных переменных. В остальных случаях имя переменной должно отражать ее назначение.
  • Заводите переменные только по мере необходимости.
       // Так не правильно
       int a, b;
       char *c, *d;
  
       // А так - правильно
       int height;
       int width;
       char *nameOfThis;
       char *nameOfThat;
  • Функции и переменные должны именоваться с прописной буквы, а если имя переменной или функции состоит из нескольких слов, то первое слово должно начинаться с прописной буквы, остальные – со строчных.
  • Избегайте аббревиатур
       // Не правильно
       short Cntr;
       char ITEM_DELIM = '\t';
  
       // Правильно
       short counter;
       char itemDelimiter = '\t';
  • Имена классов всегда начинаются с заглавной буквы.

Пробелы

  • Используйте пустые строки для логической группировки операторов, где это возможно.
  • Всегда используйте одну пустую строку в качестве разделителя
  • Всегда используйте один пробел перед фигурной скобкой
       // Не правильно
       if(foo){
       }
  
       // Правильно
       if (foo) {
       }
  • Всегда ставьте один пробел после ‘*’ или ‘&’, если они стоят перед описанием типов. Но никогда не ставьте пробелы после ‘*’ или ‘&’ и именем переменной.
       char *x;
       const QString &myString;
       const char * const y = "hello";
  • Бинарные операции отделяются пробелами с 2-х строн.
  • После преобразования типов не ставьте пробелов.
  • Избегайте преобразования типов в стиле C.
       // Неправильно
       char* blockOfMemory = (char* ) malloc(data.size());
  
       // Правильно
       char *blockOfMemory = reinterpret_cast<char *>(malloc(data.size()));

Фигурные скобки

  • Возьмите за основу расстановку открывающих фигурных скобок на одной строке с выражением, которому они предшествуют
       // Неправильно
       if (codec)
       {
       }
  
       // Правильно
       if (codec) {
       }
  • Исключение: Тело функции и описание класса всегда открывается фигурной скобкой, стоящей на новой строке
       static void foo(int g)
       {
           qDebug("foo: %i", g);
       }
  
       class Moo
       {
       };
  • Используйте фигурные скобки в условиях, если тело условия в размере превышает одну линию, или тело условия достаточное сложное и выделение скобками действительно необходимо
       // Неправильно
       if (address.isEmpty()) {
           return false;
       }
  
       for (int i = 0; i < 10; ++i) {
           qDebug("%i", i);
       }
  
       // Правильно
       if (address.isEmpty())
           return false;
  
       for (int i = 0; i < 10; ++i)
           qDebug("%i", i);
  • Исключение 1: Используйте скобки, если родительское выражение состоит из нескольких строк / оберток
       // Правильно
       if (address.isEmpty() || !isValid()
           || !codec) {
           return false;
       }
  • Исключение 2: Используйте фигурные скобки, когда тела ветвлений if-then-else занимают несколько строчек
       // Неправильно
       if (address.isEmpty())
           return false;
       else {
           qDebug("%s", qPrintable(address));
           ++it;
       }
  
       // Правильно
       if (address.isEmpty()) {
           return false;
       } else {
           qDebug("%s", qPrintable(address));
           ++it;
       }
  
       // Неправильно
       if (a)
           if (b)
               ...
           else
               ...
  
       // Правильно
       if (a) {
           if (b)
               ...
           else
               ...
       }
  • Используйте фигурные скобки для обозначения пустого тела условия
       // Неправильно
       while (a);
  
       // Правильно
       while (a) {}

Круглые скобки

  • Используйте круглые скобки для группировки выражений:
       // Неправильно
       if (a && b || c)
  
       // Правильно
       if ((a && b) || c)
  
       // Неправильно
       a + b & c
  
       // Правильно
       (a + b) & c

Использование конструкции switch

  • Операторы case должны быть в одном столбце со switch
  • Каждый оператор case должен иметь закрывающий break (или return) или комментарий, которой предполагает намеренное отсутствие break & return.
       switch (myEnum) {
       case Value1:
           doSomething();
           break;
       case Value2:
           doSomethingElse();
           // проходим дальше
       default:
           defaultHandling();
           break;
       }

Разрыв строк

  • Длина строки кода не должна превышать 80 символов. Если надо – используйте разрыв строки.
  • Запятые помещаются в конец разорванной линии; операторы помещаются в начало новой строки. В зависимости от используемой вами IDE, оператор на конце разорванной строки можно проглядеть.
       // Правильно
       if (longExpression
           + otherLongExpression
           + otherOtherLongExpression) {
       }
  
       // Неправильно
       if (longExpression +
           otherLongExpression +
           otherOtherLongExpression) {
       }

Наследование и ключево слово virtual

  • При переопределении virtual-метода, не помещайте слово virtual в заголовочный файл.

Как использовать Doxygen

Doxygen – мощное средство документирования кода. Ведь гораздо удобнее, когда комментарии к коду лежат рядом с кодом – когда меняется код, с гораздо большей вероятностью комментарий тоже поменяется, если будет на виду во время изменения.

Doxygen позволяет из обычных сишных комментариев, записанных в специальном формате, генерировать документы chm (как вариант – HTML, LaTeX, rtf, pdf) с ссылками, диаграммами классов и прочими удобными наворотами.

За основу этого описания взят файл отсюда http://courses.graphicon.ru/files/courses/cg/2008/prac/doxygen.pdf

Как этим пользоваться

В коде

Комментарий в специальном формате. Существуют три варианта

       /**
         комментарий
       */ 

либо

      /// комментарий либо
      //! комментарий

Все, что написано внутри комментариев, оформленных таким образом, выносится в chm. Для единообразия лучше использовать /// для коротких комментариев и /** */ для длинных Кроме этого, есть некоторое количество служебных слов (они начинаются с символа @: @main, @code и др.), которые задают правила отображения документации (выделение в отдельный раздел, специальное форматирование и шрифт для выделения примера кода, вынесение текста на заглавную страницу и т.п.)

Qt Creator умеет генерировать комментарии Doxygen автоматически. Если перед конструкцией языка, которую вы хотите задокументировать набрать /** и нажать Ввод, то будет сформирован полный комментарий для всей конструкции.

Как сгенерировать html

Вы только что создали файл с документацией.

Создание файла настроек

Когда вы только создали файл с документацией, надо создать файл – хранилище настроек. Для этого

  • либо скопировать из уже существующего
  • либо в командной строке: doxygen –g генерируется файл под названием Doxyfile (без расширения, текстовый, читать и редактировать можно в Far Manager либо Total Commander по кнопочке F4). В этом файле хранятся опции – можно настроить имя chm-файла, папку куда будет складываться документация, генерацию документации в формат LaTeX и кучу всего другого. Этот файл можно редактировать руками либо специальной утилитой doxywizard.

Редактирование Doxyfile

Если надо, отредактировать Doxyfile

  • либо F4
  • либо утилитой с графическим интерфейсом – для этого в командной строке
       doxywizard Doxyfile

Генерация документации

После этого запустить создание документации

  • либо из командной строки командой:
       doxygen
  • либо утилитой с графическим интерфейсом по кнопочке, похожей на шестеренку – для этого в командной строке
       doxywizard Doxyfile

Вы хотите обновить документацию для файла, у которого она уже есть, но устарела. В командной строке (в том каталоге, где лежит Doxyfile):

       doxygen

Замечания по оформлению документации

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

Документирование классов

   /**
   @class MyClass
   Тестовый класс для примера документирования кода. Ничего особенного не
   умеет, содержит конструктор, один член данных и один метод. Ваши классы
   следует документировать подобным образом.
   */
   class MyClass : public OurClass
   {
   public:
      /// Конструктор по умолчанию MyClass();
       /// Метод, делающий что-то. Он делает это таким-то образом.
       /// @param in_iParameter1 – параметр, отвечающий за что-то
       /// @param out_sParameter2 - параметр, отвечающий за что-то еще
       /// @return true если все хорошо, false если все плохо
       bool DoSmthng(int in_iParameter1, std::string out_sParameter2);
   private:
       /// этот член хранит в себе какую-то информацию 
       int m_iParameter1;
       /// этот член тоже хранит в себе какую-то информацию 
       std::string m_sParameter2; 
   };

Документирование функций

   /**
   @function MyFunction
   Тестовая функция для примера документирования кода. Ничего особенного не
   умеет, имеет два входных параметра. Ваши функции следует документировать
   подобным образом.

   @param in_iParameter1 – параметр, отвечающий за что-то
   @param out_sParameter2 - параметр, отвечающий за что-то еще
   @return true если все хорошо, false если все плохо
   */
   bool MyFunction (int in_iParameter1, std::string out_sParameter2);

Документирование модулей

В любом месте кода

   /**
   @mainpage Этот модуль следует использовать следующим образом: сначала его нужно собирать в VisualStudio 6.0, а потом полученный dll 
   скопировать из Bin/BCB/ в папку с .exe
   */

Разные штуки

  • Текст на главной странице - @mainpage
  • Создание новой страницы - @page идентификатор название

Например @page pagereq Требования к системе

  • Создание секции - @section идентификатор название

Например @section common Общие требования

  • Вставка примера кода - @code

Этот тэг парный, его закрывает @endcode

  • Краткое описание - @brief

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

  • Подробное описание - @full
  • Автор - @author
  • Описание к файлу – @file
  • Предупреждение - @warning
  • Заметка - @note
  • Именованная группа - @name имя

После этого группа в скобках @{ … @} Например, таким образом можно группировать методы класса:

   /**
   @class MyClass 
   */
   class MyClass : public OurClass 
   { 
   public:
       /// @name Конструктор/Деструктор
       /// @{
       MyClass();
       virual ~MyClass();
       /// @}
       /// @name Установка параметров
       /// @{
       /// Установливает параметр1
       SetParameter1(int);
       /// Возвращает параметр1
       int GetParameter1();
       /// @}
       /// Делает еще что-то void DoSmthng();
   private:

       /// этот член хранит в себе какую-то информацию 
       int m_iParameter1; 
   };

Главное исключение

  • Не бойтесь нарушать описанные выше правила, если вам кажется, что они только запутают ваш код.