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

Голуб Ален И. - Веревка достаточной длины, чтобы... выстрелить с. Руководство по программированию. Автору удается сделать изложение столь серьезной темы живым и интересным за счет рассыпанного по тексту юмора и глубокого знания предмета


Скачать 1.36 Mb.
НазваниеРуководство по программированию. Автору удается сделать изложение столь серьезной темы живым и интересным за счет рассыпанного по тексту юмора и глубокого знания предмета
Дата12.06.2019
Размер1.36 Mb.
Формат файлаpdf
Имя файлаГолуб Ален И. - Веревка достаточной длины, чтобы... выстрелить с.pdf
ТипРуководство
#81349
страница3 из 17
1   2   3   4   5   6   7   8   9   ...   17
Часть
2
Общие проблемы разработки
программ
Эта часть книги содержит общие правила для процесса разработки программ и не касается деталей собственно языков Си и Си++. Я сделаю это в последующих частях.

Правила программирования на Си и Си++
32
15. Прежде всего, не навреди
Это правило касается сопровождения программ. Будучи ребенком, я читал научно-фантастический рассказ, в котором незадачливый путешественник во времени случайно наступает на доисторическую бабочку и, вернувшись в свое время, находит окружающий мир изменившимся ужасным образом. Это похоже на большие компьютерные программы, где тронь здесь что-то кажущееся незначительным — и где- то там вся программа перестает работать. Методы объектно- ориентированного проектирования существуют, прежде всего, для решения (или по крайней мере для облегчения решения) этой проблемы в будущем, но уже существуют миллионы строк старого кода, который сегодня нуждается в сопровождении.
Мне приходилось видеть людей, которые изменяют программу просто потому, что им не нравится, как она выглядит. Это не очень хорошая идея. Если вы не знаете всех частей программы, затрагиваемых изменением (а это почти невозможно), то не трогайте код. Вы можете вполне резонно возразить, что на самом деле ни одно из правил в этой книге не относится к сопровождению программ. Вы просто не можете менять существующий код в соответствии с каким-то методическом руководством (как бы вам этого ни хотелось), не вызывая риска непоправимого вреда. Представленные здесь правила полезны лишь в том случае, когда вы начинаете программу с нуля.
16. Редактируйте свою программу
17. Программа должна быть переписана не менее
двух раз
18. Нельзя измерять свою производительность
числом строк
Прежде, когда вы изучали английский в школе, то вам никогда не приходило в голову сдавать черновик письменного задания, если вы, конечно, рассчитывали на оценку выше тройки. Тем не менее, многие компьютерные программы являются просто черновиками и содержат столько же ошибок, сколько и черновики ваших сочинений. Все хорошие программы вначале написаны, а затем отредактированы с целью улучшения. (Конечно, я имею в виду "редактировать" в смысле "исправлять".)
Имейте в виду, что редактирование должно быть сделано по окончании, потому что неотредактированный текст программы, по сути,

Имена и идентификаторы
33 невозможно сопровождать (точно также, как и ваше неотредактированное сочинение было невозможно читать). Создатели программы знакомы с ее текстом и могут выполнить редактирование более эффективно, чем программист, занимающийся сопровождением, который сначала должен ее расшифровать перед тем, как выполнить какую-либо реальную работу.
К сожалению, это очень похоже на театральное шоу, когда кто-то пишет программу быстро, но не думая о сопровождении или об элегантности. "Ого, он выдает в два раза больше кода вдвое быстрее".
Учтите, что тот же бедный сопровождающий программист будет затем вынужден затратить в восемь раз больше времени, сокращая первоначальный размер программы наполовину и делая ее пригодной для использования. Число строк кода в день, как мера объема, не является мерилом производительности.
Если вам нужен другой, чем сопровождение, мотив, то имейте в виду, что редактирование может рассматриваться как процесс уменьшения чего-либо. Маленькие программы выполняются быстрее.
19. Вы не можете программировать в изоляции
Классическая книга Джеральда Уэйнберга "The Psychology of Computer
Programming" (New York: Van Nostrand Reinhold, 1971) содержит великолепную историю об автоматах с газированной водой.
Администрация одного вычислительного центра решила, что слишком много времени растрачивается сотрудниками у автоматов с газированной водой. Люди создают много шума и ничего при этом не делают, поэтому автоматы убрали. Через несколько дней консультанты на местах были настолько перегружены работой, что к ним стало невозможно обратиться.
Мораль состоит в том, что люди совсем не зря растрачивали время: оказывается, издавая весь этот шум, они помогали друг другу в решении проблем.
Изоляция может стать настоящей проблемой в группе объектно- ориентированного проектирования, которая по необходимости должна состоять из пользователей, проектировщиков, программистов, специалистов по документации и т.д., работающих совместно. Так как число программистов в этой группе часто меньше, чем в более традиционных проектных коллективах, то становится трудно найти кого- то, с кем можно обсудить проблемы; страдает производительность.
Подумайте о еженедельных вечеринках в вашей фирме, как средстве повышения производительности.

