Стандарт оформления кода который мы приняли


Notice: Функция get_currentuserinfo с версии 4.5.0 считается устаревшей! Используйте wp_get_current_user(). in /hlds/web/u138079p19/code4life.ru/htdocs/wp-includes/functions.php on line 3840

Буквально перед началом разработки s4g 0.9.2 мы приняли стандарт оформления кода. И в данной статье я хотел бы рассказать о нем.

Статья о стандарте оформления кода.

На поиски и анализ информации ушло около двух дней, на систематизацию анализов и составление нашего стандарта ушел целый день, хорошо что мы уже знали что нам надо, итого 3 мучительных дня составления пары страниц Word документа))

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

Долго изучая и анализируя в интернетах таблицы с префиксами и адаптируя к нашим условиям, решили:

Префикс Значения Тип
g_ префикс для глобальной переменной
m_ префикс для переменной класса
c_ константа (префикс для типа)
s строка объекты типа string
sz строка, ограниченная нулевым символом char []
ch символ char
i целочисленное значение int
i8 int8_t
i16 int16_t
i32 int32_t
ui unsigned int
ui8 uint8_t
ui16 uint16_t
ui32 uint32_t
dw DWORD
w WORD
b, is, can, has, should is – является ли, can – может ли, has – имеет ли, should – должен ли bool
l long
ul unsigned long
a массив array
v вектор
id идентификатор int32_t
p указатель *
o объект, экземпляр класса (не указатель)
I интерфейс
C класс class
t время
dt дата (и время)
r ссылка &
fn переменная-функция

Префикс fn используется для переменной указателя который ссылается на функцию.

Дальше был вопрос о иерархии именования внутри одной переменной, как ее именовать? time delta или delta time? Принято time delta но если у нас не только delta времени, и есть еще множество delta, как быть? Этот вопрос начал приобретать свою актуальность начиная с момента выпуска SkyXEngine 0.9.0. В итоге долгих раздумий решили:

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

К примеру, класс CManagerTimes использует большое количество счетчиков времени (но кроме временных данных есть и другие). В этом случае логично предположить что «время» является ключевым фактором в именовании, значит, слово time будет наиболее приоритетным словом, и претендует на начало в имени, также многие параметры связаны со «скоростью» течения времени, но «скорость» описывает течение времени, значит «скорость» будет вторым по значимости словом, в итоге имя переменной будет: m_iTimeSpeed

Затем внезапно вспомнил про то что bool может нести как истинный isTrue смысл так и сложный isFalse, и решили:

В именах переменных типа bool недопустимо использование отрицания

А как же быть с префиксами свойственными для проекта? Мы долго над этим думали, в итоге для движка решили не делать префиксов, потому что он огромен, а вот язык не такой большой поэтому можно. Было много сомнений … в итоге решили что префикс для функций и типов будет иметь вид: s4g_Func и s4g_Type, а для дефайнов не мудрено сделать вот так: S4G_

С аббревиатурами тоже пришлось повозится, но более лучшего варианта мы не нашли:

Аббревиатуры в именах должны быть написаны в верхнем регистре, до и после должны быть буквы в нижнем регистра для явного выделения аббревиатуры: exportHTMLsource()

Большое наличие классов и глобальных функций требовали жесткого разграничения, в итоге:

Имена методов классов должны начинаться с нижнего регистра: getSpeedWalk

Имена функций должны начинаться с верхнего регистра.

Также для функций желательна симметричность:

  • get/set,
  • add/remove,
  • create/destroy,
  • start/stop,
  • insert/delete,
  • increment/decrement,
  • old/new,
  • begin/end,
  • first/last,
  • up/down,
  • min/max,
  • next/previous,
  • old/new,
  • open/close,
  • show/hide,
  • suspend/resume, и т. д.

Сразу же четко дифференцировали разделы класса:

Разделы класса public, protected и private должны быть отсортированы. Все разделы должны быть явно указаны. Сначала раздел public, затем protected/private.

Не рекомендуется переменные класса предоставлять в public.

С пространствами имен и дефайнами решили не выдумывать:

Имена пространств имён следует записывать в нижнем регистре.

namespace gdata
{};

Дефайны и перечисления должны быть написаны только в верхнем регистре с использованием нижнего пробела: OBJ_MAX_LEN

Константы в перечислениях должны иметь префикс — общее имя типа, при этом название перечисления должно совпадать с префиксом:

enum COLOR {
COLOR_RED,
COLOR_GREEN,
COLOR_BLUE
};

Если определение дефайна должно вставляться в выражения, то оно должно оборачиваться в скобки:

#define A_ADD_B(a, b) (a + b)

иначе если определение дефайна является конечной инструкцией, оно должно быть обернуто в фигурные скобки:

#define PRINT(str) {printf(str);}

По поводу блоков (логических и синтаксических):

Логические блоки в коде следует отделять пустой строкой

Отступы в блоках {} равны одному значению табуляции (4 пробела), дополнительные отступы в блоках категорически запрещены.

Каждый символ открытия { и закрытия } блока должен быть расположен на новой строке

Горизонтальные отступы:

Бинарные операторы окружаются двумя пробелами:

a + b

Унарные операторы пишутся без пробелов:

int a = -2;

Указатели и ссылки должны быть привязаны только к переменным:

int *a;
int &a;

При вызове функции после имени функции сразу идет открывающая скобка.

После запятых, точек с запятой ставится пробел, в других случаях они не ставятся

Скобки не обошли стороной:

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

Операции разыменования и взятие адреса должны оборачивать в скобки выражение:

&(aArr[0])
*(obj->GetPoint())

С именами файлов тоже были вопросы, но решили вот так:

Имена файлов рекомендуется писать относительно предметной области, без дополнительных префиксов проекта. Префиксы имени проекта необходимы для библиотек, h и cpp файлов прослоек библиотек (для предоставления функций по управлению функционалом библиотеки), файлов с main функцией, для четкой их идентификации и соотношения с проектом.

Если в файле (cpp/h) описание одного класса — то файл называется как класс с точностью до регистра букв, если более одного класса, или не классы вовсе – то в соответствии со смыслом предоставляемого функционала.

Рекомендуется в h файлах только заголовки, в cpp реализация.

Заголовочные файлы должны содержать защиту от вложенного включения:

#idndef __ИМЯ_ФАЙЛА_H
#define __ИМЯ_ФАЙЛА_H

Директивы включения (#include) должны располагаться только в начале файла.

Запретили только using namespace, а goto порекомендовали друг другу не использовать))

Однако, исключения из правил именования тоже нашлось:

типы данных которым префикс класса не применим, к примеру float3, Quaternion, matrix

дефайны, использование которых достаточно частое и необходимо максимально облегчить их запоминанием и написание, к примеру: mem_delete, mem_delete_a, mem_release

Данный стандарт оформления кода опробовали на s4g и SkyXEngine, нам нравится, код стал намного привлекательнее, теперь будем пробовать на движке))

Поделиться:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*