Правила оформлення коду

Зміст

На цій сторінці описано правила оформлення коду для бібліотек та прикладних програм проекту Deeptown. Дотримання цих правил не менш важливе, ніж якість коду: це підвищує читання коду іншими людьми. Недотримання цих правил може стати причиною відмови у прийнятті коду.

Звичайно, з будь-яких правил є винятки, і ніхто не вимагає дотримуватися цих правил до літери. Але практика показує, що код, оформлений у єдиному стилі, легше читається та розуміється людьми, зайнятими у проекті. На відміну від багатьох інших проектів, наші правила – не дуже суворі, і в них позначені лише базові речі.

У першому розділі наведено загальні правила для всіх мов програмування та розмітки; у наступних розділах вони конкретизуються для різних мов.

Загальні правила

Мова та кодування

Для міжнародних знаків у проекті вживається кодування UTF-8. Ви можете використовувати рядки українською та іншими мовами прямо у коді програм – для цього потрібно зберегти вихідний код програми у кодуванні UTF-8. Але пам'ятайте, що це поганий стиль: у хорошій програмі, всі міжнародні повідомлення перебувають у файлах даних.

Підхід до написання коду

Найголовніше правило: код має бути легкочитаний і красивий.

Диптаун - це дуже великий проект, що складається з багатьох модулів. Ці модулі зав'язані один на одного, і правильне функціонування одних неможливе без інших. Тому ми не приймаємо write-only код.

Для того, щоб код виходив красивим, перш за все потрібний творчий підхід до його написання. Тому ми не наводимо жодних формальних правил щодо цього питання. Спірні ситуації вирішуватимуться у дискусіях.

Коментарі

Зазвичай для виконання цієї умовидостатньо написати невеликі пояснення до кожного класу та методу у цьому класі.

Коментарі повинні пояснювати, як працює код, але не що він робить. Відповідь на друге питання має утримуватися в документації, а не в коді; ми не використовуємо в проекті системи на кшталт doxygen для створення документації з коду, оскільки переконані, що документація в коді захаращує цей код і робить його важко прочитаним.

Коментар на початку файлу

На початку кожного вихідного файлу має бути така інформація:

Відступи у коді

Використання операторних дужок

Всі операторні дужки ставляться на новому рядку; до коду, укладеного в операторні дужки, додається один відступ. Код починається з наступного після рядка, що відкриває дужки. Виняток робиться для конструкцій, де тіло операторних дужок складається з не більше 10 рядків. У цьому випадку допускається відкриваючу операторну дужку поставити на той же рядок, що і оператор, що її "породив":

Крім того, спеціальний виняток робиться для конструкції if. else:

Виняток також застосовується тільки для не надто довгих конструкцій.

Правила для K++ коду

Правила іменування

(Жирним відзначені обов'язкові правила, інші - бажані, але не обов'язкові).

  1. Модулі називаються в стилі MyModuleName;
  2. Імена файлів точно збігаються з іменами модулів. Наприклад, модуль Proto::HTTP повинен бути у файлі Proto/HTTP.kpp;
  3. Класи іменуються в стилі MyClassName, без префіксів;
  4. Публічні методи та властивості іменуються в стилі someMethodName;
  5. Аргументи функцій іменуються в стилі argument_name;
  6. Усі публічні імена повинні бути розмовляючими, бажано безскорочень, але при цьому не надто довгими. Зразкове обмеження за довжиною імені – 20 символів;
  7. Приватні способи та якості називаються аналогічно громадським;
  8. Локальні змінні іменуються в стилі variable_name (всі літери - малі, символи підкреслення між словами);
  9. Поля класу називаються аналогічно локальним змінним, але з префіксомm_.

Такий підхід до найменування має безліч плюсів. У ньому практично не використовуються префікси (які зазвичай набридають), але при цьому стиль написання імен класів, методів та змінних відрізняється, що полегшує читання коду.

Зверніть увагу, що ми вимагаємо виконання правил щодо імені публічних елементів модуля, але за іменами "внутрішньої кухні" даємо лише рекомендації. Це зроблено задля забезпечення однаковості інтерфейсів.

Правила для C++ коду

Цей розділ скопійовано із стандарту коду самого Диптауна. Можливо, деяким не сподобається такий стиль, але так історично склалося. Якщо заперечень буде надто багато – ми напишемо скрипт, який сконвертує один стиль в інший. Але робитимемо це централізовано. Зараз у проекті прийнято такий стиль, і холівари з цього приводу дуже небажані.

