260
ЧАСТЬ III Переменные const int CONTROL_CHARACTER = 0x80;
// возможные значения переменной ReportType enum ReportType {
ReportType_Daily,
ReportType_Monthly,
ReportType_Quarterly,
ReportType_Annual,
ReportType_All
};
Если вам трудно понять какой-то фрагмент кода, подумайте о переименовании переменных. В отличие от детективных романов код программ не должен содер- жать загадок. Его нужно просто читать.
Именование временных переменных
Временные переменные служат для хранения промежуточных результатов вычис- лений и служебных значений программы. Обычно им присваивают имена
temp,
x или какие-нибудь другие столь же неопределенные и неописательные имена.
В целом использование временных переменных говорит о том, что программист еще не полностью понял проблему. Кроме того, с переменными, официально получившими «временный» статус, программисты обычно обращаются небреж- нее, чем с другими переменными, что повышает вероятность ошибок.
Относитесь к «временным» переменным с подозрением Часто значение нуж- но на некоторое время сохранить. Однако в том или ином смысле временными являются почти все переменные. Называя переменную временной, подумайте, до конца ли вы понимаете ее реальную роль. Рассмотрим пример:
Пример неинформативного имени «временной» переменной (C++)
// Вычисление корней квадратного уравнения.
// Предполагается, что дискриминант (b^2-4*a*c) неотрицателен.
temp = sqrt( b^2 - 4*a*c );
root[0] = ( -b + temp ) / ( 2 * a );
root[1] = ( -b - temp ) / ( 2 * a );
Значение выражения
sqrt( b^2 - 4 * a * c ) вполне разумно сохранить в перемен- ной, особенно если учесть, что оно используется позднее. Но имя
temp ничего не говорит о роли переменной. Лучше поступить так:
Пример замены «временной» переменной на реальную переменную (C++)
// Вычисление корней квадратного уравнения.
// Предполагается, что дискриминант (b^2-4*a*c) неотрицателен.
discriminant = sqrt( b^2 - 4*a*c );
root[0] = ( -b + discriminant ) / ( 2 * a );
root[1] = ( -b - discriminant ) / ( 2 * a );
По сути это тот же код, только в нем использована переменная с точным описа- тельным именем.
1 ... 29 30 31 32 33 34 35 36 ... 104
ГЛАВА 11 Сила имен переменных
261
Именование булевых переменных
Ниже я привел ряд рекомендаций по именованию булевых переменных.
Помните типичные имена булевых переменных Вот некоторые наиболее полезные имена булевых переменных.
쐽
done Используйте переменную done как признак завершения цикла или дру- гой операции. Присвойте ей
false до выполнения действия и установите ее в
true после его завершения.
쐽
error Используйте переменную error как признак ошибки. Присвойте ей зна- чение
false, если все в порядке, и true в противном случае.
쐽
found Используйте переменную found для определения того, обнаружено ли некоторое значение. Установите ее в
false, если значение не обнаружено, и в
true, как только значение найдено. Используйте переменную found при поис- ке значения в массиве, идентификатора сотрудника в файле, определенного чека в списке чеков и т. д.
쐽
success или ok Используйте переменную success или ok как признак успешно- го завершения операции. Присвойте ей
false, если операция завершилась не- удачей, и
true, если операция выполнена успешно. Если можете, замените имя
success на более определенное, ясно определяющее смысл «успеха». Если под
«успехом» понимается завершение обработки данных, можете назвать перемен- ную
processingComplete. Если «успех» подразумевает обнаружение конкретно- го значения, можете использовать переменную
found.
Присваивайте булевым переменным имена, подразумевающие значение
true или false Имена вроде done и success — хорошие имена булевых перемен- ных, потому что они предполагают использование только значений
true или false:
что-то может быть или выполнено, или не выполнено, операция может завершиться или успехом, или неудачей. С другой стороны, имена вроде
status и sourceFile не годятся, так как при этом значения
true или false не имеют ясного смысла. Какой вывод можно сделать
, если переменной
status задано
true? Означает ли это, что что-то имеет статус? Все имеет статус. Означает ли это, что что-то имеет статус
«все в порядке»? Означает ли значение
false, что никакое действие не было выпол- нено неверно? Если переменная имеет имя
status, ничего определенного на сей счет сказать нельзя.
Поэтому имя
status лучше заменить на имя вроде
error или
statusOK, а имя
source-File — на
sourceFileAvailable,
sourceFileFound или подобное имя, соответствующее сути переменной.
Некоторые программисты любят дополнять имена булевых переменных префик- сом
is. В результате имя переменной превращается в вопрос:
isdone?
isError?
isFound?
isProcessingComplete? Ответ на этот вопрос сразу становится и значением перемен- ной. Достоинство этого подхода в том, что он исключает использование неопре- деленных имен: вопрос
isStatus? не имеет никакого смысла. Однако в то же время он затрудняет чтение логических выражений: например, условие
if (
isFound ) менее понятно, чем
if (
found ).
262
ЧАСТЬ III Переменные
Используйте утвердительные имена булевых переменных Имена, основан- ные на отрицании (такие как
notFound, notdone и notSuccessful), при выполнении над переменной операции отрицания становятся куда менее понятны, например:
if not notFound
Подобные имена следует заменить на
found, done и processingComplete, выполняя отрицание переменных в случае надобности. Так что для проверки нужного зна- чения вы использовали бы выражение
found, а не not notFound.
Именование перечислений
Принадлежность переменных к тому или иному перечисле- нию можно пояснить, дополнив их имена префиксами, та- кими как
Color_, Planet_ или Month_:
Пример дополнения элементов перечислений префиксами (Visual Basic)
Public Enum Color
Color_Red
Color_Green
Color_Blue
End Enum
Public Enum Planet
Planet_Earth
Planet_Mars
Planet_Venus
End Enum
Public Enum Month
Month_January
Month_February
Month_December
End Enum
Кроме того, сами перечисления (
Color, Planet или Month) можно идентифициро- вать разными способами: например, используя в их именах только заглавные буквы или дополняя их имена префиксами (
e_Color, e_Planet или e_Month). Кое-кто мог бы сказать, что перечисление по сути является типом, определяемым пользовате- лем, поэтому имена перечислений надо форматировать так же, как имена клас- сов и других пользовательских типов. С другой стороны, члены перечислений являются константами, поэтому имена перечислений следует форматировать как имена констант. В этой книге я придерживаюсь конвенции, предусматривающей применение в именах перечислений букв обоих регистров.
В некоторых языках перечисления рассматриваются скорее как классы, а именам членов перечисления всегда предшествует имя самого перечисления, например,
Color.Color_Red или Planet.Planet_Earth. Если вы используете подобный язык, по- вторять префикс не имеет смысла, так что вы можете считать префиксом само имя перечисления и сократить имена до
Color.Red и Planet.Earth.
Перекрестная ссылка О пере- числениях см. раздел 12.6.
ГЛАВА 11 Сила имен переменных
263
Именование констант
Имя константы должно характеризовать абстрактную сущ- ность, представляемую константой, а не конкретное значе- ние. Имя
FIVE — плохое имя константы (независимо от того,
имеет ли она значение
5.0). CYCLES_NEEDED — хорошее имя.
CYCLES_NEEDED может иметь значение 5.0, 6.0 и любое другое. Выражение FIVE =
6.0 было бы странным. Аналогично BAKERS_DOZEN — плохое имя константы, а
DONUTS_MAX — вполне подходящее.
11.3. Сила конвенций именования
Программисты предпочитают порой не использовать стандарты и конвенции по вполне разумной причине. Некоторые стандарты и конвенции, слишком жесткие и неэффективные, подавляют творчество и снижают качество программы. Это пе- чально, так как эффективные стандарты — один из мощнейших инструментов. В
этом разделе мы обсудим, почему, когда и как создавать собственные стандарты именования переменных.
Зачем нужны конвенции?
Конвенции обеспечивают несколько преимуществ.
쐽
Они позволяют больше принимать как данное. Приняв одно общее решение вместо нескольких более узких, вы сможете сосредоточиться на более важных аспектах кода.
쐽
Они помогают использовать знания, полученные при работе над предыдущи- ми проектами. Сходство имен облегчает понимание незнакомых переменных.
쐽
Они ускоряют изучение кода нового проекта. Вместо изучения особенностей кода
Аниты, Джулии и Кристин вы сможете работать с более согласованным кодом.
쐽
Они подавляют «размножение» имен. Не применяя конвенцию именования, вы легко можете присвоить одной сущности два разных имени. Скажем, вы мо- жете назвать общее число баллов и
pointTotal, и totalPoints. Возможно, при на- писании программы вам все будет понятно, но другой программист, который попытается понять такой код позднее, может столкнуться с серьезными про- блемами.
쐽
Они компенсируют слабости языка. Вы можете использовать конвенции для имитации именованных констант и перечислений. Конвенции позволяют про- вести грань между локальными данными, данными класса и глобальными дан- ными, а также охарактеризовать типы, не поддерживаемые компилятором.
쐽
Они подчеркивают отношения между связанными элементами. Если вы исполь- зуете данные объектов, компилятор заботится об этом автоматически. Если язык не поддерживает объекты, вы можете свести этот недостаток к минимуму при помощи конвенции именования. Так, имена
address, phone и name не говорят о том, что эти переменные связаны между собой. Но если вы решите допол- нять все переменные, хранящие данные о сотрудниках, префиксом
Employee,
эта связь будет ясно выражена в итоговых именах
employeeAddress, employeePhone
и
employeeName. Конвенции программирования могут устранить недостатки используемого вами языка.
Перекрестная ссылка Об имено- ванных константах см. раздел
12.7.
264
ЧАСТЬ III Переменные
Суть сказанного в том, что наличие хоть какой-то конвенции обычно пред- почтительнее, чем ее отсутствие. Конвенция может быть произвольной.
Сила конвенций именования объясняется не конкретными аспектами, а самим фактом их использования, обеспечивающим структурирование кода и умень- шающим количество поводов для беспокойства.
Когда следует использовать конвенцию именования?
Непреложных правил на этот счет нет, однако некоторые рекомендации дать можно. Итак, используйте конвенцию именования, если:
쐽
над проектом работают несколько программистов;
쐽
программу будут изменять и сопровождать другие программисты (что имеет место почти всегда);
쐽
обзор программы выполняют другие программисты из вашей компании;
쐽
программа так велика, что вы не можете полностью охватить ее умом, а вы- нуждены рассматривать по частям;
쐽
программа будет использоваться длительное время, из-за чего вам, возможно,
придется вернуться к ней через несколько недель или месяцев;
쐽
прикладная область имеет необычную терминологию и вы хотите стандарти- зовать применение терминов или аббревиатур в коде.
Использовать конвенции именования всегда выгодно, а мои советы помогут вам определить оптимальную детальность конвенции для конкретного проекта.
Степень формальности конвенций
Конвенциям именования могут соответствовать разные сте- пени формальности. Неформальная конвенция может быть совсем простой: «Используйте выразительные имена». Дру- гие неформальные конвенции рассматриваются в следую- щем разделе. В общем, оптимальная степень формальнос- ти конвенции определяется числом людей, работающих над программой, разме- ром программы и ожидаемым временем ее использования. При работе над кро- шечными проектами, подлежащими выбросу, следование строгой конвенции,
наверное, окажется пустой тратой сил. В случае более крупных проектов, реали- зуемых с участием нескольких программистов, формальная конвенция — важней- шее средство улучшения удобочитаемости программы.
11.4. Неформальные конвенции именования
В большинстве проектов используются относительно неформальные конвенции именования, подобные тем, что описываются в этом разделе.
Конвенция, не зависящая от языка
Ниже приведены некоторые советы по созданию конвенции, не зависящей от языка.
Проведите различие между именами переменных и именами методов
Конвенция, используемая в этой книге, подразумевает, что имена переменных и
Перекрестная ссылка О разли- чиях формальности при рабо- те над небольшими и крупны- ми проектами см. главу 27.