Правила программирования на Си и Си++
34
20. Пустые потери времени
Если вы не можете решить неподатливую проблему, то займитесь на некоторое время чем-либо другим. Программисты часто наиболее продуктивны, когда смотрят в окно, слоняются по коридорам с пустым выражением на своих лицах, сидят в кафе и пьют кофе с молоком, или иным способом "теряют время".
Я был студентом в те древние времена, когда персональным компьютером был Apple I, а серьезные студенты-программисты владели коробками S-100, которые вы программировали, вводя двоичные команды переключателями лицевой панели по одному байту за раз. (Если вы были счастливчик, то имели интерпретатор языка БЕЙСИК и терминал, сделанный из старого телевизора). Студенты делили PDP 11/70, работавшую под UNIX (которая отлично работала на 16-битовой машине с 64 Кбайт памяти — Боже мой! Как все с тех пор усовершенствовалось).
О возможности использования персонального компьютера для выполнения домашних заданий не было и речи.
На среднем занятии по программированию присутствовало от 40 до 80 человек, и одновременно проводилось шесть и более занятий. Поэтому, когда на занятии раздавалось задание, то вы хватали бумагу с ним и буквально опрометью бросались вниз в терминальный зал, где приковывали себя к компьютеру и начинали яростно программировать до тех пор, пока не выполняли свое задание. Это могло продолжаться несколько дней. Если вы отрывались поесть или поспать, то ваш терминал занимал другой, и у вас появлялась весьма реальная перспектива не уложиться в срок, отведенный на задание. Некоторые люди все еще продолжают программировать подобным способом.
Такая обстановка, конечно, не способствовала хорошо продуманному проектированию программ, поэтому большинство из этих программ были в четыре раза больше, чем необходимо, и требовали в два раза больше времени на отладку, чем требовалось. К тому же, количество строк кода, написанное за час, сокращается пропорционально количеству часов, которые вы просидели, глядя на экран. (Это иллюзия — думать, что вы можете достичь большей производительности, работая 12 часов в день вместо 8).
Однажды, будучи на последнем курсе, я был так расстроен, пытаясь решить одну проблему, о которую бился головой в течение примерно четырех часов, что с чувством отвращения завершил сеанс и выскочил на улицу. Примерно три минуты спустя, когда я спускался по холму за порцией сосисок, искомое решение неожиданно всплыло в моей голове.
Это было настоящим откровением: вы должны расслабиться, чтобы дать

Имена и идентификаторы
35 своему мозгу возможность работать. К сожалению, я не смог пробиться назад к компьютеру, поэтому я так никогда и не исправил свою ошибку, но, по крайней мере, понял, как должен работать тот процесс.
21. Пишите программу с учетом сопровождения —
вы специалист по сопровождению
Сопровождение начинается немедленно после завершения программы, а сопровождением на этой стадии обычно занимаетесь вы сами. Это хорошая мысль — осчастливить сопровождающего программиста.
Поэтому ваша первая забота о том, чтобы программа легко читалась.
Структура и назначение каждой строки должны быть избыточно ясны, и если это не так, то вам нужно добавить поясняющие комментарии.
Одной из причин того, что поиски математических доказательств корректности программ остаются донкихотством, заключается в том, что нет программ без ошибок. Каждая программа не только содержит ошибки, но и требования к ней меняются, как только программа начинает эксплуатироваться, и у пользователя появляются потребность в каких-то новых свойствах, что вызывает появление новых и усовершенствованных ошибок. Так как ошибки всегда с нами, то мы должны писать нашу программу так, чтобы их можно было легче искать.
Вы можете переформулировать настоящее правило таким образом: Не умничайте. Искусный код почти невозможно сопровождать.
21.1. Эффективность — часто просто пугало
Я потратил несколько часов, делая одну подпрограмму более "эффективной", и не останавливался, чтобы подумать о том, как часто эта подпрограмма будет вызываться, что является пустой потерей времени в том случае, когда программа вызывается лишь один или два раза. Ваша программа должна быть непременно настолько эффективной, насколько это возможно, но вашей первоочередной заботой является сопровождение, и вы не должны приносить читаемость в жертву на алтарь эффективности. Напишите программу сперва с учетом сопровождения, затем запустите свою программу под профайлером и определите, где на самом деле есть узкие места. Будучи вооружены реальной информацией, вы теперь знаете, где стоит обменять часть читаемости на скорость, и можете вернуться и сделать это изменение. Тем не менее, вы можете включить первоначальный текст в комментарий, чтобы не потерять его. Всегда имейте в виду, что любое количество подчисток на уровне текста программы не повысит эффективность так, как это сделает лучший алгоритм. Пузырьковая сортировка будет

Правила программирования на Си и Си++
36 выполняться медленно вне зависимости от того, насколько хорошо она запрограммирована.

