Главная страница

Совершенный код. Совершенный код. Мастер-класс. Стив Макконнелл. Руководство по стилю программирования и конструированию по


Скачать 5.88 Mb.
НазваниеРуководство по стилю программирования и конструированию по
АнкорСовершенный код
Дата31.03.2023
Размер5.88 Mb.
Формат файлаpdf
Имя файлаСовершенный код. Мастер-класс. Стив Макконнелл.pdf
ТипРуководство
#1028502
страница88 из 106
1   ...   84   85   86   87   88   89   90   91   ...   106
ГЛАВА 31 Форматирование и стиль
719
Цели хорошего форматирования
Многие решения о том, как должно выглядеть хорошее фор#
матирование, представляют собой субъективные эстетичес#
кие оценки; часто можно достичь одной и той же цели по#
разному. Вы можете сделать споры о субъективных вопро#
сах менее субъективными, если явно укажете критерии ва#
ших предпочтений. Говоря объективно, хорошая схема фор#
матирования должна делать следующие вещи.
Точно представлять логическую структуру кода Сно#
ва повторим Основную теорему форматирования: главная цель хорошего форматирования — показать логическую структуру кода. Для демонстрации логической структуры программисты обычно применяют отступы и другие не#
отображаемые символы.
Единообразно показывать логическую структуру кода Некоторые стили форматирования состоят из правил с таким количеством исключений, что по#
следовательно их соблюдать практически невозможно. Действительно хороший стиль подходит в большинстве случаев.
Улучшать читабельность Стратегия использования отступов, соответствую#
щая логике, но усложняющая процесс чтения кода, бесполезна. Схема формати#
рования, использующая пробелы и разделители только там, где они требуются ком#
пилятору, логична, но читать такой код невозможно. Хорошая структура форма#
тирования упрощает чтение кода.
Выдерживать процедуру исправления Лучшие схемы форматирования хо#
рошо переносят модификацию кода. Исправление одной строки не должно при#
водить к изменению нескольких других.
В дополнение к этим критериям иногда во внимание принимается и задача ми#
нимизации количества строк кода, необходимых для реализации простого выра#
жения или блока.
Как воспользоваться принципами хорошего форматирования на практике
Критерии хорошей схемы форматирования могут служить основой для обсуждения возможных вариантов форматов, помогая отличить субъек#
тивные причины в предпочтении одного стиля форматирования перед другим
Оценка критерия с нескольких точек зрения может привести к разным выводам.
Так, если вы твердо убеждены, что минимизация количества строк кода очень важна
(вероятно, потому, что у вас маленький монитор), вы можете критиковать один стиль только за то, что для списка параметров метода он использует на две стро#
ки больше, чем какой#то другой.
Эксперименты выявили хруп- кость программистской квали- фикации: опытные программис- ты имеют стойкие представления о том, как должны выглядеть программы, и, если эти убежде- ния нарушаются — казалось бы,
даже безобидными способами,
— их производительность ради- кально ухудшается.
Эллиот Соловей
и Кейт Эрлих
(Elliot Soloway
and Kate Ehrlich)

