История элегантных программ

В наше время, время объектов и визуальных сред быстрой разработки, нас постоянно поздравляют с тем, что теперь программы могут писать даже непрофессионалы (читай: последние чайники). Я вас поздравляю - теперь программа, занимающая на диске 40 мегабайт, считается небольшой. Это, на мой взгляд, есть подтверждение того, что каждый должен заниматься своим делом: программист - программировать, а пользователь - пользоваться. Никакие объекты и визуальные среды не аннулируют старых добрых постулатов структурного программирования, гласящих, что хорошие программы надо писать в хорошем стиле.

В свое время знаменитый Дейкстра говорил, что язык Кобол надо запретить, а преподавание его считать преступлением против человечности вроде фашизма. Эти золотые слова не утратили своей актуальности и сейчас, когда в школах на уроках информатики юные души калечат изучением устаревших версий Бейсика. Пусть говорят, что с тех давних времен язык сильно изменился в лучшую сторону, но он по-прежнему остается лишенным и утонченной строгости Паскаля, и гибкости и мощи Си.

Преимущество же Паскаля в том, что он был создан специально для обучения структурному программированию и способен воспитать в начинающем программисте тот самый хороший стиль. Впрочем, если вы должного "программистского воспитания" не получили, не отчаивайтесь - я сам в свое время, еще в школе, перешел с Бейсика на Паскаль в течение одного месяца, и с тех пор не написал ни одной программы на Бейсике, поскольку в этом совершенно отпала нужда.

Стиль - очень важная и очень индивидуальная особенность программирования, и спор двух программистов о стиле обычно перерастает в кидание банановыми шкурками, а потому разговор об оном лучше начать с нейтральной территории - с истории программирования. Притчей во языцех стали теперь времена, когда программы приходилось писать в двоичных кодах. Тогда действительно был сделан важный, именно тем, что первый, шаг к упрощению программирования - замена двоичных кодов символьными мнемониками. Было добавлено новое свойство языков программирования - запоминаемость. Тогда же был сделан и следующий шаг - добавление макрорасширений, позволяющих сокращенно описывать повторяющиеся фрагменты программы, что сразу увеличило мощность языков.

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

 

При всех недостатках мощность и абстрактность облегчили труд программиста и позволили непосредственно заняться проблемой управляемости программ. Написанная на Ассемблере, а позже и на Фортране или родственном ему Бейсике, программа содержала такое количество команд перехода, что программисту приходилось рисовать блок-схемы, напоминающие, когда и куда передается управление.

Именно преодолению данной проблемы были посвящены теоретические войны 70-х. Результатом их стало появление структурного программирования, а также специальных структурных языков программирования, среди которых наибольшее распостранение получили Паскаль и Си. Основой данной идеологии является разбиение программы на модули, соответствующее разбиению основной задачи на множество небольших подзадач. Каждый модуль выполняет свою задачу независимо от других, и потому может быть описан и отлажен отдельно. Это облегчает программирование - весь нужный код можно держать в уме, к тому же упрощается распределение работы между программистами, вместе работающими над одной программой.

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

Ключевым моментом здесь является отказ от команды безусловного перехода, известной также под названием GOTO. Было доказано, что эта команда может быть в любом положении заменена структурными операторами передачи управления, в число которых входит условный оператор, операторы цикла и оператор выбора. Ограничив себя ими, вы значительно упростите логику программы, что немедленно скажется на производительности труда. Никакой выигрыш неструктурной программы в скорости не оправдает затрат труда на ее отладку.

Еще один ключевой момент - использование подпрограмм. На стадии разработки любой модуль, исходный код которого выходит за пределы экрана, рекомендуется выделять в подпрограмму. Это значительно увеличивает читабельность программы, особенно если не стесняться давать процедурам и переменным осмысленные имена вместо невнятных аббревиатур. На стадии профилирования, когда все уже будет работать как надо, в критических по скорости фрагментах вызовы подпрограмм можно будет развернуть, но до тех пор в процессе отладки гораздо проще будет отслеживать передачу управления в пределах одного экрана.

За рубежом теме стиля программирования посвящают целые монографии, и невозможно всю ее осветить в рамках одной статьи, но тем не менее, понимание изложенных мною основ структурного программирования сослужит вам неплохую службу при разработке программ более серьезных, нежели "Hello, world". Надеюсь, в дальнейшем еще вернуться к этой теме, ибо не только опыт важен в искусстве программирования, но и теоретическая подкованность.

Дмитрий БОРОДАЕНКО

Версия для печатиВерсия для печати

Номер: 

37 за 1997 год

Рубрика: 

Технологии программирования
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!