Часть
3
Форматирование и документация
Форматирование важно; тексты на Си и Си++ и так достаточно тяжело читаются, чтобы ухудшать ситуацию еще и плохим форматированием.
Представьте, что вы пытаетесь прочесть книгу, текст которой не отформатирован: нет абзацных отступов, разделения абзацев пустой строкой, пробелов после знаков препинания и так далее. Сопровождение плохо отформатированной программы невозможно.
Я объединил правила форматирования и документации в одной части, потому что форматирование является одним из лучших инструментов документирования, имеющихся в вашем распоряжении.
Под "документацией", рассматривающейся в этой части книги, понимается документирование программ (т.е. комментарии, а не документация уровня пользователя). Его зря не относят к программированию, ведь хороший комментарий для вас — в буквальном смысле нить Ариадны.
Я сознаю, что дискуссии по вопросам форматирования и документации часто достигают религиозного накала. Имейте в виду, что приводимые здесь мной правила — только те, которыми я пользуюсь сам. Имеются и другие совершенно разумные методы работы. С другой стороны, кто-то не особо умный мне однажды сказал, что "не важно, какой стиль форматирования вы применяете, если вы применяете его постоянно".
Программа, которая постоянно форматируется плохо, хуже, чем понятная временами. Случайный просвет лучше, чем никакого.

Правила программирования на Си и Си++
38
22. Программа без комментариев ничего не стоит
Программа, на написание которой затрачен год, может использоваться в течение 10 лет. Вам придется затратить на сопровождение гораздо больше денег, чем вы выделили на первоначальную разработку, а программа без комментариев несопровождаема. "Блестящий" программист, который втрое быстрее, чем другие, пишет короткий, элегантный, но некомментированный текст программы, вам обойдется дорого. Какому-то менее талантливому программисту придется затратить в 10 раз больше времени, чем нужно, устраняя неизбежные ошибки.
Программисты, которые не могут писать по-английски (или на том языке, на котором говорят в стране, где предполагается осуществлять сопровождение), изготовляют часовые бомбы, а не компьютерные программы. Так как хорошая документация столь необходима для процесса сопровождения, то важно, чтобы программисты были способны ее написать. По этой причине начинающие программисты, имеющие диплом по филологии, истории или другой гуманитарной дисциплине, часто являются более предпочтительными, чем люди с дипломами по естественным наукам (математике, физике и т.п.). Специалисты по естественным наукам редко знают как писать, а большинство из них также не знают как программировать; они обучены тому, как запрограммировать алгоритм, а не как написать пригодную для сопровождения компьютерную программу.
К счастью, писать можно легко научиться. Конечно, если вы придерживаетесь правила "Сделай сначала комментарии", то вам придется писать все свои комментарии до начала программирования.
23. Располагайте программу и документацию вместе
Если документация отделена от текста программы, то ее очень трудно обновлять. Следовательно, основная часть вашей документации должна располагаться в комментариях, а не в отдельном документе.
Если вам на самом деле нужна отпечатанная документация высшего качества, то вы можете воспользоваться чем-нибудь похожим на систему
Web (для языка Паскаль) или CWeb (для языков Си и Си++) в комбинации с T
E
X
1
. Я пользуюсь подобной системой под названием
1
Web описана в книге Дональда Кнута ""The WEB System of Structured
Documentation" (Palo Alto: Stanford University Dept. of Computer Science, Report
No.STAN-CS-83-980, 1983). Система CWeb описана в книге Дональда Е. Кнута и
Сильвио Ливая "The CWeb System of Structured Documentation" (Reading: Addison
Wesley, 1994). Обе публикации не только описывают как работают эти системы, но

Форматирование и доку ментация
39 arachne, которая была разработана мной для того, чтобы писать свою книгу "Compiler Design in C". (Arachne документирует тексты на Си и
Си++, используя в качестве редактора troff). Все эти программы позволяют вам размещать исходный текст программы и документацию в одном файле. Вы можете выделить исходный текст для компиляции, или загрузить этот файл в текстовый процессор, чтобы напечатать единое руководство с исходным текстом и документацией. Эти системы позволяют осуществлять перекрестный поиск идентификаторов в программе и документации, позволяя вам прослеживать связи одной части программы с другой ("этот код используется вон там"), и так далее.
Так как для получения печатной версии используется обычный текстовый процессор, то вы можете делать то, чего непросто добиться в комментариях — вставлять рисунки, например.
24. Комментарии должны быть предложениями
Они должны быть хорошо составлены и иметь правильную пунктуацию, по возможности без сокращений. Не превращайте свои комментарии в секретный код, применяя странные сокращения и изобретая свой собственный грамматический строй. Вам также не должна требоваться нить Ариадны для расшифровки комментариев.
25. Пропустите свой исходный тест через систему
проверки орфографии
Ваши комментарии не только станут более читаемыми, этот метод побудит вас использовать в качестве имен переменных те, что легко читаются, т. к. являются обычными словами.
26. Комментарий не должен подтверждать
очевидное
Начинающие программировать на Си склонны попадать в эту ловушку.
Избегайте явно нелепых случаев типа:
++x; // увеличить x но мне также не нравятся комментарии типа:
хорошо демонстрируют это. В этих книгах документируются реальные тексты программ, реализующих указанные системы.
T
E
X является редакционно-издательской системой Кнута. Она имеется в нескольких коммерческих версиях.