720
ЧАСТЬ VII Мастерство программирования
31.2. Способы форматирования
Вы можете получить хороший формат кода, по#разному используя несколько инструментов для форматирования.
Неотображаемые символы
Используйтенеотображаемыесимволыдляулучшениячитаемости. Неотображаемые символы, к которым относятся пробелы, знаки табуляции, переводы строк и пус#
тые строки, — это основное средство для демонстрации структуры программы.
Вам вряд ли придет в голову писать книгу без пробелов между словами, разбиения на абзацы и деления на главы. Может,
такую книгу и можно прочитать от начала до конца, но прак#
тически невозможно просматривать ее в поисках какой#то мысли или важного эпизода. Еще хуже, что такой формат книги не позволит показать читателю, как автор намеревал#
ся организовать информацию. Структура, предлагаемая ав#
тором, дает подсказку о логической организации темы.
Разбиение книги на главы, абзацы и предложения показывает читателю, как сле#
дует мысленно организовывать тему. Если эта организация неочевидна, читате#
лю приходится самому ее домысливать, что налагает на него более тяжкое бремя и увеличивает вероятность никогда не узнать, как на самом деле организована данная тема.
Информация, содержащаяся в программе, сосредоточена еще плотней, чем инфор#
мация в большинстве книг. Если страницу книги можно прочесть и понять за 1
или 2 минуты, то большинство программистов не могут читать и понимать лис#
тинг программы со скоростью, даже приблизительно сравнимой с этой. Программа должна давать гораздо больше подсказок о своей организации, чем книга.
Группировка Еще один способ применения неотображаемых символов — груп#
пировка взаимосвязанных выражений
В литературе мысли группируются в абзацы. Хорошо написанный абзац содер#
жит предложения, относящиеся только к определенной идее. Он не должен со#
держать посторонних предложений. Точно так же абзац кода должен содержать только взаимосвязанные операторы, выполняющие одно задание.
Пустые строки Кроме необходимости группировать взаимосвязанные опера#
торы, очень важно отделять несвязанные выражения друг от друга. Начало ново#
го абзаца в книге обозначается отступом или пустой строкой. Начало нового аб#
заца в коде нужно указывать с помощью пустой строки.
Пустые строки позволяют продемонстрировать организацию программы. Вы можете использовать их для деления групп взаимосвязанных операторов на аб#
зацы, отделения методов друг от друга и выделения комментариев.
Хотя эту статистику тяжело применить на практике, но одно исследова#
ние показало, что оптимальное число пустых строк в программе состав#
ляет от 8% до 16%. Если оно больше 16%, то время, затрачиваемое на от#
ладку, заметно увеличивается (Gorla, Benander and Benander, 1990).
Перекрестная ссылка Некото- рые исследователи проводят аналогии между структурой книги и структурой программы
(см. подраздел «Книжная пара- дигма документирования про- грамм» раздела 32.5).

ГЛАВА 31 Форматирование и стиль
721
Отступы Применяйте отступы для демонстрации логической структуры про#
граммы. Как правило, операторы выделяются отступами, когда они следуют пос#
ле некоторого выражения, от которого они логически зависят.
Существуют данные, что отступы влияют на способность программиста понимать код. В статье «Program Indentation and Comprehensibility» со#
общается, что некоторые исследования выявили корреляцию между на#
личием отступов и способностью к пониманию кода (Miaria et al., 1983). В тесте на понимание испытуемые показали результат на 20–30% лучше, когда програм#
мы использовали схему отступов из 2–4#х пробелов, чем когда программы вооб#
ще не содержали отступов.
То же исследование выявило, что нельзя не только недостаточно выде#
лять, но и чрезмерно подчеркивать логическую структуру программы.
Меньше всего баллов за понимание получили программы, совсем не со#
держащие отступов. Второй с конца результат принадлежал программам, исполь#
зующим отступы из 6 пробелов. Авторы пришли к выводу, что оптимальными яв#
ляются отступы из 2–4#х пробелов. Интересно, что многим испытуемым отступы из 6 пробелов показались удобнее, чем другие, даже несмотря на то, что оконча#
тельный результат оказался хуже. Возможно, это связано с тем, что отступы из 6
пробелов выглядят приятнее. Но независимо от того, насколько красиво они вы#
глядят, отступы из 6 пробелов оказались хуже читаемыми. Это один из примеров коллизии между эстетикой и читабельностью.
Скобки
Используйте скобки чаще, чем вам это кажется необходимым. Применяйте скоб#
ки для разъяснения выражений, состоящих из двух и более членов. Возможно, в скобках нет нужды, но они добавляют ясности и ничего вам не стоят. Например,
скажите, как вычисляются следующие выражения?
Вариант на C++: 12 + 4% 3 * 7 / 8
Вариант на Microsoft Visual Basic: 12 + 4 mod 3 * 7 / 8
Пришлось ли вам задуматься о том, как эти выражения вычисляются, вот в чем вопрос? Можете ли вы быть уверенными в своем ответе без обращения к спра#
вочной информации? Даже опытные программисты не отвечают с полной уверен#
ностью, и именно поэтому следует использовать скобки, если есть хоть малейшее сомнение в том, как вычисляется выражение.
31.3. Стили форматирования
Большинство вопросов форматирования касается размещения блоков — групп операторов, располагающихся под управляющими выражениями. Блок окружен скобками или ключевыми словами:
{ и } в C++ и Java, if%then%endif в Visual Basic и другими похожими структурами в других языках. Для простоты в большей части этого обсуждения используются общие обозначения
begin и end. Я предполагаю,
что вы поймете, как это можно соотнести со скобками в C++ и Java или анало#
гичными механизмами выделения блоков в других языках. Ниже описаны четы#
ре основных стиля форматирования:

722
ЧАСТЬ VII Мастерство программирования

