Добавить в цитаты Настройки чтения

Страница 22 из 28



Что касается быстродействия, то оптимизирующие трансляторы ныне выдают программы, работающие быстрее, чем большинство программ, написанных в машинных кодах. Более того, проблема быстродействия обычно может быть решена следующим образом: после отладки программы, выданной транслятором, часть ее (от 1% до 5%) заменяют вручную написанной вставкой5).

Какой язык высокого уровня следует использовать для системного программирования? Единственным разумным кандидатом является PL/I6). Он обладает очень полным набором функций и отвечает разнообразию ситуаций операционной системы. Существует множество трансляторов с этого языка, среди них есть и диалоговые, в том числе очень быстрые, обладающие также богатыми разновидностями диагностики ошибок, и, наконец, производящие хорошо оптимизированную машинную программу. Сам я считаю, что алгоритмы удобнее и быстрее разрабатывать на APL; затем я их транслирую на PL/I, чтобы обеспечить согласование с системными требованиями.

Диалоговое программирование. Одним из обоснований проекта Multics, реализованного в MIT, была его полезность при разработке систем программ. Проект Multics (и вслед за ним система TSS, созданная IBM) отличается от других диалоговых вычислительных систем как раз теми своими качествами, которые необходимы для системного программирования: несколько уровней совместного использования и защиты данных и программ, широкие возможности работы с библиотеками и средства, обеспечивающие совместную работу со многих терминалов. Я убежден, что во многих областях использования вычислительных машин системы типа Multics никогда не смогут заменить систем пакетной обработки. Но я думаю, что коллектив, создавший Multics, наиболее убедительно доказал жизнеспособность своих идей именно в приложении к системному программированию.

Пока еще существует не слишком много очевидных доказательств плодотворного использования этих, по-видимому, эффективных инструментов программиста. Широко известно, однако, что отладка - это очень трудная и медленная часть системного программирования, я медленная оборачиваемость проклятие отладки. Поэтому логика доводов в пользу диалогового программирования представляется неоспоримой7).

И далее, мы слышали хорошие отзывы от многих людей, разрабатывающих таким способом небольшие системы или части систем. Единственные известные мне цифры относительно программирования больших систем принадлежат Дж. Харру из фирмы Bell Labs. Они приведены в табл. 12.1. Эти цифры относятся к написанию, ассемблированию и отладке программ системы электронной коммутации. Данные Харра свидетельствуют о том, что диалоговые возможности по крайней мере удваивают производительность системного программирования8).

Таблица 12.1

Эффективное использование большинства диалоговых средств требует, чтобы работа велась на языке высокого уровня, поскольку телетайпы и терминалы нельзя использовать для отладки путем разгрузки памяти. Используя язык высокого уровня, легко редактировать программу и получать избирательные распечатки.

Язык высокого уровня и диалоговое программирование, вместе взятые, действительно представляют собой острые инструменты.

XIII. ЦЕЛОЕ ИЗ ЧАСТЕЙ

"Я духов вызывать могу уз бездны".

"И я могу и каждый это может. Вопрос лишь, явятся лъ они на зов".

(Ш е к с п и р, "Генрих IV" )

Среди современных магов не перевелись хвастуны:



"Я могу написать программы, которые управляют движением самолетов, перехватывают баллистические ракеты, ведут банковские счета, руководят производственными линиями". На это следует ответ: "И я могу, и каждый это может, но будут ли эти программы работать после того, как Вы их напишете?".

Как создается работоспособная программа? Как отлаживается программа? И как объединяется множество отлаженных программ-компонентов в проверенную и надежную систему? Мы эпизодически касались этих методов; теперь настала пора рассмотреть их более систематично.

Проект без ошибок

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

Подобную же роль играет подробная и тщательная разработка архитектуры, присущая этому подходу. В. А. Выссотски руководитель проекта Safeguard в фирме Bell Telephone Laboratories, утверждает: "Гвоздь проблемы состоит в том, чтобы описать продукт. Многие и многие неудачи вызваны теми его аспектами, которые не были как следует специфицированы"'). Аккуратное описание функций, тщательная спецификация и последовательное изгнание всяческих украшательств как в функциях, так и в методиках позволяет сократить число системных ошибок, которые предстоит отыскать в дальнейшем.

Проверка спецификаций. Задолго до появления первых строк программы следует передать спецификации на скрупулезную проверку их полноты и ясности группе независимых специалистов. Как говорит Выссотски, сами разработчики не в состоянии этого сделать: "Они ни за что не скажут вам, что есть неясности; они будут увлеченно придумывать собственные пути через все пропасти и темные места".

Нисходящее проектирование. В 1971 г. появилась прекрасная работа Н. Вирта, в которой он формализовал процедуру проектирования, и с тех пор лучшие программисты пользуются ею. Более того, его идеи, первоначально сформулированные для разработки программ, полностью применимы к проектированию сложных систем. Разбиение процесса создания системы на архитектуру, разработку п реализацию является основополагающим в его идеях; и, далее, архитектура, разработка и реализация лучшим образом осуществляются с помощью нисходящих методов.

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

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

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

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

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