Правила программирования на Си и Си++
40
/*-------------------------------------------
* Определения глобальных переменных:
*-------------------------------------------
*/
Любой средний программист знает, как выглядит определение.
27. Комментарий должен предоставлять только
нужную для сопровождения информацию
Особенно неприятным и бесполезным комментарием является декларативный заголовочный блок. Заголовок сам по себе не является злом, а совсем наоборот. Блок комментариев в начале файла, описывающий, что делается в файле, может быть довольно полезен.
Хороший блок говорит вам, какое свойство реализуется файлом, показывает список открытых (не статических) функций, сообщает вам, что эти функции делают и т.д.
Заголовки, которые мне не нравятся, имеют содержание, которое определяется указанием, обычно типа какого-то руководства по фирменному стилю. Такие заголовки обычно выглядят подобно листингу
1, увеличивая беспорядок посредством обильных количеств бесполезной информации за счет читаемости. Часто случается так, как на листинге 1, когда заголовок существенно больше самой программы. Также обычно, как в нашем случае, что текст программы или совершенно самодокументирован, или нужно добавить одну или две строки комментариев, чтобы он им стал. Хотя требование вышеуказанной бессмыслицы и может согревать душу деспота-руководителя, но для облегчения сопровождения оно мало что дает.
Листинг 1. Бесполезный заголовочный комментарий
1 /*-----------------------------------------––––––––--–--**
2 ** **
3 ** ДАТА: 29 февраля 2000 г. **
4 ** ФУНКЦИЯ: **
5 ** equal **
6 ** **
7 ** АВТОР: **
8 ** Джозеф Эндрюс **
9 ** **
10 ** ОПИСАНИЕ: **
11 ** Эта функция предназначена для сравнения двух строк **
12 ** на лексикографическое равенство. **
13 ** **
14 ** ИСКЛЮЧЕНИЯ: **
15 ** Функция не работает для строк Unicode. **
16 ** **
17 ** СПЕЦИАЛЬНЫЕ ТРЕБОВАНИЯ: **

Форматирование и доку ментация
41 18 ** нет. **
19 ** **
20 ** АРГУМЕНТЫ: **
21 ** char *s1; Указатель на первую сравниваемую строку **
22 ** char *s2; Указатель на вторую сравниваемую строку **
23 ** **
24 ** РЕЗУЛЬТАТЫ: **
25 ** Функция возвращает true, если строки-аргументы **
26 ** лексикографически идентичны. **
27 ** **
28 ** КОММЕНТАРИИ: **
29 ** нет. **
30 ** **
31 ** ПРИМЕЧАНИЯ ПО РЕАЛИЗАЦИИ: **
32 ** нет. **
33 ** **
34 ** ИСТОРИЯ ИЗМЕНЕНИЙ: **
35 ** **
36 ** АВТОР: Эндрюс, Джозеф **
37 ** ДАТА: 12, июль, 1743 **
38 ** ИЗМЕНЕНИЕ: Начальное состояние **
39 ** **
40 ** АВТОР: Джонс, Том **
41 ** ДАТА: 13, июль, 1743 **
42 ** ИЗМЕНЕНИЕ: Изменены имена аргументов со str1, str2. **
43 ** **
44 ** Вест текст программы в этом файле охраняется **
45 ** авторским правом. **
46 ** Copyright (c) Вымышленная корпорация **
47 ** Все права сохраняются. **
48 ** **
49 ** Никакая часть этой подпрограммы не может быть **
50 ** воспроизведена в любой форме без явного разрешения **
51 ** в трех экземплярах со стороны отдела Министерства **
52 ** сокращения персонала. Нарушители будут лишены своего **
53 ** старшего сына. **
54 **------------------------------------------------------**
55 */
56
inline
equal (
char
*s1,
char
*s2 )
57 {
58
return
!strcmp( s1, s2 ); // Возвращает истину, если
59 } // строки равны.
Действительная проблема заключается в том, что этот тип заголовков нарушает ряд других правил, таких как: "не комментируй очевидное",
"исключай неразбериху" и так далее. Тот минимум реальной информации, который содержится в этом заголовке, относится к системе регистрации изменений, а не к исходному тексту программы. Комментарии в программе должны сообщать вам сведения, полезные при сопровождении.