явные блоки;

эмуляция явных блоков;

использование пар
begin%end (скобок) для обозначения границ блока;

форматирование в конце строки.
Явные блоки
Большинство споров по поводу форматирования возникает из#за несовершенства большинства популярных языков программирования. Хорошо спроектированный язык имеет явную структуру блоков, которая приводит к естественному стилю отступов. Так, в Visual Basic у каждой управляющей структуры есть свой термина#
тор, и вы не сможете ее использовать без этого терминатора. Код разбивается на блоки естественным образом. Несколько примеров на Visual Basic приведено в листингах 31#6, 31#7 и 31#8:
Листинг 31-6. Пример явного блока if (Visual Basic)
If pixelColor = Color_Red Then statement1
statement2
End If
Листинг 31-7. Пример явного блока while (Visual Basic)
While pixelColor = Color_Red statement1
statement2
Wend
Листинг 31-8. Пример явного блока case (Visual Basic)
Select Case pixelColor
Case Color_Red statement1
statement2
Case Color_Green statement1
statement2
Case Else statement1
statement2
End Select
Управляющая структура на Visual Basic всегда состоит из начального выражения
(в этих примерах —
If%Then, While и Select%Case) и всегда содержит соответствую#

ГЛАВА 31 Форматирование и стиль
723
щий оператор
End. Отступы внутри такой структуры не подвергаются сомнению,
а варианты выравнивания других ключевых слов частично ограничены. Листинг
31#9 показывает абстрактное представление того, как выглядит такой вид форма#
тирования:
Листинг 31-9. Абстрактный пример стиля форматирования явного блока
A XXXXXXXXXXXXXXXXXXXX
B XXXXXXXXXXXX
C XXXXXXXXXXXXXXX
D XXXX
В этом примере управляющая конструкция начинается оператором A и кончает#
ся оператором D. Выравнивание между этими двумя операторами обеспечивает визуальное единство конструкции.
Дебаты по поводу форматирования управляющих структур частично возникают потому, что некоторые языки не
требуют применения блоковых структур. Вы можете использовать оператор
if%then, за которым следует единственное выраже#
ние, а не формальный блок. Для создания блока вам приходится добавлять пару
begin%end или открывающую и закрывающую скобки вместо их автоматического получения с каждой управляющей структурой. Отделение
begin и end от самой структуры — так, как языки, подобные C++ и Java, делают это со скобками
{ и }, —
приводит к вопросу: куда поместить эти
begin и end? Поэтому меньше проблемы с отступами становятся проблемами только потому, что вам приходится компен#
сировать недостатки плохо спроектированных языковых структур. Способы та#
кой компенсации описаны ниже.
Эмуляция явных блоков
Хорошим подходом в языках, не имеющих явных блоков, будет рассмотрение ключевых слов
begin и end (или символов { и }) в виде расширений управляющих структур, с которыми они используются. Далее, имеет смысл попробовать сэму#
лировать форматирование языка Visual Basic на вашем языке. Листинг 31#10 со#
держит абстрактное представление визуальной структуры, которую вы пытаетесь эмулировать:
Листинг 31-10. Абстрактный пример стиля форматирования явного блока
A XXXXXXXXXXXXXXXXXXXX
B XXXXXXXXXXXX
C XXXXXXXXXXXXXXX
D XXXX
При таком стиле управляющая конструкция открывает блок в операторе A и за#
крывает блок в операторе D. Это предполагает, что
begin должен находиться в конце оператора A, а
end должен быть оператором D. Говоря абстрактно, для эмуляции явных блоков вам надо сделать нечто, подобное листингу 31#11:

724
ЧАСТЬ VII Мастерство программирования
Листинг 31-11. Абстрактный пример эмуляции стиля явного блока
A XXXXXXXXXXXXXX{X
B XXXXXXXXXXXXXX
C XXXXXXXXXXXXXXXXX
D }X
Несколько примеров такого стиля на C++ приведено в листингах 31#12, 31#13 и
31#14:
Листинг 31-12. Пример эмуляции явного блока if (C++)
if ( pixelColor == Color_Red ) {
statement1;
statement2;
}
Листинг 31-13. Пример эмуляции явного блока while (C++)
while ( pixelColor == Color_Red ) {
statement1;
statement2;
}
Листинг 31-14. Пример эмуляции явного блока switch/case (C++)
switch ( pixelColor ) {
case Color_Red:
statement1;
statement2;
break;
case Color_Green:
statement1;
statement2;
break;
default:
statement1;
statement2;
break;
}
Этот стиль выравнивания вполне функционален. Он хорошо выглядит, его мож#
но применять единообразно, а также его удобно сопровождать. Он соответствует
Основной теореме форматирования в том плане, что помогает показать логичес#
кую структуру кода. Это вполне разумный вариант стиля. Такой стиль является стандартом в Java и широко распространен в C++.
{
}

