Стандарт оформления кода — различия между версиями

Материал из SkyXEngine wiki
Перейти к: навигация, поиск
м
м
Строка 4: Строка 4:
 
*исходный код движка,
 
*исходный код движка,
 
*шейдеры.
 
*шейдеры.
 
  
 
== Общее правило именования ==
 
== Общее правило именования ==
Строка 10: Строка 9:
  
 
К примеру, класс CManagerTimes использует большое количество счетчиков времени (но кроме временных данных есть и другие). В этом случае логично предположить что «время» является ключевым фактором в именовании, значит, слово time будет наиболее приоритетным словом, и претендует на начало в имени, также многие параметры связаны со «скоростью» течения времени, но «скорость» описывает течение времени, значит «скорость» будет вторым по значимости словом, в итоге имя переменной будет: m_iTimeSpeed
 
К примеру, класс CManagerTimes использует большое количество счетчиков времени (но кроме временных данных есть и другие). В этом случае логично предположить что «время» является ключевым фактором в именовании, значит, слово time будет наиболее приоритетным словом, и претендует на начало в имени, также многие параметры связаны со «скоростью» течения времени, но «скорость» описывает течение времени, значит «скорость» будет вторым по значимости словом, в итоге имя переменной будет: m_iTimeSpeed
 
  
 
== Имена в коде ==
 
== Имена в коде ==
Строка 155: Строка 153:
 
};
 
};
 
</syntaxhighlight>
 
</syntaxhighlight>
 
  
 
Если определение дефайна должно вставляться в выражения, то оно должно оборачиваться в скобки:
 
Если определение дефайна должно вставляться в выражения, то оно должно оборачиваться в скобки:
Строка 161: Строка 158:
 
иначе если определение дефайна является конечной инструкцией, оно должно быть обернуто в фигурные скобки:
 
иначе если определение дефайна является конечной инструкцией, оно должно быть обернуто в фигурные скобки:
 
<syntaxhighlight lang="C++">#define PRINT(str) {printf(str);}</syntaxhighlight>
 
<syntaxhighlight lang="C++">#define PRINT(str) {printf(str);}</syntaxhighlight>
 
  
 
Настоятельно рекомендуется использование симметричных имен:
 
Настоятельно рекомендуется использование симметричных имен:
Строка 180: Строка 176:
 
*show/hide,  
 
*show/hide,  
 
*suspend/resume
 
*suspend/resume
 
  
 
== Блоки, операции, отступы ==
 
== Блоки, операции, отступы ==
Строка 211: Строка 206:
 
*(obj->GetPoint())
 
*(obj->GetPoint())
 
</syntaxhighlight>
 
</syntaxhighlight>
 
  
 
'''При вызове функции''' после имени функции сразу идет открывающая скобка.
 
'''При вызове функции''' после имени функции сразу идет открывающая скобка.
Строка 220: Строка 214:
  
 
'''Приведение типов неявное''', если не требуется сделать это явно, либо потеря точности недопустима.
 
'''Приведение типов неявное''', если не требуется сделать это явно, либо потеря точности недопустима.
 
  
 
== Файлы исходного кода ==
 
== Файлы исходного кода ==
Строка 239: Строка 232:
  
 
Не рекомендуется переменные класса предоставлять в public.
 
Не рекомендуется переменные класса предоставлять в public.
 
  
 
'''Использование goto не рекомендуется'''.
 
'''Использование goto не рекомендуется'''.

Версия 13:14, 22 июля 2018

Стандарт оформления кода (code style) — это набор определенных правил при написании исходного кода, на определенном языке программирования.

Данный стандарт распространяется на:

  • исходный код движка,
  • шейдеры.

Общее правило именования

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

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

Имена в коде

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

Таблица префиксов
Префикс Значения Тип
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 используется для переменной указателя который ссылается на функцию.

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

Имена типов/классов/структур, должны быть обязательно написаны в смешанном регистре, начиная с верхнего: CPoint, CCamera

Настоятельно рекомендуется не использовать префиксы имени проекта в именах типов/классов/структур, для их безотносительной идентификации.

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

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

get/set должны быть использованы везде, где осуществляется прямой доступ к атрибуту.

Имена типов в шаблонах должны формироваться следующим образом: первое основное можно называть T, остальные осмысленные имена большими буквами с подчеркиванием

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

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

  • _out – выходной, будет произведена запись
  • _in – входящий, без записи
  • _opt - опциональный, значение может быть недействительным (к примеру вместо указателей можно отправить 0)

Для представления массивов (наборов/коллекций) следует использовать множественное число объектов:

vector<Point>  aPoints;

Переменным-итераторам следует давать имена i, j, k, для каждого цикла можно создавать дополнительную переменную il jl kl сохраняя длину массива, чтобы не вычислять каждый раз

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

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);}

Настоятельно рекомендуется использование симметричных имен:

  • 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

Блоки, операции, отступы

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

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

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

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

a + b

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

-2

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

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

int *a;
int &a;

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

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

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

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

Инициализация переменной всегда должны быть соответствующим типом, к примеру: float fNum = 1.0f; а не 1.0

Приведение типов неявное, если не требуется сделать это явно, либо потеря точности недопустима.

Файлы исходного кода

Имена файлов рекомендуется писать относительно предметной области, без дополнительных префиксов проекта. Префиксы имени проекта необходимы для библиотек, h и cpp файлов прослоек библиотек (для предоставления функций по управлению функционалом библиотеки), файлов с main функцией, для четкой их идентификации и соотношения с проектом. Если в файле (cpp/h) описание одного класса - то файл называется как класс с точностью до регистра букв, если более одного класса, или не классы вовсе – то в соответствии со смыслом предоставляемого функционала. Рекомендуется в h файлах только заголовки, в cpp реализация. Заголовочные файлы должны содержать защиту от вложенного включения:

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

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

Прочее

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

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

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

using namespace недопустимо.

Исключения из правил

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