Правила программирования на Си и Си++
42
28. Комментарии должны быть в блоках
Комментарии в общем воспринимаются лучше, когда помещаются в многострочных блоках, которые чередуются с блоками текста программы.
Для этого комментарий должен описывать на высоком уровне, что делают несколько последующих строк кода. Если комментарии попадаются через строчку, то это похоже на чтение двух книг одновременно, причем по строке из каждой по очереди. И если программа, комментируемая вами, сложная, то вы можете воспользоваться сносками:
// Вот блочный комментарий, описывающий последующий блок
// программы. После общего резюме я описываю некоторые
// особенности:
//
// 1. Этот комментарий описывает, что происходит в строке
// с меткой 1
//
// 2. Этот комментарий описывает, что происходит в строке
// с меткой 2
//
// В точке 1 алгоритм устанавливается на ...
// here_is_the_code();
while
( some_condition )
{ this_code_is_rather_obscure(); /* 1 */
} more_stuff_here();
while
( some_condition )
{ this_code_is_also_obscure(); /* 2 */
}
29. Комментарии должны быть выровнены
вертикально
Выравнивайте начало и конец комментария вертикально в многострочных комментариях.
/* Первая строка,
* вторая строка,
* третья строка.
*/
Если ваш компилятор их поддерживает, то здесь помогут комментарии в стиле Си++:

Форматирование и доку ментация
43
// Первая строка,
// вторая строка,
// третья строка.
Есть две причины появления этого правила, они обе демонстрируются в последующей программе:
/********************************************************** void the_function( void )
Это многострочный комментарий, выполняющий все, что должен делать комментарий.
К сожалению, отсутствие слева вертикального столбца из звездочек затрудняет зрительное разделение комментария и программы
*********************************************************** void the_function( void )
{
// далее настоящая функция. code_goes_here();
}
/**********************************************************/
Во-первых, заметили ли вы, что я забыл поместить / в конце второй строки звездочек? Таким путем можно запросто терять целые функции.
Во-вторых, трудно заметить, где оканчивается комментарий и начинается текст программы. Исправьте обе ошибки следующим образом:
/***********************************************************
* void the_function( void )
*
* Это многострочный комментарий, выполняющий все, что должен
* делать комментарий.
*
* Вертикальный столбец из звездочек слева облегчает
* зрительное разделение комментария и программы
***********************************************************
*/
void
the_function(
void
)
{
// далее настоящая функция. code_goes_here();
}

Правила программирования на Си и Си++
44
30. Используйте аккуратные столбцы везде, где
можно
Так как форматирование по сути является видом комментирования, то это правило применяйте также и к тексту программы. Два следующих блока функционально одинаковы, но заметьте, насколько легче искать имена переменных во втором блоке, причем не из-за выравнивания комментариев, а потому что имена образовали аккуратный столбец:
int
x; // Опишите, что делает x.
unsigned long int
(*pfi)(); // Опишите, что делает pfi.
const char
*the_variable; // Опишите, что делает the_variable.
int
z; // Опишите, что делает z. x = 10; // Здесь идет комментарий. the_variable = x; // Здесь второй комментарий. z = x; // A здесь третий. по сравнению с:
int
x; // Опишите, что делает x.
unsigned long int
( *pfi )(); // Опишите, что делает pfi.
int
z; // Опишите, что делает z.
const char
*the_variable; // Опишите, что делает
// the_variable. x = 10; // Здесь идет комментарий. the_variable = x; // Здесь второй комментарий. z = x; // A здесь третий.
Вы можете рассматривать на этот вид форматирования как по сути "табличный", как если бы я создал таблицу со столбцами "тип", "имя" и "описание".
Другим хорошим местом для использования столбцов является список инициализации элементов в Си++, который я форматирую следующим образом: class derived : public base
{ string str;
const int
x; public: derived(
char
*init_str,
int
init_x ) {}
} derived::derived(
char
*init_str,
int
init_x )
:base( str, x )
,str ( init_str )
,x ( init_x )
{}

Форматирование и доку ментация
45
31. Не располагайте комментариев между именем
функции и открывающей скобкой
Основная сложность в следующем примере: foo(
int
x )
/* Не помещайте
* комментарий
* здесь. */
{
//...
} заключается в том, что тело функции может оканчиваться на следующей странице или не помещаться на одном экране. То есть читающий не может сказать, видит ли он прототип или действительное определение.
Поместите этот комментарий или до имени функции, или вставьте его в тело функции ниже открывающей скобки:
/* Или помещайте
** его здесь.
*/ foo(
int
x )
{
/* или здесь,
** с таким же отступом, что и у кода.
*/
}
32. Помечайте конец длинного составного оператора
чем-нибудь, имеющим смысл
Прежде всего, подобные комментарии в конце блока:
while
( a < b )
{
for
( i = 10; --1 >= 0; )
{ f( i );
} // for
} // while не дают ничего, кроме неразберихи, если блоки короткие. Я использую их только тогда, когда составной оператор слишком велик, чтобы поместиться на экран (в моем текстовом редакторе около 40 строк) или в нем столько уровней вложений, что я не могу понять суть происходящего.
Комментарии в конце блока обычно целесообразны в больших составных операторах, но мне приходилось часто видеть подобный код:

Правила программирования на Си и Си++
46
На первой странице:
while
( a < b )
{
while
( something_else() )
{
for
( i = 10; --1 >= 0; )
{
for
( j = 10; --j >= 0; )
{
// далее идет масса кода
На какой-то из последующих страниц:
} // for
} // for
} // while
} // while
Эти комментарии слишком кратки, чтобы быть полезными. Завершающие блок комментарии должны полностью описывать управляющий оператор.
Завершающие блок комментарии из предыдущего примера должны выглядеть таким образом:
} // for( j = 10; --j >= 0; )
} // for( i = 10; --1 >= 0; )
} // while( something_else() )
} // while( a < b )
Так как
#ifdef
почти всегда расположен на некотором расстоянии от
#endif
, то я всегда ставлю метку у
#endif
:
#ifndef
__SOMEFILE_H_
#define
__SOMEFILE_H_
// здесь следует 1000 строк программы
#endif
// __SOMEFILE_H_
То же самое я делаю с
#else
33. Располагайте в строке только один оператор
Нет абсолютно никакой причины упаковывать в одну строку столько операторов, сколько сможете, если только у вас нет намерения сделать программу нечитаемой. Если в строке больше одной точки с запятой, то что-то неверно. Не используйте запятую-оператор (даже если вы знаете, что это такое) по той же причине. Очевидным исключением является оператор
for
, все три части которого должны быть на одной строке.

Форматирование и доку ментация
47
34. Указывайте имена аргументов в прототипах
функций
Это особенно важно в определениях классов. Страницы руководств (и встроенных систем помощи) для программы, над которой вы старательно работаете, вряд ли существуют в тот момент, когда они вам нужны больше всего — когда вы начинаете разработку. Вы обычно получаете документацию из двух мест: комментариев, добавленных к настоящим функциям и заголовочных файлов. Из них обычно лучше заголовочный файл, как более компактный. В любом случае из документации, которая на самом деле нужна по функции, вам необходимо знать порядок и число аргументов, а легче всего найти эту информацию в прототипе функции.
Если ваш прототип похож на этот: some_function(
int
,
int
,
int
,
int
,
int
); то вам не удастся получить много помощи.
35. Используйте "предикатную" форму при
разбиении длинных выражений
"Предикатом" в английском языке называется вторая половина предложения — глагол и дополнение, над которым глагол выполняет действие. Порядок слов в английском предложении, конечно, фиксированный: глагол всегда идет первым.
Многие компьютерные языки имитируют структуру английского языка
(языки Си и Си++ попадают в эту категорию). Паскаль, например, даже повторяет пунктуацию английского предложения: с точкой с запятой, отделяющей независимые операторы, и точкой на конце. Вызов функции является хорошим примером предикатной формы: глагол является именем функции, а прямые дополнения (вещи, на которые действует глагол) являются аргументами.
Вы также можете посмотреть на операторы типа глагола, потому что они выполняют некоторое действие над операндами ("объектами"). Это разумно, поэтому используйте ту же самую схему, что и в английском предложении, если вам нужно разбить длинное выражение на несколько строк. Помещайте сначала глагол (оператор):
if
( its_thursday_and_the_moon_is_in_scorpio()
||its_friday_afternoon_and_close_to_quitting_time()
||i_just_cant_bear_to_look_at_this_computer_for_another_minute()
)
{ go_home();
}