ГЛАВА 31 Форматирование и стиль
725
Использование пар begin-end (скобок)
для обозначения границ блока
Альтернативой структуре явного блока может служить использование пар
begin%
end в качестве границ блока. (В дальнейшем обсуждении пары begin%end приме#
няются для общего обозначения операторов
begin%end, скобок и других эквива#
лентных языковых структур.) Если вы берете за основу этот подход, то рассмат#
риваете
begin и end как операторы, следующие за управляющей структурой, а не как фрагменты, являющиеся ее частью. Графически это выглядит идеально, так же,
как и при эмуляции явного блока, приводимой еще раз в листинге 31#15:
Листинг 31-15. Абстрактный пример стиля форматирования явного блока
A XXXXXXXXXXXXXXXXXXX
B XXXXXXXXXXXX
C XXXXXXXXXXXXXX
D XXXX
Но для того, чтобы в новом стиле
begin и end трактовались как составные части структуры блока, а не управляющего выражения, надо поместить
begin в начало блока (а не в конец управляющего выражения), а
end — в конец блока (а не в ка#
честве терминатора управляющего выражения). Говоря абстрактно, вам нужно сделать нечто, подобное структуре, изображенной в листинге 31#16:
Листинг 31-16. Абстрактный пример использования begin и end в качестве границ блока
A XXXXXXXXXXXXXXXXXXXX
{XXXXXXXXXXXXXXXX
B XXXXXXXXXXXXXXXXX
C XXXXXXXXXXXXXXXXX
}X
Несколько примеров использования
begin и end в качестве границ блоков, пока#
зано в листингах 31#17, 31#18 и 31#19:
Листинг 31-17. Пример применения begin и end в качестве границ блока if (C++)
if ( pixelColor == Color_Red )
{
statement1;
statement2;
}
Листинг 31-18. Пример применения begin и end в качестве границ блока while (C++)
while ( pixelColor == Color_Red )
{
statement1;
statement2;
}
}
{

726
ЧАСТЬ VII Мастерство программирования
Листинг 31-19. Пример применения begin и end в качестве
границ блока switch/case (C++)
switch ( pixelColor )
{
case Color_Red:
statement1;
statement2;
break;
case Color_Green:
statement1;
statement2;
break;
default:
statement1;
statement2;
break;
}
Такой стиль выравнивания также вполне функционален и согласуется с Основ#
ной теоремой форматирования (напомним: он показывает логическую структу#
ру, лежащую в основе данного кода). Единственное его ограничение в том, что его нельзя применять буквально в операторах
switch/case в C++ и Java, что пока#
зано в листинге 31#19. (Ключевое слово
break служит заменой закрывающей скобке,
а у открывающей скобки нет эквивалента.)
Форматирование в конце строки
Еще одна стратегия форматирования называется «форматированием в конце стро#
ки», и объединяет большую группу методик, в которых отступ в коде делается к середине или концу строки. Отступы в конце строки служат для выравнивания блока относительно ключевого слова, с которого он начинается, выравнивания следующих параметров метода под первым параметром, размещения вариантов в операторе
case и подобных случаев. Листинг 31#20 представляет абстрактный пример:
Листинг 31-20. Абстрактный пример стиля форматирования в конце строки
A XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
B XXXXXXXXXXXXXXX
C XXXXXXXXXXXXXXX
D XX
В этом примере оператор A начинает управляющую конструкцию, а оператор D
завершает. Операторы B, C и D выровнены под ключевым словом, с которого на#
чинается блок в операторе A. Одинаковые отступы B, C и D показывают, что эти операторы сгруппированы вместе. Листинг 31#21 содержит менее абстрактный пример кода, отформатированного в соответствии с этой стратегией:

ГЛАВА 31 Форматирование и стиль
727
Листинг 31-21. Пример форматирования в конце строки в блоке while (Visual Basic)
While ( pixelColor = Color_Red )
statement1;
statement2;
Wend
В этом примере
end помещен в конец строки, а не под соответствующим ключе#
вым словом. Некоторые предпочитают располагать
end под ключевым словом, но выбор между этими двумя вполне приемлемыми вариантами — наименьшая из проблем этого стиля.
Стиль форматирования в конце строки иногда работает вполне удовлетворительно.
Листинг 31#22 демонстрирует пример, в котором этот стиль работает:
Листинг 31-22. Редкий пример, в котором форматирование
в конце строки выглядит привлекательно (Visual Basic)
If ( soldCount > 1000 ) Then markdown = 0.10
profit = 0.05
Ключевое слово else выровнено относительно слова then, расположенного над ним.
Else markdown = 0.05
End If
В этом случае ключевые слова
Then, Else и End If выровнены, и код, следующий за ними,
также выровнен. Визуальный эффект соответствует ясной логической структуре.
Критически взглянув на приводимый ранее пример
case#оператора, вы, вероят#
но, сможете указать на недостаток данного стиля. По мере усложнения условного выражения этот стиль начнет давать бесполезные или обманчивые подсказки о логической структуре кода. В листинге 31#23 приведен пример ухудшения этого стиля при его применении в более сложном условном выражении:
Листинг 31-23. Более типичный пример, в котором
форматирование в конце строки является неудачным решением (Visual Basic)
If ( soldCount > 10 And prevMonthSales > 10 ) Then
If ( soldCount > 100 And prevMonthSales > 10 ) Then
If ( soldCount > 1000 ) Then markdown = 0.1
profit = 0.05
Else markdown = 0.05
End If
Else markdown = 0.025
End If
Else markdown = 0.0
End If
>

728
ЧАСТЬ VII Мастерство программирования
В чем причина причудливого форматирования выражений
Else в конце примера?
Они последовательно выровнены под соответствующими ключевыми словами, но вряд ли можно утверждать, что такие отступы проясняют логическую структуру.
И если при модификации кода изменится длина первой строки, такой стиль фор#
матирования потребует изменения отступов во всех соответствующих выражениях.
Так что возникает проблема сопровождения, которой не существует для стилей явных блоков, их эмуляции и использования пар
begin%end для обозначения гра#
ниц блоков.
Вы можете решить, что эти примеры придуманы лишь в демонстрационных це#
лях, но такой стиль применяется очень упорно, несмотря на все его недостатки.
Масса учебников и справочников по программированию рекомендует этот стиль.
Самая первая увиденная мной книга, содержащая эту рекомендацию, была опуб#
ликована в середине 1970#х, последняя — в 2003 году.
Вообще форматирование в конце строки неаккуратно, его сложно применять еди#
нообразно и тяжело сопровождать. Далее я приведу другие проблемы такого стиля.
Какой стиль наилучший?
При работе в Visual Basic используйте отступы для явных блоков (тем более что в среде разработки Visual Basic затруднительно не придерживаться этого стиля).
В Java стандартной практикой является применение формата явных блоков.
В C++ можно просто выбрать тот стиль, который вам больше нравится или кото#
рому отдают предпочтение большинство разработчиков вашей команды. Как эмуля#
ция явных блоков, так и обозначение границ с помощью
begin%end работает оди#
наково хорошо. Единственное исследование, сравнивавшее эти два стиля, не об#
наружило статистически значимых различий между ними с точки зрения понят#
ности кода (Hansen and Yim, 1987).
Ни один из этих стилей не обеспечивает защиты от дурака, и оба время от време#
ни требуют «разумного и очевидного» компромисса. Вы можете предпочесть тот или иной стиль по эстетическим причинам. В этой книге в примерах кода при#
меняется стиль явных блоков, так что вы можете увидеть массу иллюстраций это#
го стиля, просто просмотрев листинги. Выбрав однажды стиль, вы получите наи#
большую выгоду от хорошего форматирования, применяя его единообразно.
31.4. Форматирование управляющих структур
Форматирование некоторых программных элементов час#
то является только эстетическим вопросом. Однако форма#
тирование управляющих структур влияет на удобство чте#
ния и понимания и поэтому имеет практическое значение.
Тонкие моменты форматирования
блоков управляющих структур
Работа с блоками управляющих структур требует внимания к деталям. Вот неко#
торые советы.
Перекрестная ссылка О доку- ментировании управляющих структур см. подраздел «Ком- ментирование управляющих структур» раздела 32.5. О дру- гих аспектах управляющих структур см. главы 14–19.

1   ...   84   85   86   87   88   89   90   91   ...   106


написать администратору сайта