Имена идентификаторов
Идентификатор — это имя переменной, функции или других объектов. Мы можем определять идентификаторы любыми словами/именами. Тем не менее, есть несколько общих правил, которые необходимо соблюдать:
- Идентификатор не может быть ключевым словом. Ключевые слова зарезервированы.
- Идентификатор может состоять только из букв (нижнего и верхнего регистра) латинского алфавита, цифр и символов подчёркивания. Это означает, что все другие символы и пробелы — запрещены.
- Идентификатор должен начинаться с буквы (нижнего или верхнего регистра). Он не может начинаться с цифры.
- Язык C++ различает нижний и верхний регистры. nvalue отличается от nValue и отличается от NVALUE.
Теперь, когда вы знаете, как можно называть идентификаторы, давайте поговорим о том, как их нужно называть.
Во-первых, имена переменных начинаются с буквы в нижнем регистре. Если имя переменной состоит из одного слова, то это слово должно быть записано в нижнем регистре:
int value; // корректно
int Value; // некорректно (должно начинаться с буквы в нижнем регистре)
int VALUE; // некорректно (должно начинаться с буквы в нижнем регистре)
int VaLuE; // некорректно (должно начинаться с буквы в нижнем регистре)
В статье о директивах я уже упоминал, что константные переменные именуются буквами в верхнем регистре с использованием символа подчеркивания между словами.
#define CONSTANT_VARIABLE 18
#define SOME_ANOTHER_CONST 4
Имена функций, как правило, начинаются с буквы в нижнем регистре (хотя есть некоторые разногласия по этому вопросу). Мы будем придерживаться этого стиля, поскольку даже функция main(), главная функция всех программ, начинается с буквы в нижнем регистре, как и все функции из Стандартной библиотеки C++.
string conjunction (string a, string b);
int myNewFunction (int x, int y);
Имена идентификаторов, которые начинаются с заглавной буквы, используются для структур и классов, коими в скриптах выступают объекты.
object Ships;
object NonPlayableCharacters;
Если вы, по каким-то причинам, используете неконстантные глобальные переменные - добавляйте к их именам соответствующие префиксы. Например g. Во-первых, это избавит вас от проблем с непреднамеренным изменением значений. А во-вторых, позволит обращаться к таким переменным, даже если внутри функции существует локальная переменная с таким же именем.
Более детально я объяснял это на соответствующем уроке.
Более детально я объяснял это на соответствующем уроке.
bool gMode = true;
int gVersion = 20043;
шутка юмора
Вопрос: Какой наилучший префикс для глобальных переменных?
Ответ: //
Ответ: //
В том, что касается переменных - скриптовая часть Корсаров устроена так, что в путаницу попасть ещё легче, чем в обычном С++.
Поскольку ссылки в Корсарах имеют свой отдельный тип данных - очень легко перепутать, с каким типом данных мы работаем в данный момент. В одной функции, обращаясь к переменной какого-то корабля, мы работаем с целым числом, а другая ф-ция обрабатывает этот же корабль как ссылку. А таких функций будут сотни. Легко запутаться и передать не тот тип данных, или неправильно его обработать.
Подобная проблема будет и со структурами, которые абсолютно все данные хранят в строковом формате.
Многие из ваших предшественников решали эту проблему добавлением в имя переменной префикса, обозначающего её тип:
bool bGameStarted; // b = bool
float fHullPercent; // f = float
int iSomeNumber; // i = integer
string sCharName; // s = string
ref rHero; // r = reference
aref arHealth; // ar = attribute reference
В перечислении аргументов функции ситуация обратная. Из-за того, что ссылки выделены в самостоятельный тип данных, может быть не очевидным, какой тип ожидает функция. В таких случаях, префикс ссылочной переменной лучше указать таким, что будет указывать на тип данных, который передается в функцию по ссылке.
int myFunc (ref fPosX, ref fPosY, ref sCharName)
{
// ...
}
Используя такой подход к именованию, вы всегда будете уверены, какой тип данных имеет переменная.
И, пожалуй, самое важное правило из всех: используйте в качестве идентификаторов только те имена, которые реально описывают то, чем является объект. Очень характерно для неопытных программистов сокращать имена переменных, чтобы сэкономить время при наборе кода или потому, что они думают, что всё и так понятно. В большинстве случаев не всё всегда является понятным и очевидным. В идеале переменные нужно называть так, чтобы человек, который первый раз увидел ваш код, понял как можно скорее, что этот код делает. Через 3 месяца, когда вы будете пересматривать свой код, вы забудете, как он работает, и будете благодарны самому себе за то, что называли переменные по сути, а не как попало. Чем сложнее код, тем проще и понятнее должны быть идентификаторы.
Форматирование кода
- Вместо символа табуляции (клавиша <Tab>) используйте 4 пробела. Причиной использования пробелов вместо символов табуляции является то, что если вы откроете свой код в другом редакторе, то он сохранит правильные отступы, в отличие от использования символов табуляции. Большинство IDE позволяют настроить использование пробелов при нажатии клавиши <Tab>.
- Открытие и закрытие фигурных скобок функции (и других блоков кода) должно находиться на одном уровне на отдельных строках. В случае возникновения ошибки несоответствия скобок, найти те самые проблемные скобки визуально будет проще.
int main()
{
}
- Каждый стейтмент функции должен быть с соответствующим отступом (клавиша <Tab> или 4 пробела):
int main()
{
int myVar = 2;
return myVar;
}
- Используйте пробелы и пропуски строк между стейтментами для улучшения читабельности вашего кода:
iCost = 57;
rPricePerItem = 24.2;
iValue = 5;
iNumberOfItems = 17;
Расположение кода в файле
В самом верху файла должны находиться директивы. Сначала #include, затем #define.
Если вы используете глобальные переменные - их также необходимо объявлять в верхней части кода. Ниже директив #include, но выше остального кода в файле.
И только после этого следуют ваши функции.
Старайтесь компоновать код так, чтобы в пределах одного файла находились только функции, которые непосредственно связанные с выполнением задач, описанных в названии файла. Не разбрасывайте взаимосвязанный код по всей программе. Так будет легче в нем ориентироваться при внесении изменений или поиске нужных функций. В том числе и вам.
Старайтесь компоновать код так, чтобы в пределах одного файла находились только функции, которые непосредственно связанные с выполнением задач, описанных в названии файла. Не разбрасывайте взаимосвязанный код по всей программе. Так будет легче в нем ориентироваться при внесении изменений или поиске нужных функций. В том числе и вам.
Использование функций
Одной из наиболее распространенных проблем, с которой сталкиваются новички, является непонимание того, где, когда и как эффективно использовать функции.
Чтобы ответить на этот вопрос, давайте сначала обозначим преимущества, которые дают функции в написании программ:
Чтобы ответить на этот вопрос, давайте сначала обозначим преимущества, которые дают функции в написании программ:
- Структура. Как только программы увеличиваются в размере/сложности, сохранять весь код внутри одной функции становится трудно. Функция — это как мини-программа, которую мы можем записать отдельно от головной программы, не заморачиваясь при этом об остальных частях кода. Это позволяет разбивать сложные задачи на более мелкие и простые, что кардинально снижает общую сложность программы.
- Повторное использование. После объявления функции, её можно вызывать много раз. Это позволяет избежать дублирования кода и сводит к минимуму вероятность возникновения ошибок при копировании/вставке кода.
- Тестирование. Поскольку функции убирают лишний код, то и тестировать его становится проще. А так как функция — это самостоятельная единица, то нам достаточно протестировать её один раз, чтобы убедиться в её работоспособности, а затем мы можем её повторно использовать много раз без необходимости проводить тестирование (до тех пор, пока не внесем изменения непосредственно в эту функцию).
- Модернизация. Когда нужно внести изменения в программу или расширить её функционал, то функции являются отличным вариантом. С их помощью можно внести изменения в одном месте, чтобы они работали везде.
- Абстракция. Для того, чтобы использовать функцию, нам нужно знать её имя, данные ввода, данные вывода и где эта функция находится. Нам не нужно знать, как она работает. Это очень полезно для написания кода, понятного другим.
Исходя из этой информации, можно дать несколько рекомендаций по написанию функций:
- Код, который появляется более одного раза в программе, лучше переписать в виде функции. Например, если мы обрабатываем одни и те же данные несколько раз одним и тем же способом, то это отличный вариант для написания отдельной функции.
- Код, который используется для сортировки чего-либо, лучше записать в виде отдельной функции. Например, если у нас есть список вещей, которые нужно отсортировать — пишем функцию сортировки, куда передаем несортированный список и откуда получаем отсортированный.
- Функция должна выполнять одно (и только одно) задание.
- Когда функция становится слишком большой, сложной или непонятной — её следует разбить на несколько подфункций. Это называется рефакторингом кода.
Справка:Рефа́кторинг (англ. «refactoring»), или перепроекти́рование кода — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы.
Комментарии
ВСЕГДА
ПИШИТЕ
КОММЕНТАРИИ
Всегда оставляйте комментарии к своему коду. Если сомневаетесь, нужен комментарий или нет - напишите. Уточняющий комментарий всегда будет только плюсом. Например, мы объявили переменную с именем numberOfChars, которая должна хранить количество символов определенной части строки. Сколько символов в строке Hello, world!: 10, 11, 12 или 13? Это зависит от того, учитываем ли мы пробелы и знаки препинания или нет. Вместо названия переменной numberOfCharsIncludingWhitespaceAndPunctuation лучше оставить хороший комментарий, который прояснит ситуацию:
// Эта переменная подсчитывает количество символов части строки, включая пробелы и знаки препинания
int numberOfChars;
Не ленитесь и комментируйте все участки кода. Как минимум, у вас должны быть описания функций. Если функция длиннее десяти строк - она абсолютно точно нуждается в дополнительных комментариях.
Ред. nazarpunk
Во-вторых, комментарии - очень непопулярная тема, к сожалению. А приучить людей ставить одну букву - можно))
Но комментарий в данном случае тоже вполне себе подойдет, ты абсолютно прав.
В зависимости от структуры, это могут быть запуски обработчиков ошибок, сервисов обслуживания движка, самого движка и т.п.
Или просто иниты основных модулей, если это приложение попроще.
g_myStruct.m_lpMySub.pszMyString
На новые типы данных
g_nNumberOfChars
Ред. avuremybe
Но есть одна проблема.
Из всего перечисленного в скрипты Корсаров завезли только венгерскую нотацию.
Ред. avuremybe
К этому моменту он бы уже знал, что у всех функций после имени скобки ставятся. И перепутать ее с переменной невозможно, хоть как ее не называай.