1.11. МНЕМОНИКА ИМЕН В ПРОГРАММАХ
1.11. МНЕМОНИКА ИМЕН В ПРОГРАММАХ
Предлагаемая здесь методика составления имен (идентификаторов) носит рекомендательный характер. Для использования этой методики в конкретном проекте необходима ее адаптация. Составленные в соответствии с методикой имена можно использовать в программах для именования констант, переменных, типов, процедур, объектов, файлов и т. д. После адаптационной переработки методика может стать составной частью стандарта проекта. Имена, используемые в программных продуктах, должны:
— соответствовать назначению (из имени должно однозначно следовать его назначение и, наоборот, из назначения — его имя);
— обладать узнаваемостью (это свойство имени позволяет улучшить читаемость исходных текстов программ);
— обеспечивать запоминаемость (имя необходимо легко запомнить для того, чтобы каждый раз не возвращаться к документации или к тексту программы, в котором это имя определено);
— быть краткими (слишком длинные имена не запоминаемы и, несмотря на повышенную узнаваемость по сравнению с короткими именами, усложняют чтение исходного текста программы);
— обладать уникальностью (как следствие, «соответствовать назначению»: имена должны составляться таким образом, чтобы во всей системе не было двух одинаковых глобальных имен).
Конечно, хотелось бы добиться одновременного выполнения всех изложенных выше требований в совокупности, но, поскольку требование краткости противоречит требованию «обладать узнаваемостью», а иногда и «обеспечивать запоминаемость», необходимо находить оптимальный компромисс в соблюдении всех требований.
В идеальном случае имена не следует запоминать: их нужно составлять таким образом, чтобы каждый раз, зная, для которого объекта составляете имя, вы приходили бы к одному и тому же варианту имени.
Текст данных рекомендаций не лимитирует использование прописных и строчных букв, способ разделения слов и то, какие слова использовать в именах, — дополнительные ограничения налагает конкретный язык программирования. Также не рассматривается пригодный для конкретного языка программирования символ разделителя слов.
Имена констант и переменных относятся к данным, а имена данных образуются от имен существительных. Имена процедур должны быть активными, т. е. базироваться на активном глаголе, за которым следует существительное. Имена объектов обычно образуются от имен существительных, но в редких случаях могут включать глаголы и имена прилагательные. Полное имя метода состоит из имени объекта, которому принадлежит метод, символа "." разделителя и собственно имени метода объекта. Для таких полных имен крайне трудно добиться краткости. Метод является процедурной абстракцией, и его собственное имя образуется от глагола.
Итак, имя состоит из слов. Пусть длина имени — это количество слов, использованных в этом имени. Имя А является родительским по отношению к имени Б, если длина имени Б больше, чем длина имени А, и первые (слева) слова имени Б совпадают со словами имени А в том же порядке. Имя А можно рассматривать как общий префикс для имен группы Б. Например, имя debug является родительским для имен debug_info, debug_mode, debug_log, debug_error_get, debug_error_set и т. п. Имя debug_error, в свою очередь, является родительским для debug_error_get, debug_error_set.
Имя А является дочерним по отношению к имени Б, если имя Б является родительским по отношению к имени А.
Имена принадлежат одной группе, если эти имена имеют одинаковую длину и одного общего предка А. Длина имени А на единицу меньше длины имен этой группы. В таком случае А будет являться именем этой группы. Например, имена debug_error_get, debug_error_set являются именами группы debug_error. Имена debug__info, debug_mode, debug_log и debug_error, в свою очередь, являются именами группы debug.
Пусть мощность группы А — общее количество имен в этой группе. Префикс имени — это слово, которое записывается самым первым в имени и не учитывается при определении длины, родства и принадлежности группе. Префиксы используют, например, для указания типов переменных или полей: i_count, b_valid, is_protected. i, b, is — префиксы.
Требования иерархической организации имен могут частично нарушаться или вообще не использоваться при составлении локальных имен (имен для локальных переменных, имен полей таблиц, имен свойств и методов объектов и т. п.). Однако в случае, если локальных имен много, имеет смысл применять эти требования и к локальным именам.
Если имя А является дочерним по отношению к имени Б, то имя Б является обозначением некоторого объекта. Это означает, что все слова имени, кроме последнего имени, могут быть образованы только именами существительными. Только самое последнее слово в имени может быть существительным, глаголом или прилагательным. Это правило, однако, может иногда нарушаться. Например, есть некоторое действие и набор глобальных настроек (констант), которые контролируют это действие. В таком случае в именах этих констант предпоследним словом будет глагол.
В некоторых случаях имена объектов могут быть глаголами. Например, подсистему очистки базы данных логично было бы назвать слово "clear" (очистить). В таком случае глагол "очистить" будет стоять в середине имени.
Пример 1. change_user_password — плохое имя. Первое слово — глагол и оно не может обозначать имя объекта. Кроме того, может оказаться, что для каждого пользователя в системе хранится несколько паролей, например, пароль для доступа к своему аккаунту (account) и пароль для входа в чат. В таком случае в двух разных местах может потребоваться ввести две функции (изменить пароль для доступа к account и изменить пароль для входа в чат) с одинаковыми именами, что противоречит пункту "соответствовать назначению" общих требований к именам.
Пример 2. passport_password_change или passport_password_change — хорошие имена. В системе есть подсистема управления аккаунтами пользователей, называемая passport. Часть этой подсистемы, занимающаяся управлением паролями, называют passport_password. Одну из функций этой части — изменение пароля — называют passport_password_change.
Длина имени должна быть минимальной. Не используйте в именах лишних слов. Каждое слово, использованное в имени, должно означать конкретный объект, которому принадлежит это имя или конкретное действие или свойство, которому соответствует это имя. Имена объектов, действий и свойств, в свою очередь, должны состоять из имен, длина которых равна одному слову.
Пример 1. ConvertlntegerDateToSQLStrDate — плохое имя. Как вы думаете, вспомните ли вы его с точностью до символа через день?
Слова "Convert" и "То" чаще всего можно вообще опустить, поскольку очевидно, что если есть два формата даты, то, следовательно, происходит преобразование из одного формата в другой.
Слово "Date" повторять два раза не нужно, поскольку и исходное данное, и результат являются датой.
Все SQL-запросы в программе — это строки. Поэтому слово "Str" — лишнее.
Пример 2. IntegerDateSQL — приемлемое имя. Есть подсистема управления датами, и эта функция конвертирует дату, представленную в виде целого числа в строку, которую можно использовать в SQL-запросе. Недостатком этого имени является отсутствие активного глагола. Сравните это имя с исходным вариантом примера 1.
В системе не может появиться группа имен мощностью 1.
Пример 1. PASSPORT_DEAD_REMOVE_TIMEOUT — плохое имя, если с умершими пользователями (так на сайте названы пользователи, которые слишком долго не появляются) нельзя производить никаких других операций, кроме удаления.
Пример 2. PASSPORT_DEAD_TIMEOUT — хорошее имя.
Пример 3. passport_is_login_valid — плохое имя. Слово "is" — лишнее.
Пример 4. passport_login_valid — хорошее имя. Есть подсистема управления аккаунтами passport. В ней есть часть, которая занимается управлением логинами пользователей passport_login. Функция passport_login_valid проверяет, является ли "логин" правильным.
В некоторых случаях, однако, могут быть созданы группы длиной 1, например, если предполагается, что в эту группу в будущем будут добавлены новые имена.
Сокращения в словах в общем случае недопустимы. Если используете в именах слова с сокращениями, то может сложиться ситуация, когда долго будете вспоминать, каким именно способом сократили это слово и сокращали ли его вообще. Тем более что одно и то же слово можно сократить разными способами.
Это же касается и использования множественного числа существительных, глаголов во второй и третьей форме и т. п. Везде, где возможно, нужно использовать начальную форму слова, для того что бы избежать разночтения.
Кроме того, если допускаете различные сокращения (или любую другую путаницу с формами одного и того же числа), то может оказаться, что из назначения имени не следует однозначно само имя из-за того, что не выполняется пункт "соответствие назначению" общих требований к именам.
Слова не в начальной форме могут быть использованы только в том случае, если они используются МНОГО раз и при этом во ВСЕХ местах — одинаково.
Следствие: в качестве последнего слова имени может быть использовано только общепринятое сокращение (или неначальная форма), которое ВЕЗДЕ (и много раз) в программе используется именно в таком варианте. Если сокращение используется редко, то предпочтительнее использовать начальную форму слова.
Пример 1. StrToFloat — плохое имя. В ряде языков программирования есть зарезервированное слово "String". В таком случае получается, что в некоторых случаях к строкам обращаемся по полному имени, а в некоторых — по сокращению. Однако сокращение "Str" — общепринятое в системах программирования фирмы "Borland". При использовании этих систем, но не в SQL-запросах, такое сокращение резонно использовать, и имя StrToFloat становится хорошим именем.
Пример 2. StringToFloat — хорошее имя (если не учитывать наличие лишнего слова "То", но "То" хорошо показывает, что это имя процедуры конвертора типов).
Пример 3. mp_pagelist — хорошее имя, если в группе "mp" много имен или это сокращение используется в таком же написании и таком же смысле большое количество раз в других именах (mp — сокращение от "main page").
Пример 4. PASSPORT_PASSWORD_LENGTH_MIN — хорошее имя, сокращение в конце — общепринятое и везде в системе используется именно в таком варианте написания.
Пример 5. TPassportPrivileges — плохое имя для таблицы, в которой хранится список привилегий. Очевидно, что в таблице хранится много всяких привилегий, и множественное число в данном случае излишне.
Пример 6. TPassport_Privilege — хорошее имя, однако если бы не велась речь о базах данных, префикс "T" соответствовал бы типу, а не переменной.
Не допускается использование префиксов без особой на то необходимости.
Случаи, в которых использование префиксов оправдано:
• если это не имена переменных, а имена типов переменных, можно использовать префикс "T";
• если имена ваших сущностей будут перемешиваться с посторонними именами;
• в случае локальных имен.
Имена, используемые в ограниченном контексте, могут быть очень короткими. Традиционно имена i и j используются для обозначения счетчиков, p и q — для указателей, s — для строковых, а ch — для литерных переменных. Эти традиционные кратчайшие имена могут соответствовать префиксам, поясняющим тип переменных.
Пример 1. is_passport_privilege_valid — плохое имя. Префикс в глобальном имени излишен.
Пример 2. passport_privilege_valid — хорошее имя.
Пример 3. i_order — хорошее имя для поля в таблице, указывающее на порядок чего-либо. Префикс "i" характеризует тип целый.
Дополнительные рекомендации по составлению имен:
• не начинайте и не заканчивайте имена символом подчеркивания;
• не используйте имена, состоящие только из строчных букв (исключения составляют имена констант и макроопределений);
• не следует в одной и той же программе использовать имена, различающиеся лишь написанием букв — строчной или прописной;
• в зависимости от возможностей языка программирования можно разделять части имен символом подчеркивания или написанием с большой буквы очередной части имени;
• использование строчных букв в начале каждого слова имени затрудняет трансляцию текста программы с одного языка программирования на ряд других языков.
Ряд понимаемых трудно имен следует тщательно комментировать. Такой комментарий лучше приводить справа от описания имени.
При описании логической организации переменных, файлов или классов следует применять дополнительные комментарии.
Рефакторинг (от англ. refactoring) — оптимизация, улучшение реализации программы без изменения ее функциональности.
Применительно к уже кем-то или когда-либо написанным программам может осуществляться реакторинг имен, структуры данных программы, структуры программы и кода. Одновременно с рефакторингом кода может быть осуществлен и рефакторинг описания алгоритма на естественном языке.
Применительно к именам под рефакторингом понимается изменение имен таким образом, чтобы они соответствовали новым требованиям. Имена — это очень важная часть программы. Многие программисты склонны преуменьшать значимость имен.
Непонятные имена — это нечитаемая программа, а нечитаемую программу тяжело сопровождать.
Рассмотрим случаи, в которых может потребоваться рефакторинг имен:
Случай 1 — изменение правил. Можно составить разные правила образования имен и следовать сначала одним правилам, потом, уточнив эти правила, следовать другим. Неизменным должно оставаться только одно правило: все имена в проекте должны быть построены по одним правилам.
Случай 2 — частичный рефакторинг имен. Если по каким-либо причинам изменили правила составления имен, то следует обновить все имена, не подходящие под новые правила.
Случай 3 — невозможность однозначного предсказания будущего. Любой проект развивается. На этапе создания может оказаться, что спроектированная структура не полна или сначала предполагалась одна структура, а затем стала очевидной другая, более предпочтительная структура.
Случай 4 — рефакторинг имен, на ваш взгляд, не нужен: вы уже заканчиваете работу над проектом, не планируете в будущем его поддерживать и вам все равно, что о вас подумают люди, которым придется разбираться в вашем коде.
Квалифицированные программисты тратят некоторое время на вычищение своего кода для простоты его последующего использования. Ясность кода определяется ясностью имен данных, понятностью назначения и последовательности действий, ясностью имен процедур и объектов.