Верблюжья нотация в С++

Материал из MyDC's Wiki

(Перенаправлено с Горбатая нотация в С++)
Перейти к: навигация, поиск

Содержание

Основной принцип построения имён

Имена отражают суть (предназначение) своего объекта. Если имя состоит из нескольких слов, то все слова записываются слитно и в нижнем регистре, а на стыке слов, каждое новое слово должно начинаться с заглавной буквы. Выступающая буква верхнего регистра напоминает горб верблюда, - отсюда и название нотации. Другое используемое название для этой нотации: "Горбатая нотация".

webConnectionFactory


Имена предопределенных типов данных

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

Line
SavingsAccount


Имена переменных

Имена переменных должны начинаться с прописной буквы и соответствовать основному принципу построения имён

line
savingsAccount

Данный принцип позволяет легко отличать объекты от типов и избегать коллизий.


Переменные по возможности должны иметь такое же имя, как и имя типа.

void setTopic(Topic* topic) // NOT: void setTopic(Topic* value)
// NOT: void setTopic(Topic* aTopic)
// NOT: void setTopic(Topic* t)


void connect(Database* database) // NOT: void connect(Database* db)
// NOT: void connect (Database* oracleDB)

Если по некоторым причинам это невозможно, следует выбирать осмысленные названия:

Point    startingPoint, centerPoint;
Name     loginName;


Все имена должны быть написаны на английском языке

fileName; // NOT: filNavn

Английский язык является основным языком международной разработки.


Имена макросов

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

#define MAX_ITERATIONS 32
#define COLOR_RED 3
#define PI 3.14


Имена предопределенных методов или функций

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

getName();
computeTotalWidth();

Такие имена идентичны именам переменных, но функция отличается от переменных наличием скобок.

Определения методов должны быть отделены друг от друга тремя пустыми строками. Таким образом методы будут выделяться.


Имя метода не должно содержать в себе имени типа или объекта

line.getLength(); // NOT: line.getLineLength();


Названия предопределенных пространств имён

Названия предопределенных пространств имён должны быть полностью в нижнем регистре.

model::analyzer
io::iomanager
common::math::geometry


Имена предопределённых типов шаблонов

Имена предопределённых типов шаблонов должны состоять из одной буквы верхнего регистра.

template<class T> ...
template<class C, class D> ...

Тикие имена делают шаблонные типы отличимыми от всех других используемых имён.


Аббревиатуры в именах

Аббревиатуры не должны быть написаны в верхнем регистре:

exportHtmlSource(); // NOT: exportHTMLSource();
openDvdPlayer(); // NOT: openDVDPlayer();

Использование верхнего регистра для аббревиатуры даст конфликты с именами переменных. Переменная в таком случае должна быть названа dVD, hTML и т.п. какое название, очевидно, не очень удобочитаемо. Другая проблема проиллюстрирована в примерах выше, когда аббревиатура соединяется с другим словом, начинающимся с буквы в верхнем регистре. Очевидно это также плохо воспринимается для чтения.


Аббревиатуры для имён не допустимы.

computeAverage(); // NOT: compAvg();
command // NOT: cmd
copy // NOT: cp
point // NOT: pt
compute // NOT: comp
initialize // NOT: init
Однако распространённые аббревиатуры, которые используются чаще всеми именно в виде аббревиатуры следует так и писать:
html // NOT: HypertextMarkupLanguage
cpu // NOT: CentralProcessingUnit
pe // NOT: PriceEarningRatio


Ссылки на глобальные переменные и функции

Ссылаться на глобальные переменные всегда надо с использованием оператора ::

::mainWindow.open()
::applicationContext.getName()

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


Переменные и область видимости

Переменные с большой областью видимости должны иметь длинные имена, переменные с малой областью имени должны иметь короткие имена.

Общие временные переменные для целых чисел: i, j, k, m, n и для символов: c и d.


Геттеры и Сеттеры

Используйте геттеры и сеттеры.

employee.getName();
employee.setName(name);
 
matrix.getElement(2, 4);
matrix.setElement(2, 4, value);

Множественное число в именах переменных

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

vector<Point> points;
int values[];


Переменные-итераторы

Переменные-итераторы должны быть названы так: i, j, k, it и тд.

for (int i = 0; i < nTables); ++i) {
    ...
}
for (vector<MyClass>::iterator it = list.begin(); it != list.end(); ++it) {
    Element element = *it;
    ...
}

Названия j, k и тд. должны быть использованы для вложенных циклов.

Префикс is

Префикс is должен использоваться для булевых методов.

bool isSet() const;
bool isVisible() const;
bool isFinished() const;
bool isFound() const;
bool isOpen() const;
Есть несколько альтернативных вариантов префикса, которые лучше отражают суть метода:
bool hasLicense() const;
bool canEvaluate() const;
bool shouldSort() const;

Дополняющие имена методов

Дополняющие имена методов должны использоваться для отражения сути методов:

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


Отрицающие логические переменные

Отрицающие логические переменные не должны использоваться.

bool isError; // NOT: isNoError
bool isFound; // NOT: isNotFound


Имена констант в перечислении

Имена констант в перечислении должны иметь такие же имена как и макросы и должны иметь в префиксе имя перечисления.

