Жанр: Учеба
Правила программирования на Си и Си плюс плюс.
...ения
являются также показателем небрежного мышления. Поэтому первый шаг в
написании любой программы - записать то, что делает программа, и как
она это делает.
Есть разные мнения о возможности мышления вне языка, но я убежден,
что аналитическое мышление того типа, который нужен в компьютерном
программировании, тесно связано с языковыми навыками. Я не думаю, что
является случайностью то, что многие из знакомых мне лучших
программистов имеют дипломы по истории, филологии и схожим наукам.
Процесс проект ирования 23
Также не является случайностью то, что некоторые из виденных мной
худших программ были написаны инженерами, физиками и математиками,
затратившими в университете массу энергии на то, чтобы держаться как
можно дальше от занятий по языку и литературе.
Сущность заключается в том, что математическая подготовка почти не
нужна в компьютерном программировании. Тот тип организационного
мастерства и аналитических способностей, который нужен для
программирования, связан полностью с гуманитарными науками. Логика,
например, преподавалась на философском факультете, когда я был в
университете. Процесс, используемый при проектировании и написании
компьютерных программ, почти полностью идентичен тому, который
используется, чтобы сочинять и писать книги. Процесс программирования
совсем не связан с теми процессами, которые используются для решения
математических уравнений.
Здесь я делаю различие между информатикой (computer science) -
математическим анализом компьютерных программ - и
программированием или разработкой программного обеспечения -
дисциплиной, интересующейся написанием компьютерных программ.
Программирование требует организационных способностей и языковой
подготовки, а не абстрактного мышления, необходимого для занятий
математическим анализом. (В университете меня заставили проходить год
на лекции по математическому анализу, но я никогда из него ничего не
использовал ни на занятиях по информатике, хотя для них матанализ был
необходимым условием, ни в реальной жизни).
Я как-то получил открытую рецензию на книгу, посвященную мной
предмету проектирования компиляторов, в которой рецензент (который
преподавал в одном из ведущих университетов) заявил, что он "считает
абсолютно неуместным включение исходного кода компилятора в книгу о
проектировании компиляторов". По его мнению, необходимо учить
"фундаментальным принципам" - лежащей в основе математике и теории
языка, а детали реализации - "тривиальны". Первое замечание имеет
смысл, если у вас создалось впечатление, что книга написана ученымспециалистом
по информатике, а не программистом. Рецензент
интересовался лишь анализом компилятора, а не тем как его написать.
Второе замечание просто показывает вам, насколько изолировала себя
научная элита от реального труда программирования. Интересно, что
основополагающая работа по теории языка, сделавшая возможным
написание компиляторов, была выполнена в Массачусетском
технологическом институте лингвистом Наумом Хомским, а не
математиком.
Правила программирования на Си и Си++
24
Обратной стороной этой медали является то, что если вы зашли в тупик
при решении проблемы, один из лучших способов выйти из него - это
объяснить проблему приятелю. Почти всегда решение возникает в вашей
голове посредине объяснения.
6.1. Начинайте с комментариев
Если вы последовали совету в предыдущем правиле, то комментарии для
вашей программы уже готовы. Для того, чтобы получить
документированное описание реализации, вы просто писали и добавляли
вслед за каждым абзацем блоки кода, реализующие качества, описанные в
этом абзаце. Оправдание "у меня не было времени, чтобы добавить
комментарии" на самом деле означает "я писал этот код без проекта
системы и у меня нет времени воспроизвести его". Если создатель
программы не может воспроизвести проект, то кто же сможет?
7. Читайте код
Все писатели - это читатели. Вы учитесь, когда смотрите, что делают
другие писатели. Удивительно, но программисты - писатели на Си++ и Си
- часто не читают код. Тем хуже. Я настоятельно рекомендую, чтобы, как
минимум, члены группы программирования читали код друг друга.
Читатель может найти ошибки, которые вы не увидели, и подать мысль,
как улучшить код.
Идея здесь - не формальная "критика кода", имеющая довольно
сомнительный характер: никто не хочет наступать на ногу коллеге, поэтому
шансы получить полезную обратную связь в формальной ситуации малы.
Для вас лучше присесть с коллегой и просто разобрать код строка за
строкой, объясняя что как делается и получая какую-то обратную связь и
совет. Для того, чтобы подобное упражнение принесло пользу, автор кода
не должен делать никаких предварительных пояснений. Читатель должен
быть способен понимать код, читая его. (Нам всем приходилось иметь дело
с учебниками, столь трудными для понимания, что ничего нельзя было
понять без объяснения преподавателя. Хотя это и гарантирует, что
преподаватель не останется без работы, но никак не отражается на авторе
учебника). Если вам пришлось объяснять что-то вашему читателю, то это
значит, что ваше объяснение должно было быть в коде в виде комментария.
Добавьте этот комментарий, как только вы его произнесли; не
откладывайте этого до окончания просмотра.
Процесс проект ирования 25
7.1. В цехе современных программистов нет места
примадоннам
Это следствие из правила чтения. Программисты, которые думают, что их
код совершенен, которые отвергают критику, вместо того, чтобы считать ее
полезной, и которые настаивают на том, что они должны работать
втихомолку, вероятно, пишут тарабарщину, не поддающуюся
сопровождению - даже если кажется, что она работает. (Смысловое
ударение здесь на слове кажется).
8. Разбивайте сложные проблемы на задачи меньшего
размера
На самом деле это также правило и литературного стиля. Если концепцию
слишком сложно объяснить за один раз, то разбейте ее на меньшие части и
объясняйте каждую по очереди. То же назначение у глав в книге и
параграфов в главе.
Как пример, связанный с программированием, возьмем прошитое
бинарное дерево, отличающееся от нормального дерева тем, что указатель
на узел-потомок в концевом узле указывает на само дерево.
Действительным преимуществом прошитого дерева является то, что его
легко пересечь нерекурсивно при помощи этих дополнительных
указателей. Проблема заключается в том, что сложно выйти из алгоритмов
пересечения (в особенности обратного пересечения). С другой стороны,
имея указатель на узел, легко написать алгоритм поиска последующего
элемента в обратном порядке. Путем изменения формулировки с
"выполнить пересечение в обратном порядке" на "начав с самого
отдаленного узла, искать последующие элементы в обратном порядке, пока
они не закончатся" получаем разрешимую задачу:
tree t; // дерево
node = postorder_first( t ); // исходный узел
while
( node ) // есть еще узлы?
node = postorder_successor( t ); // следующий узел-родитель
9. Используйте весь язык
9.1. Используйте для работы соответствующий
инструмент
Данное правило является спутником правила "Не путайте привычность с
читаемостью", представленного ниже, но скорее больше касается проблем
руководства. Мне часто говорят, что студентам не разрешается
Правила программирования на Си и Си++
использовать некоторые части Си или Си++ (обычно это указатели),
потому что они "нечитаемы". Обычно это правило навязывается
руководителями, знающими ФОРТРАН, БЕЙСИК или какой-то другой
язык, не поддерживающий указатели, ибо их не очень-то заставишь изучать
Си. Вместо того, чтобы допустить, что их знания недостаточны, такие
руководители будут лучше калечить своих программистов. Указатели
отлично читаемы для программистов на Си.
И наоборот, я видел ситуации, где руководство требовало, чтобы
программисты перешли с языка программирования типа КОБОЛ на Си, но
не желало оплачивать переподготовку, необходимую для перехода. Или
хуже, руководство платило за переподготовку, но не предоставляло
времени, необходимого для действительного изучения материала.
Переподготовка является занятием, требующим всего рабочего дня. Вы не
можете одновременно выполнять "полезную" работу, а если попытаетесь,
то ваши деньги будут выброшены на ветер. Так или иначе, после того, как
руководители видят, что их работники не были превращены в гуру
программирования на Си++ после 3-дневного краткого курса, они
реагируют, накладывая ограничения на использование некоторых частей
языка. Фактически говоря "вы не можете использовать ту часть Си++,
которая не похожа на язык, который мы использовали до перехода на
Си++". Естественно, что будет нельзя эксплуатировать ни одну из
прогрессивных особенностей языка - которые прежде всего и являются
главной причиной его использования - если вы ограничите себя
"простейшим" подмножеством особенностей.
Глядя на эти ограничения, мне в первую очередь интересно знать, зачем
было менять КОБОЛ на Си. Принуждение программистов на языке КОБОЛ
использовать Си всегда поражало меня своей большой глупостью. КОБОЛ
- великолепный язык для работы с базами данных. У него есть
встроенные примитивы, упрощающие выполнение задач, которые довольно
трудны для Си. Си, в конце концов, был разработан для создания
операционных систем, а не систем управления базами данных. Довольно
просто дополнить КОБОЛ, чтобы он поддерживал модный графический
интерфейс пользователя, если это единственная причина перехода на Си.
10. Проблема должна быть хорошо продумана перед
тем, как она сможет быть решена
Это правило с двумя последующими первоначально располагалось в начале
этой главы. Подумав, я переместил их сюда, так как побоялся, что,
прочитав их, вы пропустите оставшуюся часть главы. Однако в мои
намерения не входит чтение проповедей. Эти правила посвящены весьма
Процесс проект ирования 27
реальным проблемам и во многих отношениях являются самыми важными
правилами в этой книге.
Настоящее правило является настолько очевидным утверждением в
повседневной жизни, что кажется странным его восприятие как едва ли не
ереси применительно к программированию. Мне часто говорят, что
"невозможно потратить пять месяцев на проектирование, не написав ни
одной строки кода - ведь наша производительность измеряется числом
строк кода, написанных за день". Люди, говорящее это, обычно знают, как
делается хороший проект; просто у них нет этой "роскоши".
Мой опыт говорит, что хорошо спроектированная программа не только
работает лучше (или просто работает), но и может быть написана быстрее и
быть проще в сопровождении, чем плохо спроектированная. Лишние
четыре месяца при проектировании могут сэкономить вам более четырех
месяцев на этапе реализации и буквально годы в период сопровождения.
Вам не добиться высокой производительности, если приходится
выбрасывать прошлогоднюю работу из-за существенных изъянов проекта.
Кроме того, скверно спроектированные программы труднее реализовать.
Тот аргумент, что у вас нет времени на проектирование, потому что вы
"должны захватить рынок программ как можно скорее", просто не
выдерживает никакой критики, потому что реализация плохого (или
никакого) проекта требует гораздо больше времени.
11. Компьютерное программирование является
индустрией обслуживания
Меня иногда шокирует неуважение, проявляемое некоторыми
программистами по отношению к пользователям своих программ, как если
бы "пользователь" (произносится с презрительной усмешкой) был низшей
формой жизни, неспособной к познавательной деятельности. Но факт
состоит в том, что весь компьютер существует лишь с одной целью:
служить конечному пользователю наших продуктов. Если никто бы не
пользовался компьютерными программами, то не было бы программистов.
Печальным фактом является то, что существенно больше половины
разрабатываемого ежегодно кода выбрасывается за ненадобностью. Такие
программы или никогда не поступают в эксплуатацию, или используются
лишь очень короткое время, после чего выбрасываются. Это означает
невероятную потерю производительности, сокращая для большинства
управляющих реальные среднесуточные цифры выработки. Подумайте о
всех начинающих фирмах, выпускающих программы, которые никогда не
будут проданы, о всех внутрифирменных группах разработчиков, пишущих
бухгалтерские пакеты, которыми нельзя пользоваться.
Правила программирования на Си и Си++
Посмотри в окно!
Чтобы сохранить великий дар природы — зрение,
врачи рекомендуют читать непрерывно не более 45–50 минут,
а потом делать перерыв для ослабления мышц глаза.
В перерывах между чтением полезны
гимнастические упражнения: переключение зрения с ближней точки на более дальнюю.
Легко увидеть, как возникает эта печальная ситуация: программисты
создают программы, которые никому не нужны. Исправить ее тоже легко,
хотя это и сталкивается с неожиданными трудностями в некоторых
условиях: спросите людей, что им нужно, и затем сделайте то, что они вам
сказали.
К сожалению, многие программисты производят впечатление полагающих,
что конечные пользователи не знают, чего хотят. Вздор! Почти всегда
пользователи оказываются так запуганы сыплющим специальными терминами
"экспертом", что замолкают. Мне часто говорили: "Я знаю, что мне
нужно, но не могу это выразить". Лучший ответ на это: "Отлично, скажите
это на нормальном языке - я сделаю перевод на компьютерный".
12. Вовлекайте пользователей в процесс
проектирования
13. Заказчик всегда прав
Ни одной программе не добиться успеха, если ее проектировщики не
общаются непосредственно с ее конечными пользователями. Несмотря на
это, часто ситуация больше напоминает игру ("испорченный телефон"), в
которую многие из нас играли в детском саду и при которой 20 ребятишек
садятся в кружок. Кто-нибудь шепчет фразу своему соседу (соседке),
который передает ее своему, и так далее по кругу. Забава заключается в
том, чтобы послушать, как сообщение звучит после того, как пройдет весь
круг - обычно ничего похожего на исходную фразу. Тот же самый
процесс часто встречается при разработке программ. Пользователь говорит
с управляющим, докладывающим другому управляющему, который
нанимает консультационную фирму. Президент консультационной фирмы
разговаривает с руководителем разработчиков, который в свою очередь
говорит со старшим группы, обращающимся, наконец, к программистам.
Шансы на то, что даже простой документ с требованиями останется после
этого процесса невредимым, равны нулю. Единственным решением этой
проблемы является тесное вовлечение пользователей в процесс разработки,
лучше всего путем включения, по крайней мере, одного конечного
пользователя в команду разработчиков.
Родственная ситуация складывается в случае простой самонадеянности
части программистов, которые говорят: "Я знаю, что пользователи сказали,
что им нужно сделать это таким способом, но у них нет достаточных
знаний о компьютерах, чтобы принять сознательное решение; мой способ
лучше". Такое отношение фактически гарантирует, что программой
никогда не будут пользоваться. Исправить ситуацию здесь можно,
Процесс проект ирования 29
официально назначив конечного пользователя лицом, оценивающим
качество проекта. Никто не может начать писать код до тех пор, пока
пользователь-член команды не даст на это добро. Сотрудники,
игнорирующие проект в пользу своих идей, должны быть уволены. В
реальной жизни для подобного типа детского упрямства на самом деле нет
места.
При этом нужно сказать, что опытный проектировщик зачастую
предлагает лучшее решение проблемы, чем то, что придумано конечным
пользователем, в особенности, если учесть, что конечные пользователи
часто предлагают интерфейсы, созданные по образцу программ, которыми
они постоянно пользуются. Несмотря на это, вы должны убедить
пользователя, что ваш способ лучше, перед тем, как его реализовать.
"Лучший" интерфейс не является лучшим, если никто, кроме вас, не
сможет (или не захочет) им пользоваться.
14. Малое - это прекрасно (большое == медленное)
Распухание программ является огромной проблемой. Жесткий диск
вместимостью 350 Мбайт на моем лэптопе может вместить операционную
систему, усеченные версии моих компилятора и редактора и больше
ничего. В стародавние времена я мог разместить версии для CP/M тех же
программ на единственной дискете вместимостью 1,2 Мбайта. UNIX в то
время спокойно работал на 16-разрядном PDP-11 c 64 Кбайтами ядра
(внутренней памяти). В наше время большинство операционных систем
требуют 32-разрядных машин с минимум 16 Мбайтами оперативной
памяти, чтобы работать с приемлемой скоростью. Я убежден, что б ольшая
часть этого распухания памяти является результатом небрежного
программирования.
В добавок к проблеме размера у вас также есть проблема со временем
выполнения. Виртуальная память не является настоящей памятью. Если
ваша программа слишком велика, чтобы поместиться в оперативной
памяти, или если она выполняется одновременно с другими программами,
то она должна периодически подкачиваться с диска. На эти подкачки,
мягко выражаясь, расходуется время. Чем меньше программа, тем менее
вероятно, что произойдет подкачка, и тем быстрее она будет выполняться.
Третьей проблемой является модульность. Одна из основ философии
UNIX гласит "меньше - лучше". Большие задачи лучше выполняются
взаимодействующей системой маленьких модульных программ, каждая из
Уже не редкость емкость дисковой памяти, превышающая спустя 5 лет указанные
автором значения на два порядка, а оперативной - на порядок. - Прим.перев.
Правила программирования на Си и Си++
которых делает хорошо лишь одно задание, но каждая из них может
сообщаться с другими компонентами. (Стандарт связи и внедрения
объектов Microsoft (OLE) добавляет это свойство в Windows, а OpenDoc -
в Macintosh). Если ваше приложение представляет собой модульную
конструкцию из маленьких программ, работающих вместе, то становится
очень просто настраивать вашу программу по заказу путем смены модулей.
Если вам не нравится этот редактор, то поменяйте его на новый.
Наконец, программы обычно уменьшаются в процессе
усовершенствования. Большие программы, вероятно, никогда не
подвергались усовершенствованиям.
Разыскивая решение этой проблемы, я заметил, что коллективы
программистов с плохим руководством часто создают излишне большие
программы. То есть группа ковбоев от программирования, каждый из
которых работает в одиночку в своем офисе и не разговаривает с другими,
напишет массу лишнего кода. Вместо одной версии простой служебной
функции, используемой по всей системе, каждый программист создаст
свою версию одной и той же функции.
Часть
Общие проблемы разработки
программ
Эта часть книги содержит общие правила для процесса разработки
программ и не касается деталей собственно языков Си и Си++. Я сделаю
это в последующих частях.
Правила программирования на Си и Си++
15. Прежде всего, не навреди
Это правило касается сопровождения программ. Будучи ребенком, я читал
научно-фантастический рассказ, в котором незадачливый путешественник
во времени случайно наступает на доисторическую бабочку и,
вернувшись в свое время, находит окружающий мир изменившимся
ужасным образом. Это похоже на большие компьютерные программы, где
тронь здесь что-то кажущееся незначительным - и где-то там вся
программа перестает работать. Методы объектно-ориентированного
проектирования существуют, прежде всего, для решения (или по крайней
мере для облегчения решения) этой проблемы в будущем, но уже
существуют миллионы строк старого кода, который сегодня нуждается в
сопровождении.
Мне приходилось видеть людей, которые изменяют программу просто
потому, что им не нравится, как она выглядит. Это не очень хорошая
идея. Если вы не знаете всех частей программы, затрагиваемых
изменением (а это почти невозможно), то не трогайте код. Вы можете
вполне резонно возразить, что на самом деле ни одно из правил в этой
книге не относится к сопровождению программ. Вы просто не можете
менять существующий код в соответствии с каким-то методическом
руководством (как бы вам этого ни хотелось), не вызывая риска
непоправимого вреда. Представленные здесь правила полезны лишь в том
случае, когда вы начинаете программу с нуля.
16. Редактируйте свою программу
17. Программа должна быть переписана не менее
двух раз
18. Нельзя измерять свою производительность
числом строк
Прежде, когда вы изучали английский в школе, то вам никогда не
приходило в голову сдавать черновик письменного задания, если вы,
конечно, рассчитывали на оценку выше тройки. Тем не менее, многие
компьютерные программы являются просто черновиками и содержат
столько же ошибок, сколько и черновики ваших сочинений. Все хорошие
программы вначале написаны, а затем отредактированы с целью
улучшения. (Конечно, я имею в виду "редактировать" в смысле
"исправлять".)
Имейте в виду, что редактирование должно быть сделано по
окончании, потому что неотредактированный текст программы, по сути,
Имена и идент ификат оры 33
невозможно сопровождать (точно также, как и ваше неотредактированное
сочинение было невозможно читать). Создатели программы знакомы с ее
текстом и могут выполнить редактирование более эффективно, чем
программист, занимающийся сопровождением, который сначала должен
ее расшифровать перед тем, как выполнить какую-либо реальную работу.
К сожалению, это очень похоже на театральное шоу, когда кто-то
пишет программу быстро, но не думая о сопровождении или об
элегантности. "Ого, он выдает в два раза больше кода вдвое быстрее".
Учтите, что тот же бедный сопровождающий программист будет затем
вынужден затратить в восемь раз больше времени, сокращая
первоначальный размер программы наполовину и делая ее пригодной для
использования. Число строк кода в день, как мера объема, не является
мерилом производительности.
Если вам нужен другой, чем сопровождение, мотив, то имейте в виду,
что редактирование может рассматриваться как процесс уменьшения
чего-либо. Маленькие программы выполняются быстрее.
19. Вы не можете программировать в изоляции
Классическая книга Джеральда Уэйнберга "The Psychology of Computer
Programming" (New York: Van Nostrand Reinhold, 1971) содержит
великолепную историю об автоматах с газированной водой.
Администрация одного вычислительного центра решила, что слишком
много времени растрачивается сотрудниками у автоматов с газированной
водой. Люди создают много шума и ничего при этом не делают, поэтому
автоматы убрали. Через несколько дней консультанты на местах были
настолько перегружены работой, что к ним стало невозможно обратиться.
Мораль состоит в том, что люди совсем не зря растрачивали время:
оказывается, издавая весь этот шум, они помогали друг другу в решении
проблем.
Изоляция может стать настоящей проблемой в группе объектноориентированного
проектирования, которая по необходимости должна
состоять из пользователей, проектировщиков, программистов,
специалистов по документации и т.д., работающих совместно. Так как
число программистов в этой группе часто меньше, чем в более
традиционных проектных коллективах, то становится трудно найти когото,
с кем можно обсудить проблемы; страдает производительность.
Подумайте о еженедельных вечеринках в вашей фирме, как средстве
повышения производительности.
Правила программирования на Си и Си++
20. Пустые потери времени
Если вы не можете решить неподатливую проблему, то займитесь на
некоторое время чем-либо другим. Программисты часто наиболее
продуктивны, когда смотрят в окно, слоняются по коридорам с пустым
выражением на своих лицах, сидят в кафе и пьют кофе с молоком, или
иным способом "теряют время".
Я был студентом в те древние времена, когда персональным
компьютером был Apple I, а серьезные студенты-программисты владели
коробками S-100, которые вы программировали, вводя двоичные команды
переключателями лицевой панели по одному байту за раз. (Если вы были
счастливчик, то имели интерпретатор языка БЕЙСИК и терминал,
сделанный из старого телевизора). Студенты делили PDP 11/70,
работавшую под UNIX (которая отлично работала на 16-битовой машине
с 64 Кбайт памяти - Боже мой! Как все с тех пор усо
...Поділитися у соцмережах