CodeRules_M102
.pdfM102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 1 из 23 |
Правила кодирования
неООП (часть 1)
Введение
Область действия правил ограничена курсом.
Любая система лучше, чем бессистемное и разнородное.
Общие принципы
1. Каждое нарушение правила должно быть аргументировано и задокументировано.
Исходные тексты
2.Запрещается использовать спецсимволы (табуляции, разрыв страницы) в исходных текстах.
3.Длина строки исходного файла ограничена 80 символами. Используйте разрывы строк для
более длинных строк.
Основание: реализация ограничения на длину строки происходит либо отбрасывание, либо переносом конца, при этом исходный текст становится трудным для восприятия. Отсутствие ограничения на длину строки у других разработчиков гарантировать невозможно. 80 является общепризнанным соглашением о количестве символов в строке редакторов, эмуляторов терминалов (консолей), принтеров и отладчиков.
4.Делайте очевидным и хорошо заметным в коде разрыв строки. Выравнивайте новую строку в соответствии с предыдущей строкой.
ПРИМЕР
totalSum = a + b + c + d + e;
function (param1, param2, param3);
setText ("Long line split" "into two parts.");
for (int tableNo(0); tableNo < nTables; tableNo += tableStep)
{
}
unsigned char searchTable[] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x1, 0x02, 0x01, 0x02, 0x03, 0x01, 0x01, 0x02, 0x1, 0x02, 0x03}
5.Используйте для путей (имен папок, имен и расширений файлов) в дереве исходных текстов символы только нижнего регистра.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
creportgenerator.h |
CReportGenerator.h |
|
|
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 2 из 23 |
6.Используйте для различных типов файлов следующие расширения:
●«h» - заголовочные файлы С++
●«cpp» - файлы реализаций С++
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
creportgenerator.h |
crepgen.H |
creportgenerator.cpp |
crepgen.hpp |
|
report_generator.cxx |
|
report.c |
|
|
7. Все определения размещайте в файлах реализации. Естественным исключением являются шаблонные (template) и встраиваемые (inline) функции и классы, для которых определение размещается в том же в заголовочном файле что и объявление, но отдельно от последнего.
Основание: заголовочный файл должен предоставлять интерфейс, а реализация такого интерфейса должна быть размещена в в файле реализации.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
// In median.h |
// In median.h |
|
int findMedian(int* pData, int cnt) |
int findMedian(int* pData, int cnt); |
{ |
|
"statements"; |
// In median.cpp |
} |
int findMedian(int* pData, int cnt) |
|
{ |
|
"statements"; |
|
} |
|
|
|
Использование заголовочные файлов
8.Включения всех заголовочных файлов размещайте в начале файла.
9.В каждый заголовочный файл встраивайте механизм защиты от повторного включения ("стражи включения"). Запрещено использовать нестандартные расширения языка для предотвращения повторного включения заголовков. Не рекомендуется использовать UID, GUID
и т.д.
Рекомендуемая схема состоит в использовании определения макроса, имя которого составляется из имени файла, расширения и даты создания файла (для большей уникальности в составе больших проектов).
ПРАВИЛЬНО
#ifndef HEADERNAME_H_20070521 #define HEADERNAME_H_20070521
...
#endif // ifndef HEADERNAME_H_20070521
НЕПРАВИЛЬНО
CTABLE_H__3FF90365_AEBE_4F17_ABB0_93D70BABB93F__INCLUDED_ // плохо читается
#pragma once; // нестандартное расширение языка С++
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 3 из 23 |
10.Используйте только относительный пути для включаемых заголовочных файлов. Используйте символ слеш ('/') при указании пути (к файлу). Для указания папок поиска заголовочных файлов используйте опции компилятора (настройки проектов в среде разработки) и системные настройки.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
#include "h/intr/propertiesdialog.h" #include "c:/prj/h/itr/PropDlg.h"
11.Упорядочивайте и группируйте включения заголовочных фалов. Для группировки используйте пустые строки между группами. Заголовки включайте в порядке увеличения общности, то есть сначала включайте более частные заголовочные файлы, а затем — более общие. Такой порядок соответствует следующему порядку:
●пользовательские заголовки;
●заголовки общего пользования;
●заголовки стандартной библиотеки.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
#include "propertiesdialog.h" |
#include <iosfwd> |
#include "mainwindow.h" |
#include <iomanip> |
|
#include <qt/QTextField.h> |
#include <qt/QButton.h> |
#include <qt/QButton.h> |
#include <qt/QTextField.h> |
#include "mainwindow.h" |
|
#include "propertiesdialog.h" |
#include <iomanip> |
|
#include <iosfwd> |
|
|
|
12.Заголовочный файл должен включать только те заголовочные файлы, которые требуются для компиляции. Если включение некоторого заголовка требуется в cpp-файле, то включение должно быть в последнем, а не в соответствующем этому cpp заголовке.
Использование препроцессора
13.Минимизируйте использования препроцессора. Используйте только следующие директивы препроцессора:
●#ifndef
●#define
●#endif
●#include
14.Избегайте использования препроцессора для определения константных значений. Вместо препроцессора используйте константы, перечисления и статические методы классов.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
const int PAGE_A4_WIDTH_PX(2400); |
#define PAGE_A4_WIDTH_PX_WIDTH_PX 2400 |
|
|
class CPageGeomtryStandart |
|
{ |
|
public: |
|
static int getPageA4Width(); |
|
}; |
|
|
|
enum RgbColor |
#define COLOR_RED 0xff0000 |
{ |
#define COLOR_BLUE 0x0000ff |
RED = 0xff0000, |
#define COLOR_GREN 0x00ff00 |
BLUE = 0x0000ff, |
|
GREN = 0x00ff00 |
|
}; |
|
|
|
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) 05.02.10 стр. 4 из 23
15.Избегайте использования препроцессора для определения подставляемого в виде макросов фрагментов исходного кода. Вместо препроцессора используйте шаблонные и встраиваемые
(inline) функции.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
template<class T> |
#define min(a,b) (((a) < (b)) ?\ |
T |
(a) : (b)); |
min(const T& lhs, const T& rhs) |
|
{ |
|
return (lhs < rhs) ? lhs : rhs; |
|
} |
|
|
|
inline int min(int lhs, int rhs) |
|
{ |
|
return (lhs < rhs) ? lhs : rhs |
|
} |
|
|
|
Правила форматирования
Пробелы и просветы
16.Ставьте пробелы:
●после ключевых слов языка
●после запятой
●после точки с запятой в инструкции цикла for
●до и после оператора
|
|
|
|
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
|
|
|
|
|
a = |
(b + |
c) |
* d; |
|
a=(b+c)*d; |
|
|
|
|
|
|
||
while (bGo) |
|
|
|
while(bGo) |
||
|
|
|
|
|||
doSomething(a, |
b, c, |
d); |
doSomething(a,b,c,d); |
|||
|
|
|
|
|
|
|
for |
(i = |
0; |
(i |
< 10) |
&& bGo; i++) |
for(i=0;i<10 && bGo;i++) |
|
|
|
|
|
|
|
Перечисление всех ситуаций, когда необходимо ставить пробел, не является полным.
17.Разделяйте логически связанные части исходного кода одной пустой строкой.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
double cosAngle = Math.cos(angle); |
double cosAngle = Math.cos(angle); |
double sinAngle = Math.sin(angle); |
double sinAngle = Math.sin(angle); |
|
Matrix4x4 matrix = new Matrix4x4(); |
Matrix4x4 matrix = new Matrix4x4(); |
matrix.setElement(1, 1, cosAngle); |
matrix.setElement(1, 1, cosAngle); |
matrix.setElement(1, 2, sinAngle); |
matrix.setElement(1, 2, sinAngle); |
matrix.setElement(2, 1, -sinAngle); |
matrix.setElement(2, 1, -sinAngle); |
matrix.setElement(2, 2, cosAngle); |
matrix.setElement(2, 2, cosAngle); |
multiply(matrix); |
multiply(matrix); |
|
|
|
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 5 из 23 |
18.Разделяйте определения функции тремя пустыми строками. |
|
|
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
|
void |
void |
|
funcA() |
funcA() |
|
{ |
{ |
|
// ... |
// ... |
|
} |
} |
|
|
void |
|
|
funcB() |
|
void |
{ |
|
funcB() |
// ... |
|
{ |
} |
|
// ... |
|
|
} |
|
|
|
|
|
void |
void |
|
СMainWindow::funcA() |
СMainWindow::funcA() |
|
{ |
{ |
|
// ... |
// ... |
|
} |
} |
|
|
void |
|
|
СMainWindow::funcB() |
|
|
{ |
|
void |
// ... |
|
СMainWindow::funcB() |
} |
|
{ |
|
|
// ... |
|
|
} |
|
|
|
|
|
19.Используйте отличные от рекомендуемого форматирование только в том случае, если его использование существенно улучшает читаемость кода.
|
ПРИМЕР |
|
|
|
|
switch (typePhase) |
|
|
{ |
|
|
case PHASE_PRE |
: start(phase, "Pre"); |
break; |
case PHASE_COMMON |
: start(phase, "Common"); |
break; |
case PHASE_POST |
: start(phase, "Post"); |
break; |
} |
|
|
|
|
|
Отступы
20.Основной отступ составляет 4 пробела.
|
|
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
|
for (i = |
0; i |
< nElements; i++) |
for (i = 0; i < nElements; i++) |
{ |
|
|
{ |
a[i] |
= 0; |
|
a[i] = 0; |
} |
|
|
} |
|
|
|
|
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 6 из 23 |
21.В определении функции размещайте тип возвращаемого значения на отдельной строке. |
||
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
|
int |
int findMedian("arguments") |
|
findMedian("arguments") |
|
|
|
|
|
void |
void MyClass::myMethod("arguments") |
|
MyClass::myMethod("arguments") |
{ |
|
{ |
"statements"; |
|
"statements"; |
} |
|
} |
|
|
|
|
|
22.Выравнивайте скобки начала и конца блока и располагайте их в отдельных строках. Тело блока размещайте с основным отступом относительно границ блока.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
"statement" |
"statement" { |
{ |
"statements"; |
"statements"; |
} |
} |
|
|
|
23.Логические блоки (if, else) оформляются в соответствии с общим принципом оформления блоков следующим образом.
ПРИМЕР
if ("condition")
{
"statements";
}
if ("condition")
{
"statements";
}
else
{
"statements";
}
if ("condition")
{
"statements";
}
else if ("condition")
{
"statements";
}
else
{
"statements";
}
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 7 из 23 |
24.Цикл for оформляется в соответствии с общим принципом оформления блоков следующим образом.
ПРИМЕР
for ("initialization"; "condition"; "update")
{
"statements";
}
25.Цикл while оформлятеся в соответствии с общим принципом оформления блоков следующим образом.
ПРИМЕР
while ("condition")
{
"statements";
}
26.Цикл do - while оформлятеся в соответствии с общим принципом оформления блоков следующим образом.
ПРИМЕР
do
{
"statements";
} while ("condition");
27.Выбор switch оформляется следующим образом.
ПРИМЕР
switch ("condition")
{
case DEF: "statements"; break;
case XYZ: "statements"; break;
default:
"statements";
break;
}
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 8 из 23 |
|
28.Оформляйте всегда в блок пустые и однострочные тела циклов и т.д. |
|
||
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
|
|
|
if ("condition") |
if ("condition") |
|
|
{ |
selectBest(prop, pData); |
|
|
selectBest(prop, pData); |
|
|
|
} |
|
|
|
|
|
|
|
if ("condition") |
if ("condition") |
|
|
{ |
selectBest(prop, pData); |
|
|
selectBest(prop, pData); |
else |
|
|
} |
selectWorst(prop, pData); |
|
|
else |
|
|
|
if ("condition") selectBest(prop, |
|||
{ |
|||
pData); |
|
||
selectWorst(prop, pData); |
|
||
else selectWorst(prop, pData); |
|||
} |
|||
|
|
||
|
|
|
|
while (!done) |
while (!done) doSomething(); |
|
|
{ |
|
|
|
while (!done) |
|
||
doSomething(); |
|
||
doSomething(); |
|
||
} |
|
||
|
|
||
|
|
|
|
Пустой цикл оформляется следующим образом |
|
|
|
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
|
||
for ("init"; "cond"; "update") |
for ("init"; "cond"; "update"); |
||
{ |
|
|
|
for ("init"; "condition"; "update") {} |
|||
} |
|||
|
|
||
|
|
|
Структурированость кода
29.Размещайте не более одной инструкции в одной строке (в строке не больше одной ';', кроме случая цикла for)
|
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
int |
i(0); |
int i(0); findBorder(&i); |
findBorder(&i); |
|
|
|
|
|
30.Размещайте не более одного оператора присваивания в строке. |
||
|
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
|
a = |
0; |
a = b = 0; |
b = |
0; |
|
|
|
|
31.Полагайтесь на приоритет только арифметических операторов. Используйте скобки для выделения частей выражений и указания приоритета вычислений.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
a = b & (c | e) & d; |
a = b & c | e & d; |
|
|
32.Избегайте длинных функций. Длинными считаются функции более 180 строк.
33.Избегайте длинных файлов. Длинными считаются файлы более 1000 строк.
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 9 из 23 |
Комментарии
34.Пишите все комментарии на русском языке.
35.В начало каждого файла исходного текста вставляйте описание по следующему шаблону (имя самого файла, краткое описание, автор, дата создания).
/** |
|
\file |
имя файла |
\brief |
краткое описание содержимого файла |
\author |
ФИО автора |
\date |
дата создания файла |
*/ |
|
|
|
|
|
|
ПРИМЕР |
|
|
/** |
|
\file |
codedialog.h |
\brief |
Класс диалога выбора входящего номера |
\author |
Полевой Дмитрий |
\date |
04.09.2004 |
*/ |
|
|
|
36.Комментируйте объявление каждой функции с использованием следующего шаблона.
ШАБЛОН
/**
\brief краткое описание функции
\param описание каждого параметра (имя [in/out] - описание) \retval TYPE, основные значения
*/
|
|
ПРИМЕР |
|
|
|
/** |
|
|
\brief Функция позволяющая |
пользователю выбрать в диалоге папку |
|
\param pUserPromt |
[in] |
- текст, который будет отображаться над деревом |
папок (подсказка) |
|
|
\param pFilePath |
[in/out] |
- папка. В диалоге выбранная папка сначала будет |
pPath. Если пользователь нажал "OK", то в szPath запишется выбранная |
||
пользователем папка |
|
|
\param lenPath |
[in] |
- размер буфера pFilePath |
\param pRootPath |
[in] |
- путь к корневой папке, в которой пользователь |
будет выбирать |
|
|
\retval bool - true, если удалось, иначе false */
bool
GetFolder(const char* pUserPromt, char* pPath, size_t int lenPath, const char* pRootPath);
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com
M102 (Правила кодирования,Полевой Д.В.) |
05.02.10 |
стр. 10 из 23 |
|
37.Комментарии пишутся с отступом комментируемого кода. |
|
||
ПРАВИЛЬНО |
|
НЕПРАВИЛЬНО |
|
|
|
|
|
// Найдем среднее значение |
|
// Найдем среднее значение |
|
for (int iRow(0); iRow != nRow; |
|
for (int iRow(0); iRow != nRow; |
|
++iRow) |
|
++iRow) |
|
// По строкам таблицы. |
|
// По строкам таблицы. |
|
{ |
|
{ |
|
// Накопитель суммы по строке. |
|
// Накопитель суммы по строке. |
|
int totalValue(0); |
|
int totalValue(0); |
|
"statements"; |
|
"statements"; |
|
} |
|
} |
|
|
|
|
|
38.Размещайте комментарии либо до комментируемого фрагмента, либо в конце |
|
||
комментируемой строки по следующему образцу. |
|
||
|
ПРИМЕР |
|
|
|
|
||
/// Главный цикл перебора компонент из хранилища. |
|
||
for (indexComp = 0; indexComp < MAX_COMP; ++indexComp) |
|
||
|
|
||
int userId(0); ///< Идентификатор пользователя АСУ. |
|
||
|
|
|
|
39.Описывайте в комментариях назначение переменных.
40.Наличие комментариев не освобождает от ответственности за излишне сложный код — изощренный код должен быть переписан, а не задокументирован.
41.Избегайте использования комментариев для отключения больших кусков кода.
Правила именования
Общие правила
42.Все имена и идентификаторы пишутся на английском (без использования транслитерации и т.д.).
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
fileName |
imyaFayla |
|
|
43.Избегайте запрещенных идентификаторов для имен.
Запрещено начинать имена с подчеркивания (резервируется для реализации компиляторов).
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
fileName_ |
_fileName |
|
|
44.Пишите имена типов (в т.ч. псевдонимы typedef) в смешанном регистре начиная с символа верхнего регистра.
ПРАВИЛЬНО |
НЕПРАВИЛЬНО |
|
|
CFastString |
fast_string |
|
|
|
fastString |
|
|
|
FastString |
|
|
предложения/пожелания и сообщения об очепятках присылать на oop.misis [тузик] gmail.com