Правила программирования на Си и Си++
48
Конечно, вы можете добиться большего, просто сократив имена подпрограмм до чего-то более приемлемого, так чтобы все они поместились на одной строке.
Заметьте, как я расположил круглые и фигурные скобки в предыдущем примере с целью придания его структуре большей ясности. И при этом я использовал фигурные скобки, хотя язык этого не требовал, для облегчения поиска оператора, связанного с
if
. Следующий текст программы читается с большим трудом, потому что хуже видно, где заканчивается
if
и начинается оператор:
if
( its_thursday_and_the_moon_is_in_scorpio()
||its_friday_afternoon_and_close_to_quitting_time()
||i_just_cant_bear_to_look_at_this_computer_for_another_minute()) go_home();
36. Подпрограмма должна помещаться на экране
Затраты на вызов подпрограмм в Си/Си++ невелики; если для функции указано ключевое слово
inline
, то затрат фактически нет. Поэтому хорошая мысль состоит в том, чтобы создавать подпрограммы удобного в обращении размера и использовать их в больших количествах. Имя подпрограммы позволяет добиваться значительной абстракции. Если имена выбраны правильно, то у вас зачастую можете исчезнуть нужда в комментариях.
Вообще, мне нравится, когда рабочая часть подпрограммы (ее текст, в меньшей степени комментарии заголовка и так далее) видна полностью при редактировании; она должна целиком помещаться на экране или в окне.
37. Нужно обеспечивать возможность распечатки
всего текста программы
Часто проще найти ошибку на распечатанной странице, чем на экране, даже на большом. Текст на бумаге легче читается вследствие более высокого разрешения и лучшего фокусного расстояния, чем на экране.
При этом вы можете разложить бумажные распечатки по всей поверхности стола. Вы вряд ли чем-нибудь сможете заменить бумагу в этом плане, если только у вас нет монитора с диагональю полтора метра и разрешением 300 точек на дюйм.
Итак, ваша программа должна легко печататься. Подпрограммы должны помещаться по возможности на одной странице (не более 60 строк), и ни одна строка программы не должна быть такой длины, чтобы не поместиться в строку распечатки (около 79 символов, в зависимости от

Форматирование и доку ментация
49 шрифта), даже если ваш текстовый редактор поддерживает скроллинг по горизонтали. Если вы выйдете за эти пределы, то будете вынуждены использовать столь мелкий шрифт для вывода, что совсем не сможете прочитать свою распечатку.
38. Используйте штриховую линию для зрительного
разделения подпрограмм
Я всегда ставлю такой комментарий:
//--------------------------------------------------------- над каждым определением функции. (И к тому же, я не использую штриховую линию нигде более). Хотя пустые строки замечательно подходят для зрительного разделения блоков программы, исключительно их использование не дает эффекта. Штриховая линия между функциями облегчает их поиск. Так же как пустая строка указывает на границу абзаца, штриховые линии подобны заголовкам разделов. Если мне нужно еще более четкое разделение, то я использую:
//==========================================================
//ОПИСЫВАЮЩИЙ ТЕКСТ
//==========================================================
Подумайте об этом, как о заголовке для главы. Я стараюсь не помещать никаких комментариев, за исключением штриховых линий, вне функции, потому что такие комментарии затрудняют обнаружение определений этой функции. При этом я форматирую функции следующим образом:
//---------------------------------------------------------
void
descriptive_name( type descriptive_name )
{
// Если имена функции и аргументов недостаточно содержа-
// тельны, то я помещаю здесь комментарий, описывающий,
// что она делает. Я опускаю этот комментарий, если имена
// достаточно понятны. (Соответствующее правило гласит:
// "Не объясняй очевидного").
//
// Затем я описываю возвращаемое значение и аргумент.
// И вновь вы можете не использовать комментарий, если
// имена достаточно удачные.
//
// Наконец, я помещаю здесь комментарий, описывающий, как
// функция делает то, что она делает. И снова я пропускаю
// этот комментарий, если программа сама по себе достаточно
// содержательна. code_goes_here();
}

Правила программирования на Си и Си++
50
39. Пробел — один из наиболее эффективных
комментариев
Это кажется мелочью, но это может чрезвычайно улучшить читаемость вашей программы. Обратите внимание, как используются пробелы в этой книге в качестве организующего средства, и вы поймете, как использовать их в своей собственной программе. Пустые строки (или отступ в первой строке) зрительно разделяют абзацы. Пробел следует за точкой, но не должен ей предшествовать, потому что точка завершает что-либо. Идея вам ясна. А вот правила:

Разбивайте текст программы на логические куски (т.е. абзацы), где каждый кусок выполняет одну операцию. Окружите эти куски или пустыми строками, или строками с фигурными скобками.

За знаком препинания всегда должен идти пробел.

Операторы являются сокращениями слов. Когда вы видите "+", то говорите "плюс". Подобно любому сокращению, вы должны окружать идентификатор пробелами. (Например: a + b читается "a плюс b", a+b читается "aплюсb").

Исключение составляют унарные операторы, которые рассматриваются как словарные префиксы или суффиксы
(*p
, a--
, f(arg,arg)
и т.д.).

или
->
в Си/Си++ являются эквивалентом символа подчеркивания.
До и после них пробелов быть не должно: p->msg()
, obj.msg()
Вот пример того, что может произойти, когда вы что-нибудь упаковываете слишком плотно. Рассмотрим:
int
*p; y=(x/*p++); f(int /* вставка */);
Если вы удалите комментарии, то получите:
int
*p; y=(x
);
Сочетание
/*
в выражении y=(x/*p++)
расценивается как символ начала комментария, который заканчивается сочетанием
*/
в вызове функции f()
. (Такой случай действительно со мной произошел, и мне потребовался целый день, чтобы в нем разобраться. Естественно, компилятор не давал сообщений об ошибках, потому что здесь все синтаксически правильно).