enum Color {
    COLOR_RED,
    COLOR_GREEN,
    COLOR_BLUE
};

Такое имя даёт дополнительную информацию о том где можно найти объявление той или иной константы.


Имя перечисления

Имя перечисления должны быть в единственном числе.

enum Color {
    ...
}
 
// NOT:
enum Colors {
    ...
}

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


Имена типов исключений

Имена типов исключений должны содержать суффикс Exception.

class AccessException


Названия файлов

Файлы должны иметь название основного класса, который они содержат.

Пример: MyClass.cpp, MyClass.h


Определения методов и функций

Все определения методов и функций должны находится в файле cpp.

class MyClass {
public:
    int getValue () const { return value; } // NO!
    ...
 
private:
    int value;
};

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

Число символов в строке

Число символов в строке не должно превышать 80.

80 символов - это общее измерение для редакторов, терминальных эмуляторов, принтеров и программ отладки. Файлы, которые распространяются должны придерживаться этого ограничения. Это улучшает удобочитаемость для сторонних программистов.


Использование табуляций

Вместо табуляций должны быть использованы пробелы. Рекомендуется 2 пробела. Замена табуляции пробелами обусловлена разным отображением табуляции в различных редакторах, и поэтому код может плохо читаться.

В различных редакторах табуляции настроены по-разному. Если редактор поддерживает автозамену табуляции пробелами, то рекомендуется установить это замену в 2 пробела (4 - слишком много, 3 - не симметрично).


Стражи включения

Каждый заголовочный файл должен содержать стражи включения.

#ifndef NAMEMODULE_NAMESPACE_CLASSNAME_H
#define NAMEMODULE_NAMESPACE_CLASSNAME_H
...
#endif // NAMEMODULE_NAMESPACE_CLASSNAME_H

Имя стража включения может состоять из имени модуля, имени пространства имён и имени класса. Имя модуля и имя пространства имён может быть опущено.


Подключения заголовочных файлов

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

#include "com/company/ui/PropertiesDialog.h"
#include "com/company/ui/MainWindow.h"
 
#include <fstream>
#include <iomanip>
 
#include <qt/qbutton.h>
#include <qt/qtextfield.h>


Части класса

Части класса должны быть отсортированы в следующем порядке: public, protected, private.

Тут используется принцип: "всё публичное в первую очередь". Обычно нас интересует то, как можно использовать данный класс, а не реализацию черного ящика, поэтому секция private не так часто читается, и поэтому находится в конце.


Преобразование типов

Преобразование типов должно всегда быть явным.

floatValue = static_cast<float>(intValue); // NOT: floatValue = intValue;
// NOT: floatValue = (float) intValue;

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

Переменные должны быть объявлены перед их непосредственным использованием.

int x = 0, y = 0, z = 0;
getCenter(&x, &y, &z);


Инициализация переменных

Переменные должны всегда быть инициализированы при объявлении.

int x = 0;
bool flag = false;


Роли переменных

Переменные не должны использоваться в различных ролях. Лучше завести на каждую роль свою переменную. Это улучшит читабельность кода.


Сравнение в операторе if

Не нужно в операторе if вместо сравнения с нулём использовать булево сравнение.

if (numberLines != 0) // NOT: if (numberLines)
if (value != 0.0) // NOT: if (value)


Бесконечный цикл

Для бесконечного цикла нужно использовать while (true)

while (true) {
    ...
}


Сложные условия

Сложные условия должны быть вынесены в переменную.

// NOT:
if ((elementNo < 0) || (elementNo > maxElement)|| elementNo == lastElement) {
    ...
}


bool isFinished = (elementNo < 0) || (elementNo > maxElement);
bool isRepeatedEntry = elementNo == lastElement;
if (isFinished || isRepeatedEntry) {
    ...
}

Такой код легче дебажить и документировать.


Использование скобок

По возможности в условных операторах нужно всегда использовать скобки {} даже если в теле оператора всего лишь одно действие.

if (width != 0) {
    calcWidth(width);
}


Запись условного оператора

Условие не должно записываться в одну строку.

if (isDone) { // NOT: if (isDone) doCleanup();
    doCleanup();
}

Такой код легче читать и дебажить.


Условные операторы лучше записывать в виде:

if (condition) {
    statements;
} else {
    statements;
}

Такой вид хорошо читается и обладает преимуществом по быстрой вставке дополнительных условий.


Оператор switch

Оператор switch должен иметь вид:

switch (condition) {
    case ABC :
        statements;
        // Fallthrough
 
    case DEF :
        statements;
        break;
 
    case XYZ :
        statements;
        break;
 
    default :
        statements;
        break;
 
}


Вид кода

Код должен быть удобен для чтения.

a = (b + c) * d; // NOT: a=(b+c)*d;
 
while (true) // NOT: while(true)
 
doSomething(a, b, c, d); // NOT: doSomething(a,b,c,d);
 
case 100 : // NOT: case 100:
 
for (i = 0; i < 10; i++) { // NOT: for(i=0;i<10;i++){


Комментарии

Все комментарии в коде должны быть на английском языке.

По возможности следует использовать комментарии в стиле doxygen.

Личные инструменты
Пространства имён
Варианты
Действия
Навигация
RusHub
Инструменты
Портал