Перенесення коду

Весь код проекту повинен компілюватися, збиратися і працювати на будь-якій системі, будь то Windows, Mac, UNIX, Solaris та інші. Використання бібліотек також обмежено лише ліцензійними угодами та переносимістю їх на інші системи. У деяких випадках допускаються винятки: код може бути написаний у кількох варіантах різних систем. Але зрештою, має бути можливість складання коду на будь-якій системі.

Схеми розіменування

Далі по тексту використовуються такі визначення для різних іменоб'єктів:

  • довільна- об'єкт може бути названий довільно.
  • велика злитна- об'єкт повинен бути названий великими літерами, слова не повинні відокремлюватися один від одного. Наприклад, OBJECTNAME.
  • велика [роздільна]- об'єкт повинен бути названий великими літерами, слова відокремлюються один від одного знаком підкреслення: OBJECT_NAME.
  • рядкова злитна,рядкова [роздільна]- аналогічно: objectname і object_name відповідно.
  • основна- назва повинна починатися з великої літери, і кожне слово має починатися з великої літери. Інші літери - малі: ObjectName.

Файлова структура верхнього рівня

Весь код проекту є дерево підпроектів. Кожен підпроект - це логічно завершений модуль, який може сам складатися з підпроектів; або компілюватися у програму, статичну чи динамічну бібліотеку чи скрипт; або, нарешті, містити у собі і те, й інше. Підпроекти називаються за рядковою (іноді роздільною) схемою іменування і розташовуються в каталогах, що відповідають їх іменам.

Таким чином, за кожним підпроектом закріплюється його унікальний ідентифікатор – це шлях до підпроекту щодо кореневого каталогу проекту.

Розіменування файлів

Усі файли модуля мають бути названі за рядковою схемою іменування. Виняток становлять лише вихідні файли, у яких перебувають реалізації деяких класах - вони точно відповідають іменам класів. Про це буде сказано далі.

Розбиття файлів за каталогами

Усі файли модуля розбиваються за каталогами так:

  • всі публічні файли, що включаються, повинні знаходитися в кореневому каталозі модуля;
  • Усевнутрішні файли, що включаються, повинні знаходитися в підкаталозіimpl;
  • усі вихідні файли повинні знаходитись у каталозіsource.

Розбиття функцій та класів за файлами

Усередині кожного модуля або його частини, функції та класи розбиваються на внутрішні - використовувані лише даним модулем, та публічні - експортовані модулем для "зовнішнього світу".

Усі публічні функції та класи мають бути винесені в один або кілька заголовних файлів. На розбиття файлів обмежень не накладається.

Внутрішні функції та класи не повинні бути оголошені в публічних заголовних файлах, і жодним чином не повинні бути доступні для зовнішнього світу.

Реалізація кожного класу має бути винесена до окремого вихідного файлу, ім'я якого збігається з ім'ям класу.

На розбиття реалізацій окремих функцій файлів обмежень не накладається.

Простір імен

Вартові включення

Усі файли заголовків мають бути захищені вартовим включення. Ім'я вартового включення дається наступному шаблону: __PRFX_FILENAME_H_INCLUDED.

Тут PRFX - префікс модуля та його частини (див. п. 4.1), FILENAME - ім'я заголовного файлу, записане великими літерами.

Правила іменування сутностей

Застосовуються такі правила розіменування:

  • Визначення препроцесора називаються за великою схемою. Крім того, для всіх визначень препроцесора ставиться два префікси. Перший відповідає модулю та його частини (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

Для нестандартних типів префікс вибирається відповідно до імені типу. Довжина префікса – від одного до двох символів.

Правила оформлення операторів

Для оформлення операторів застосовуються такі правила:

  1. Кожному оператору виділяється новий рядок.
  2. Круглі дужки не виділяються пробілами.
  3. Максимальна довжина рядка – 80 символів. Якщо потрібно більше, залишок оператора переноситься на наступний рядок, до нього (залишку) додається додатковий відступ.
  4. Якщо тіло оператора if або циклу складається з одного оператора, операторні дужки не ставляться, а оператор записується з нового рядка з додатковим відступом.
  5. На використання прогалин обмежень не накладається.

Заборонені конструкції

Забороняється користуватися оператором goto. Єдиний виняток - вихід із циклів з кількома рівнямивкладеності.

Конструкцію do < . >while(. ); украй не рекомендується використовувати, особливо якщо тіло циклу більше 10 рядків.