Форматирование и доку ментация
51
Еще замечание по данному поводу. Мне часто приходилось позднее видеть объявления подобные следующему:
int
* x;
Проблема состоит в том, что:
int
* x, y; не объявляет два указателя, как подсказывает распределение пробелов.
Здесь мы имеем на самом деле еще одну проблему из рода "я могу на любом языке программирования писать как на ФОРТРАНЕ". Было бы прекрасно, если бы Си работал так же, как подсказывает предыдущее форматирование, но это не так. После правильного форматирования
int
*x, y; становится совершенно ясно, что x
— указатель, а y
— нет.
40. Используйте отступы в четыре пробела
Никлас Вирт, который изобрел языки Паскаль и Модула-2, однажды выпустил книгу, где всюду использовались отступы в один символ.
Чтение â íåé листингов ñòàëî îäíèì из самых тяжелых случаев в моей практике. Используйте достаточно большие отступы, чтобы ваш читатель мог сказать, что в тексте видно абзацы; четыре пробела кажутся идеальными.
Вы должны делать отступы последовательно. Даже во внешнем блоке подпрограммы должны быть отступы. Такой вариант неприемлем:
void
f(
void
)
{ if( x ) yyy(); more_code(); even_more_code();
} потому что слишком трудно найти начало подпрограммы. Сравните предыдущий вариант со следующим:
void
f(
void
)
{
if
( x ) yyy(); more_code(); even_more_code();
}

Правила программирования на Си и Си++
52
41. Условные операторы выделяются абзацными
отступами
Я делаю это даже в операторах из одной строки:
if
( by_land ) one();
else
two(); а не так:
if
( by_land ) one()
else
two();
Очевидным исключением является:
if
( by_land )
{ one();
}
else if
( by_sea )
{ two();
}
else if
( by_air )
{ three();
}
Я использовал здесь скобки по двум причинам. Во-первых, я как-то попал внутрь условного оператора при отладке и забыл вставить скобки, как в следующем тексте:
if
( by_land ) one();
if
(debug) printf("Ох...");
else if
( by_sea ) что привело привело фактически к:
if
( by_land ) one();
if
(debug) printf("Ох...");
else
if
( by_sea )
Со скобками программа к тому же лучше читается. Я часто нарушаю правило абзацных отступов, когда использую форматирование для того, чтобы показать с кристальной ясностью, что происходит. Аккуратные столбцы делают это осуществимым:

Форматирование и доку ментация
53
if
( by_land ) one();
else if
( by_sea ) two();
else if
( by_tunnel ) three(); но это — нечитаемо:
if
(by_land)one();
else if
(by_sea)two();
else if
(by_tunnel)three();
Подобный код никуда не годится:
for
( a ; b ; c );
while
( ++i < 10 );
Слишком просто случайно сделать следующее:
while
( i < 10 );
++i;
(Другими словами, "вечно сравнивать i
с
10
, затем увеличить i
"). Если точка с запятой никогда не ставится в конце строки, начинающейся с
for
или
while
, то вы можете использовать утилиту поиска строки типа grep для обнаружения таких проблем.
41.1. Комментарии должны иметь тот же отступ, что
и окружающий текст программы
Абзацные отступы предназначены для того, чтобы сделать структуру вашей программы легко понятной. Если вы организуете отступы в комментариях беспорядочным образом, то этим вы лишите их смысла.
Комментарий в следующей программе должен быть снабжен отступами: f()
{
/* Здесь идет
** длинный комментарий
*/ code();
}
Здесь имеется сходная проблема: f()
{
int
local_var;
int
another_local_var; code();
}
Отсутствие отступа при определении локальных переменных заставляет предположить, что они находятся в той же области видимости, что имя

Правила программирования на Си и Си++
54 функции (которая является глобальной). Так как это не так, то вы должны сделать отступ, чтобы указать на область видимости: f()
{
int
local_var;
int
another_local_var; code();
}
42. Выравнивайте скобки вертикально по левой
границе
Иногда поиск отсутствующей фигурной скобки превращается в крупную проблему. Если вы вынесете скобки туда, где их хорошо видно, то их отсутствие будет сразу же заметно:
while
( some_condition )
{
// внутренний блок
}
Я в самом деле не люблю так называемый стиль Кэрнигана и Ричи:
if
( condition ){ code();
}
else
{ more_code();
}
Здесь не только трудно проверить скобки на парность, но и отсутствие зрительного разделения за счет строк, содержащих лишь открытые скобки, ведет к ухудшению читаемости.
43. Используйте скобки, если в условном операторе
имеется более, чем одна строка
Это правило применяется, если даже дополнительными строками является комментарий. Проблема заключается в том, что слишком легко случайно добавить другой оператор и забыть добавить скобки. Текст, подобный нижеследующему, более надежен:
if
( something() )
{
*/ Quo usque tandem abutere Gatesalina, patientia nostra


"До каких же пор ты, Катилина, будешь испытывать наше терпение..." — начало известной речи Цицерона. — Прим. перев.

Форматирование и доку ментация
55
*/ somethig_else();
}

1   2   3   4   5   6   7   8   9   ...   17


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