Руководство по стилю программирования и конструированию по
Скачать 7.6 Mb.
|
ГЛАВА 11 Сила имен переменных 277 Вероятность создания избыточных аббревиатур также снижается. Программист, желающий сократить какое-то слово, должен будет проверить документ и ввести новую аббревиатуру. Если это слово уже было сокращено, программист заметит это и будет использовать существующую аббревиатуру. Этот совет иллюстрирует различие между удобством написания кода и удобством его чтения. Очевидно, что рассмотренный подход делает на- писание кода менее удобным, однако на протяжении срока службы сис- темы программисты проводят гораздо больше времени именно за чтением кода, которое благодаря этому подходу облегчается. Когда вся пыль осядет, вполне может оказаться, что этот подход облегчил и написание кода. Помните, что имена создаются в первую очередь для программистов, читающих код Прочитайте собственный код, который вы не видели минимум шесть месяцев, и обратите внимание на те имена, суть которых вы не можете понять с первого взгляда. Измените подходы, подталкивающие к выбору таких имен. 11.7. Имена, которых следует избегать Ниже я описал некоторые типы имен, которых следует избегать. Избегайте обманчивых имен или аббревиатур Убедитесь в том, что имя не является двусмысленным. Скажем, FALSE обычно является противоположностью TRUE, и использовать такое имя как сокращение фразы «Fig and Almond Season» было бы глупо. Избегайте имен, имеющих похожие значения Если есть вероятность, что вы можете спутать имена двух переменных и это не приведет к ошибке компиляции, переименуйте обе переменных. Например, пары имен input и inputValue, recordNum и numRecords или fileNumber и fileIndex так похожи с семантической точки зре- ния, что если вы будете использовать их в одном фрагменте кода, то сможете легко их спутать, внеся в код неуловимые ошибки. Избегайте переменных, имеющих разную суть, но по- хожие имена Если у вас есть две таких переменных, по- пытайтесь переименовать одну из них или изменить аб- бревиатуры. Избегайте имен вроде clientRecs и clientReps. Они различаются только одной буквой, и это трудно заметить. Выбирайте имена, различающиеся хотя бы двумя буквами или первой/последней буквой. Имена clientRecords и cli- entReports лучше, чем первоначальные имена. Избегайте имен, имеющих похожее звучание, таких как wrap и rap Когда вы пытаетесь обсудить код с другими людьми, в разговор иногда вмешиваются омонимы. Так, одним из самых забавных аспектов экстремального программиро- вания (Beck, 2000) является слишком хитрое использование терминов «Goal Donor» и «Gold Owner» 1 , которые звучат практически одинаково. В итоге разговор может принять подобный оборот: Перекрестная ссылка Техниче- ски подобное различие между сходными именами переменных называется «психологической дистанцией» (см. подраздел «Психологическая дистанция» раздела 23.4). 1 Что буквально переводится как «донор цели» и «владелец золота». В экстремальном програм- мировании так называют роли людей, соответственно ставящих перед разработчиками задачу и финансирующих проект. — Прим. перев. 278 ЧАСТЬ III Переменные — Я только что разговаривал с Goal Donor. — Что ты сказал? «Gold Owner» или «Goal Donor»? — Я сказал «Goal Donor». — Что? — GOAL - - - DONOR! — Ясно, Goal Donor. Не нужно кричать, черт возьми (Goll’ Darn it). — Какое еще «золотое кольцо» (Gold Donut)? Как и в случае непроизносимых аббревиатур, используйте для исключения подоб- ных ситуаций телефонный тест. Избегайте имен, включающих цифры Если наличие цифр в именах действи- тельно имеет смысл, используйте вместо отдельных переменных массив. Если этот вариант неуместен, цифры в именах еще более неуместны. Например, избегайте имен file1 и file2 или total1 и total2. Почти всегда можно найти более разумный способ проведения различия между двумя переменными, чем дополнение их имен цифрами. В то же время я не могу сказать, что цифры нельзя использовать вооб- ще. Некоторые сущности реального мира (такие как шоссе 66) изначально вклю- чают цифры. И все же перед созданием подобного имени подумайте, есть ли луч- шие варианты. Избегайте орфографических ошибок Вспомнить правильные имена перемен- ных и так довольно трудно. Требовать запоминания «правильных» орфографиче- ских ошибок — это уж слишком. Например, если вы решите сэкономить три бук- вы и замените слово highlight на hilite, программисту, читающему код, будет нео- писуемо трудно вспомнить, на что же вы его заменили. На highlite? hilite? hilight? hilit? jai-a-lai-t? Кто его знает. Избегайте слов, при написании которых люди часто допускают ошиб- ки Absense, acummulate, acsend, calender, concieve, defferred, definate, independance, occassionally, prefered, reciept, superseed и многие другие орфографические ошиб- ки весьма распространены в англоязычном мире. Список подобных слов можно найти в большинстве справочников по английскому языку. Не используйте такие слова в именах переменных. Проводите различие между именами не только по регистру букв Если вы программируете на C++ или другом языке, в котором регистр букв играет роль, вы можете поддастся соблазну сократить понятия fired, final review duty и full revenue disbursal соответственно до frd, FRD и Frd. Избегайте этого подхода. Хотя эти имена уникальны, их связь с конкретными значениями произвольна и непонятна. Имя Frd может с тем же успехом обозначать final review duty, а FRD — full revenue disbursal, и никакое логическое правило не поможет вам или кому-то другому запомнить, что есть что. Избегайте смешения естественных языков Если в проекте участвуют програм- мисты разных национальностей, обяжите их именовать все элементы программы, используя один естественный язык. Понять код другого программиста непросто; а код, написанный на юго-восточном диалекте марсианского языка, — невозможно. Еще более тонкая проблема связана с наличием разных диалектов английского языка. Если в проекте участвуют представители разных англоязычных стран, сде- ГЛАВА 11 Сила имен переменных 279 лайте стандартом тот или иной вариант английского языка, чтобы вам не при- шлось вспоминать, как называется конкретная переменная: «color» или «colour», «check» или «cheque» и т. д. Избегайте имен стандартных типов, переменных и методов Все языки программирования имеют зарезервированные и предопределенные имена. Про- сматривайте время от времени списки таких имен, чтобы не вторгаться во владе- ния используемого языка. Так, следующий фрагмент вполне допустим при про- граммировании на PL/I, но написать ТАКОЕ может только идиот со справкой: if if = then then then = else; else else = if; Не используйте имена, которые совершенно не связаны с тем, что пред- ставляют переменные Использование имен вроде margaret и pookie практи- чески гарантирует, что никто другой их не поймет. Не называйте переменные в честь девушки, жены, любимого сорта пива и т. д., если только девушка, жена или сорт пива не являются представляемыми в программе «сущностями». Но даже тогда вы должны понимать, что все в мире изменяется, поэтому имена девушка, жена и любимыйСортПива гораздо лучше! Избегайте имен, содержащих символы, которые можно спутать с дру- гими символами Помните, что некоторые символы выглядят очень похоже. Если два имени различаются только одним таким символом, вы можете столкнуться с проблемами. Попробуйте, например, определить, какое из имен является лишним в каждой тройке: eyeChartl eyeChartI eyeChartl TTLCONFUSION TTLCONFUSION TTLC 0 NFUSION hard2Read hardZRead hard2Read GRANDTOTAL GRANDTOTAL 6RANDTOTAL ttl5 ttlS ttlS В число пар символов, которые трудно различить, входят пары (1 и l), (1 и I), (. и ,), (0 и O), (2 и Z), (; и :), (S и 5) и (G и 6). Действительно ли важны подобные детали? Да! Джеральд Вайнберг пишет, что в 1970-х из-за того, что в команде FORMAT языка Fortran вместо точки была использована за- пятая, ученые неверно рассчитали траекторию космичес- кого корабля и потеряли космический зонд стоимостью 1,6 млрд долларов (Weinberg, 1983). Контрольный список: именование переменных Общие принципы именования переменных Описывает ли имя представляемую переменной сущность полно и точно? Характеризует ли имя проблему реального мира, а не ее решение на языке программирования? Перекрестная ссылка Вопросы, касающиеся использования дан- ных, приведены в контрольном списке в главе 10. http://cc2e.com/1191 280 ЧАСТЬ III Переменные Имеет ли имя длину, достаточную для того, чтобы над ним не нужно было ломать голову? Спецификаторы вычисляемых значений находятся в конце имен? Используются ли в именах спецификаторы Count или Index вместо Num? Именование конкретных видов данных Выразительные ли имена присвоены индексам циклов (более ясные, чем i, j и k, если цикл содержит более одной-двух строк или является вложенным)? Всем ли «временным» переменным присвоены выразительные имена? Можно ли по именам булевых переменных понять, какой смысл имеют зна- чения «истина» и «ложь»? Включают ли имена элементов перечислений префикс или суффикс, опре- деляющий принадлежность элемента к перечислению — например, префикс Color_ в случае элементов Color_Red, Color_Green, Color_Blue и т. д.? Именованные константы названы в соответствии с представляемыми абст- рактными сущностями, а не конкретными числами? Конвенции именования Проводит ли конвенция различие между локальными данными, данными класса и глобальными данными? Проводит ли конвенция различие между именами типов, именованных кон- стант, перечислений и переменных? Идентифицировали ли вы исключительно входные параметры методов, если язык не навязывает их идентификацию? Постарались ли вы сделать конвенцию как можно более совместимой со стандартными конвенциями конкретного языка? Способствует ли форматирование имен удобству их чтения? Короткие имена Стараетесь ли вы не сокращать имена без необходимости? Избегаете ли вы сокращения имен только на одну букву? Все ли слова вы сокращаете согласованно? Легко ли произнести выбранные имена? Избегаете ли вы имен, допускающих неверное прочтение или произношение? Документируете ли вы короткие имена при помощи таблиц преобразования? Распространенные проблемы именования. Избежали ли вы… …имен, которые вводят в заблуждение? …имен с похожими значениями? …имен, различающихся только одним или двумя символами? …имен, имеющих похожее звучание? …имен, включающих цифры? …имен, намеренно написанных с ошибками с целью сокращения? …имен, при написании которых люди часто допускают ошибки? …имен, конфликтующих с именами методов из стандартных библиотек или предопределенными именами переменных? …совершенно произвольных имен? …символов, которые можно спутать с другими символами? ГЛАВА 11 Сила имен переменных 281 Ключевые моменты 쐽 Выбор хороших имен переменных — одно из главных условий понятности программы. С отдельными типами переменных — например, с индексами цик- лов и переменными статуса — связаны свои принципы именования. 쐽 Имена должны быть максимально конкретны. Имена, которые из-за невыра- зительности или обобщенности можно использовать более чем с одной целью, обычно являются плохими. 쐽 Конвенции именования позволяют провести различие между локальными дан- ными, данными класса и глобальными данными, а также между именами ти- пов, именованных констант, перечислений и переменных. 쐽 Над каким бы проектом вы ни работали, вам следует принять конвенцию име- нования переменных. При выборе типа конвенции следует учитывать размер программы и число работающих над ней программистов. 쐽 Современные языки программирования позволяют отказаться от сокращения имен. Если вы все-таки сокращаете имена, регистрируйте аббревиатуры в сло- варе проекта или используйте стандартизированные префиксы. 쐽 За чтением кода программисты проводят гораздо больше времени, чем за его написанием. Выбирайте имена так, чтобы они облегчали чтение кода, пусть даже за счет удобства его написания. 282 ЧАСТЬ III Переменные Г Л А В А 1 2 Основные типы данных Содержание 쐽 12.1. Числа в общем 쐽 12.2. Целые числа 쐽 12.3. Числа с плавающей запятой 쐽 12.4. Символы и строки 쐽 12.5. Логические переменные 쐽 12.6. Перечислимые типы 쐽 12.7. Именованные константы 쐽 12.8. Массивы 쐽 12.9. Создание собственных типов данных (псевдонимы) Связанные темы 쐽 Присвоение имен данным: глава 11 쐽 Нестандартные типы данных: глава 13 쐽 Общие вопросы использования переменных: глава 10 쐽 Описание форматов данных: подраздел «Размещение объявлений данных» раздела 31.5 쐽 Документирование переменных: подраздел «Комментирование объявлений дан- ных» раздела 32.5 쐽 Создание классов: глава 6 Основные типы данных являются базовыми блоками для построения остальных типов данных. Эта глава содержит советы по применению чисел вообще, целых чисел, чисел с плавающей запятой, символов и строк, логических переменных, перечислимых типов, именованных констант и массивов. В заключительном раз- деле этой главы рассказано о создании собственных типов данных. Эта глава содержит рекомендации по предупреждению главных ошибок в приме- нении основных типов данных. Если вы уже ознакомились с основами, перехо- дите к концу главы, к обзору перечня допускаемых ошибок, а также к обсужде- нию нестандартных типов данных в главе 13. http://cc2e.com/1278 ГЛАВА 12 Основные типы данных 283 12.1. Числа в общем Далее дано несколько рекомендаций, позволяющих сократить число ошибок при использовании чисел. Избегайте «магических чисел» Магические числа — это обычные числа, такие как 100 или 47524, которые появля- ются в программе без объяснений. Если вы программируе- те на языке, поддерживающем именованные константы, ис- пользуйте их вместо магических чисел. Если вы не можете применить именованные константы, применяйте глобальные переменные, когда это возможно. Исключение магических чисел дает три преимущества. 쐽 Изменения можно сделать более надежно. Если вы используете именованные константы, нет нужды искать каждое из чисел 100, и вы не измените по ошиб- ке те из этих чисел, что ссылаются на что-либо иное. 쐽 Изменения сделать проще. Когда максимальное число элементов меняется со 100 на 200, используя магические числа, вы должны найти каждое число 100 и изменить его на 200. Если вы используете 100+1 или 100-1, вы также долж- ны найти и изменить все числа 101 и 99 на 201 и 199 соответственно. При использовании именованных констант вы просто меняете определение кон- станты со 100 на 200 в одном месте. 쐽 Ваша программа лучше читается. Конечно, в выражении: for i = 0 to 99 do ... можно предположить, что 99 определяет максимальное число элементов. А вот выражение: for i = 0 to MAX_ENTRIES-1 do ... не оставляет на этот счет сомнений. Даже если вы уверены, что это число ни- когда не изменится, применяя именованные константы, вы получите более читабельную программу. Применяйте жестко заданные нули и единицы по необходимости Зна- чения 0 и 1 используются для инкремента, декремента, а также в начале циклов при нумерации первого элемента массива. 0 в конструкции: for i = 0 to CONSTANT do ... вполне приемлем, так же как 1 в выражении: total = total + 1 Вот хорошее правило: используйте в программе как константы только 0 и 1, а любые другие числа определите как литералы с понятными именами. Ошибки деления на ноль Каждый раз, когда вы пользуетесь символом деления ( / в большинстве языков), думайте о том, может ли в знаменателе оказаться 0. Если такая возможность существует, напишите код, предупреждающий появление ошиб- ки деления на 0. Перекрестная ссылка О приме- нении именованных констант вместо магических чисел см. раздел 12.7. 284 ЧАСТЬ III Переменные Выполняйте преобразования типов понятно Убедитесь, что кто-нибудь, чи- тая вашу программу, поймет преобразования между разными типами данных, которые в ней встречаются. На языке C++ вы могли бы написать: y = x + (float) i а на Microsoft Visual Basic: y = x + CSng( i ) Эта практика поможет обеспечить однозначность ваших преобразований — раз- ные компиляторы по-разному конвертируют, а при таком подходе вы гарантиро- ванно получите то, что ожидали. Избегайте сравнений разных типов Если x — число с плавающей запятой, а i — целое, проверка: if ( i = x ) then ... почти гарантированно не сработает. К тому времени, когда компилятор опреде- лит каждый тип, который он хочет задействовать для сравнения, преобразует один из типов в другой, произведет ряд округлений и вычислит ответ, вы будете рады, если ваша программа вообще работает. Сделайте преобразования вручную, так чтобы компилятор мог сравнить два числа одного и того же типа, и точно знай- те, что нужно сравнивать. Обращайте внимание на предупреждения вашего компилято- ра Многие современные компиляторы сообщают о наличии разных типов чисел в одном выражении. Обращайте на это внимание! Каждый программист рано или поздно просит кого-нибудь помочь выследить надоедли- вую ошибку, а выясняется, что о ней все время предупреждал компилятор. Про- фессионалы высокого класса пишут свои программы так, чтобы исключить все предупреждения компилятора. Легче предоставить работу компилятору, чем вы- полнять ее самому. 12.2. Целые числа Учитывайте следующие рекомендации при применении целых чисел. Проверяйте целочисленность операций деления Когда используются целые числа, выражение 7/10 не равно 0,7. Оно обычно равно 0 или минус бесконечно- сти, или ближайшему целому, или… ну, вы понимаете. Результат зависит от выб- ранного языка. Это же относится и к промежуточным результатам. В реальном мире 10 * (7/10) = (10*7) / 10 = 7. Но не в мире целочисленной арифметики. 10 * (7/10) равно 0, потому что целочисленное деление (7/10) равно 0. Простейший способ исправить положение — преобразовать его так, чтобы операции деления выпол- нялись последними: (10*7) / 10. Проверяйте переполнение целых чисел При выполнении умножения или сло- жения необходимо принимать во внимание наибольшие возможные значения це- лых чисел. Для целого числа без знака это обычно 2 32 –1, а иногда и 2 16 –1, или 65 535. Проблема возникает, когда вы умножаете два числа, в результате чего получается Перекрестная ссылка Вариант этого примера см. в разделе 12.3. |