Страница:
Программа сдана заказчику, по изменения в нее гродолжают вноситься. Внесение изменений в программу после ее сдачи называется сопровождением программы, однако этот процесс существенно отличается от эксплуатации оборудования.
Эксплуатация оборудования для вычислительной системы сводится к замене плохих элементов, к чистке и смазке и к внесению технических изменений, исправляющих дефекты разработки. (Не все, но большая часть технических изменений исправляет именно дефекты реализации или разработки, а не архитектуры, так что они незаметны для пользователя.)
Сопровождение программы не влечет за собой чистки, смазки или ремонта. Оно сводится в основном к внесению изменений, исправляющих дефекты разработки. Однако гораздо чаще, чем в случае оборудования, такие изменения включают в себя добавление новых функций. Обычно они прекрасно видны пользователю.
Стоимость сопровождения широко используемой программы составляет обычно 40 процентов стоимости ее разработки. Что удивительно, стоимость эта в значительной мере зависит от числа пользователей. Чем больше пользователей, тем больше они найдут ошибок.
Бетти Кэмпбелл из Лаборатории ядерной физики Массачусетского Технологического Института заметила интересный цикл жизни конкретного варианта программы. Он показан на рис. 11.2. Первоначально старые ошибки, обнаруженные в предыдущих вариантах и уже устраненные в них, проявляют тенденцию к появлению в новом варианте. Новые функции нового варианта порождают новые ошибки. Эти ошибки вылавливаются, и несколько месяцев все идет хорошо. Но потом число ошибок опять начинает расти. Мисс Кемпбелл находит объяснение этому факту в том, что пользователи выходят на более высокий уровень и начинают полностью использовать все возможности, заложенные в новом варианте. Ценой многих усилии из. этого варианта вылавливаются наиболее топкие ошибки 5).
Рпс. 11.2. Количество ошибок как функция времен;! жизни одного варианта программы.
Основная проблема сопровождения программ заключается в том, что исправление одного дефекта со значительной вероятностью (20-50%) влечет за собой появление другого. Поэтому, образно говоря, весь процесс напоминает два шага вперед и шаг назад.
Почему же дефекты не исправляются более тщательно? Во-первых, даже самый мелкий дефект проявляет себя в какой-то чисто локальной неудаче. В действительности же он зачастую распространяется на всю систему, причем неочевидным образом. Попытка исправить дефект ценой минимальных усилий затрагивает лишь только локальное и очевидное, и, несмотря на существование отличной документации, очень трудно предусмотреть все далеко идущие последствия таких исправлений. Во-вторых, исправлением обычно занимается не тот же самый человек, кто написал программу; зачастую им оказывается начинающий программист или стажер.
Вследствие появления новых ошибок сопровождение программы требует гораздо больше времени на отладку каждого написанного оператора, чем на любой другой этап программирования. Теоретически после каждого исправления нужно опять пропускать весь банк тестов, разработанных для системы, с тем чтобы убедиться, что никаким неявным образом ей не был причинен ущерб. На' практике такая регрессивная отладка должна стремиться к своему теоретическому идеалу, но это очень дорого.
Очевидно, что методы разработки программ, позволяющие устранить или по меньшей мере выявить побочные эффекты, могут оказать существенное влияние на уменьшение стоимости сопровождения, равно как н методы реализации таких разработок с меньшим числом людей, сопряжении и, следовательно, ошибок.
Шаг вперед и шаг назад
Лемап и Бплсди изучали историю последовательности выпуска версий большой операционной системы6). Они обнаружили, что общее число модулей линейно с номером версии, но что число затронутых поправками модулей растет экспоненциально с ростом номера версии. Все исправления проявляют тенденцию к разрушению структуры, увеличению энтропии и неупорядоченности системы. Все меньше и меньше усилий затрачивается на исправление первоначальных недостатков проекта, все больше н больше времени уходит на исправление ошибок, вызванных предыдущими переделками. С течением времени система становится все менее упорядоченной. Рано или поздно переделки перестанут давать какой-либо результат. За каждым шагом вперед будет следовать шаг назад. И хотя в принципе система может использоваться вечно, она устареет н не сможет больше служить основой для движения вперед. К тому же меняются машины, конфигурации, потребности пользователей, так что в действительности система не может жить вечно. Возникает необходимость качественно нового и обоснованного проекта.
И таким образом, на основе статистической механической модели Леман и Биледи пришли к выводу, подтверждаемому опытом всей жизни на земле, который также применим для систем программирования: "Вещи всегда лучше, когда они совсем еще новые",- сказал Паскаль. Это же в более доходчивой форме сформулировал в своей книге7) С. Лыос.
Создание системных программ - это процесс, уменьшающий энтропию, и, следовательно, он метастабилен. Сопровождение программы - процесс, увеличивающий энтропию, и даже самое умелое осуществление его лишь отодвигает тот срок, когда система безнадежно устареет.
XII. ОСТРЫЙ ИНСТРУМЕНТ
"Хорошего работника узнают по его инструментам".
(Пословица)
Даже сейчас мпогпе программистские проекты но всем, что касается инструментария, похожи на механические мастерские. Каждый мастер-механик имеет собственный сундучок с инструментами, вещественными доказательствами его профессионального мастерства. Он собирает такой сундучок всю свою жизнь, тщательно запирает па замок и бережет его как зеницу ока. Так и программист заводит свои маленькие редакторы, программы сортировки, распечатки, средства работы с дисками и прячет их в своем файле.
Такой подход, однако, не оправдывает себя в программистском проекте. Во-первых, основной проблемой здесь является связь, а индивидуальные сундучки с инструментами скорее препятствуют установлению связи, чем способствуют этому. Во-вторых, техника изменяется, когда меняется машина или рабочий язык, так что время жизни инструментарии не велико. И, наконец, очевидно, что совместная разработка и использование универсального программистского инструментария дает гораздо больший эффект.
Однако универсальных инструментов недостаточно. Как специализированные потребности, так и персональные предпочтения обуславливают необходимость специальных инструментов, поэтому, обсуждая организацию программистской бригады, я предложил каждой бригаде иметь своего инструментальщика человека, который разрабатывает весь общий инструментарий и может дать своему руководителю-клиенту инструк-1цш по его использованию. Он создает также и специальные инструменты, потребовавшиеся руководителю.
Итак, руководитель проекта должен выработать установку и выделить ресурсы, необходимые для создания общего инструментария. В то же самое время он должен осознать потребность в специализированных инструментах и не возражать против их разработки в самих рабочих бригадах. Руководителю может показаться, что если всех отдельных разработчиков инструментария собрать в одну группу и поручить ей создание общих средств, выигрыш в эффективности будет очень велик. Но это не так.
О каких же инструментах должен думать руководитель? Что планировать и организовывать? Прежде всего, это вычислительные средства: необходимы машины и определенная целенаправленность в распределении ресурсов. Нужны операционная система и установленный стиль обслуживания. Необходим язык и необходимо выработать языковую политику. Сюда же относятся вспомогательные средства, службы отладки, генераторы тестов и система обработки текстов для ведения документации. Давайте последовательно все это рассмотрим ').
Целевые машины
Весь парк машин полезно разбить па целевые п инструментальные машины. Целевая - это та машина, для которой создается программное обеспечение и на которой оно должно в конце концов отлаживаться. Инструментальные машины средства для создания системы. Если старая машина снабжается новой операционной системой, то она может одновременно служить как целевой, так и инструментальной.
Каковы целевые машины? Группы, разрабатывающие новые супервизоры или другое математическое обеспечение, составляющее "сердце" системы, конечно, нуждается в своей собственной машине. В таких группах потребуются операторы и один-два системных программиста, отвечающих за состояние машины.
Если нужна отдельная машина, что вообще-то бывает довольно редко, то она может не обладать продельным быстродействием, но должна иметь оперативную память объемом, как минимум, миллион байтов, еще сто миллионов байтов на дисках, и терминалы. Достаточны только алфавитно-цифровыо терминалы, но оли должны работать быстрее телетайпов, т. е. быстрое, чем 15 знаков в секунду.
Отладочная машина и ее программное обеспеченно также должны иметь свой инструментарий с тем, чтобы можно было автоматически проводить различные измерения всевозможных параметров программы во ьремя отладки. Контроль использования памяти, например, представляет собой эффективное средство диагностики случаев непопятного логического поведения или неожиданно низкой производительности.
График работы. Когда вы имеете дело с новой целевой машиной, для которой создается первая операционная система, то машинного времени обычно не хватает, и его распределение становится главной про блемой. Потребность во времени для целевой машины растет по своеобразному закону. При разработке OS/360 у нас были хорошие имитаторы Системы 360 и другие средства. Из опыта предыдущей работы мы представляли, сколько машинного врем.ени нам понадобится, и потребовали от изготовителей, чтобы машины были поставлены нам заранее. По сначала они месяц за месяцем простаивали. И вдруг сразу все шестнадцать систем оказались загружены полностью и возникла проблема распределения времени. Примерный характер изменения времени использования машин показан па рис. 12.1. Все вышли на отладку своих первых блоков одновременно, а уж затем почти каждая бригада все время что-нибудь да отлаживала.
Рис. 12.1. Рост времени использования целевой машины.
Мы сначала централизовали все наши машины и библиотеку лент и поручили их обслуживание опытной профессиональной бригаде. Чтобы максимально использовать время Системы 360, мы проводили отладку в пакетном режиме на любой свободной и подходящей машине. Мы старались получать четыре выдачи в день (время оборота 2,5 ч), и настаивали на четырехчасовом обороте. Вспомогательная машина IBM 1401 с терминалами использовалась для составления графика запусков, для слежения за тысячами задач и для управления временем оборота.
Однако, от такой организации пришлось отказаться, После нескольких месяцев медленного оборота, взаимных обвинений и всеобщего недовольства мы решили распределить машинное время большими блоками. Вся группа сортировки, состоящая из 15 человек, получала, например, систему на 4-6 ч. Они сами распределяли это время между собой. Даже если машина простаивала, никто посторонний не мог ею пользоваться. ' Оказалось, что это наилучший способ распределения времени. Хотя машина использовалась несколько меньше (впрочем, не всегда), производительность возросла. Каждый член бригады может работать гораздо продуктивнее, если он получает десять выдач за шестичасовой период, чем те же десять выдач с трехчасовыми интервалами, потому что постоянная сосредоточенность почти не оставляет времени па обдумывание. После такого "рывка" бригада обычно день или два разбирает полученные результаты, а уж потом снова на шесть часов выходит на машину. Зачастую всего несколько программистов, может быть, даже только трое, распределяют между собой и плодотворно используют весь шестичасовой период. Этот способ использования целевой машины представляется наилучшим.
Так всегда было на практике, хотя никогда - в теории. Системная отладка, как астрономия, всегда была занятием для полуночников. Почти двадцать лет тому назад, занимаясь отладкой на машине IBM 701, я втянулся в работу в предутренние часы, когда в машинном зале нет начальства, спокойно спящего дома, и операторов гораздо легче склонить к нарушению правил. С тех пор сменилось три поколения вычислительных машин, техника стала совершенно другой, появились операционные системы, и только этот метод работы остался все так же предпочтительным. Он сохранился потому, что он очень продуктивен. Настало время осознать его полезность и широко распространить эту плодотворную практику.
Инструментальные машины и служба данных
Имитаторы. Если целевая машина является новой, то для нее нужен имитатор, и тогда возникает возможность приступить к отладке задолго до появления самой целевой машины. И что немаловажно, имитатор обеспечивает достоверное средство отладки даже после того, как появилась целевая машина.
Достоверный - это не то же самое, что точный. В некоторых отношениях имитатор не будет точной и заслуживающей доверия реализацией архитектуры новой машины. Но изо дня в день это будет та же самая реализация, чего никак нельзя сказать о новом оборудовании.
Мы угко привыкли к тому, что оборудование вычислительной машины почти все время работает точно. И коль скоро прикладной программист привык к тому, что поведение системы остается неизменным при каждом запуске программы, он склонен искать ошибки в своей программе, а не в машине.
Этот опыт, однако, нс применим при создании математического обеспечения для новой машины. Лабораторные варианты или первые выпуски машины никогда по работают так, как это заранее определяется; то, что они делают, не всегда надежно и, кроме того, они не остаются изо дня в день неизменяемыми. По мере того, как находятся ошибки, технические изменения вносятся во все экземпляры машины, включая и принадлежащие группе программистов. Такая нестабильная база достаточно плоха. Еще хуже периодические неполадки в оборудовании. Но хуже всего неопределенность, потому что она побуждает человека копаться в своей программе в поисках ошибки, а се может там вовсе и не быть. Таким образом, достоверный имитатор на хорошей инструментальной машине не теряет своего значения памного дольше, чем этого можно было ожидать.
Трансляторы и ассемблеры. По тем же самым причинам нужны трансляторы и ассемблеры, работающие па достоверной инструментальной машине, но транслирующие рабочую программу для целевой системы. Затем можно переходить к отладке этой программы на имитаторе.
Программируя на языке высокого уровня, можно почти закончить отладку путем трансляции и проверки рабочей программы на инструментальной машине, еще не приступая к ее проверке в кодах целевой машины. Непосредственное выполнение как альтернатива имитации, и достоверная стабильность машины обеспечивают выигрыш в эффективности.
Библиотеки программ и учет. При создании OS/360 инструментальная машина очень успешно и с большой пользой применялась для ведения библиотек программ. Система, разработанная под руководством У. Р. Кт"ау-ли, состояла из двух сопряженных моделей IBM 7010, совместно использующих большой банк данных на дисках. Машины имели также ассемблер Системы 360. Все'; машинные программы, как исходные, так и оттранслированные модули загрузки, уже проверенные или проходящие проверку, хранились в этой библиотеке. Библиотека делилась на подбиблиотеки с различными правилами обращения к ним.
Во-первых, каждая группа или отдельный программист имели в своем распоряжении определенную область, где хранились экземпляры его программ, варианты отладки и заготовки для комплексной отладки. На этой "площадке для игр" человек мог делать со своими программами все что угодно, не будучи стеснен никакими ограничениями.
Когда программист заканчивал свою часть работы и подготавливал ее к объединению с другими, он передавал экземпляры руководителю большей системы, который помещал его часть программы в подбиблиотеку объединенной системы. Теперь уже автор мог вносить изменения в свою программу только с разрешения руководителя объединенной системы. После того, как вся система собрана воедино, она должна была пройти через вес этапы комплексной отладки.
Но вот, наконец, версия системы стала готова к более широкому использованию, после чего ее следовало перенести в подбиблиотеку текущей версии. Эта копия неприкосновенна, в ней можно было только фиксировать ошибки. Она доступна для использования при объединении и проверке всех новых версий модуля. Программа-справочник на машине IBM7010 хранила сведения о каждой версии каждого модуля, его статусе, местонахождении и об изменениях в них.
Здесь необходимо выделить два понятия. Первое - это контроль, т. е. идея принадлежности программ руководителям, которые единолично могут разрешать вносить изменения. Второе - это формальное разделение и перенесение затем с "площадки для игр" для объединения в систему.
По моему мнению, это одна из наиболее хорошо сделанных вещей в проекте OS/360. Этот метод техники административного управления был независимо выра-оотан в нескольких больших программистских проектах, в том число в фирме Bell Labs, ICL и в Кембриджском Университете2). Такая техника незаменима.
Программный инструментарий. По мере того, йак появляются новые методы отладки, значение старых уменьшается, но не исчезает совсем. Поэтому нужны средства выдачи, редакторы исходных файлов, динамические выдачи памяти и даже трассировки.
Точно так же нужен полный набор средств для размещения вводимых колод на дисках, для копирования лент, распечатки файлов, внесения изменений в каталог. Если вовремя завести должность инструментальщика, то все это можно сделать заранее до того времени, когда понадобится.
Система документации. Машинная система редактирования текстов, работающая на достоверной инструментальной машине, является, может быть, самой полезной из всего инструментария н экономист больше всего труда. В нашем распоряжении была очень удобная система, разработанная Дж. Франклином. Мне кажется, что без этой системы руководства по 08/360 появились бы гораздо позже и были бы гораздо менее ясными. Говорят, что для руководств но OS/360 требуется двухметровая полка, потому что их авторы страдали недержанием речи, и что такое обилие томов придает системе своего рода непостижимость. И некоторая доля правды во всем этом есть.
Но у меня на это два возражения. Во-первых, хотя документация по OS/360 и очень велика по объему, но она снабжена продуманным планом чтения, и если использовать ее избирательно, то затраты времени сводятся к минимуму. Нужно рассматривать документацию по OS/360 как библиотеку или как энциклопедию, а не как сборник текстов для обязательного чтения.
Во-вторых, подобное изобилие гораздо предпочтительнее, чем нехватка документации, характерная для большинства систем программирования. Я охотно соглашусь, однако, с тем, что некоторые места написаны не слишком хорошо и доработка может привести к уменьшению объема. Некоторые же части напя-саны очень хорошо, например, "Concepts and Facilities".
Модель производительности. Лучше иметь, чем не иметь. Делайте модель по методу "снаружи - внутрь" (подробно мы рассмотрим этот метод в следующей главе), Используйте тот же самый нисходящий подход приразработке модели производительности, логической модели и самого программного продукта. Начинайте де-лать\модель пораньше. Прислушайтесь к тому, что она будет вам говорить.
Язык высокого уровня и диалоговое программирование
При разработке OS/360 почти десять лет тому назад не использовались два самых важных инструмента сегодняшнего системного программиста. Они и сейчас еще используются не слишком широко, хотя вйе указывает на их эффективность и возможность самого широкого применения. Это, во-первых, язык высокого уровня п, во-вторых, диалоговое программирование. Я убежден, что только инерция н леность мешают всеобщему распространению этих средств; технические трудности не могут более служить достаточно веским оправданием.
Язык высокого уровня. Основные доводы в пользу языка высокого уровня производительность и быстрота отладки. Вопрос о производительности мы обсудили ранее (гл. VIII). В цифрах оценить преимущества использования такового языка очень трудно.
Убыстрение отладки связано просто с тем, что делается меньше ошибок и их легче найти. Ошибок меньше потому, что отсутствует уровень, на котором можно сделать не только синтаксические, но и семантические ошибки, например, перепутать регистры. Найти же ошибки легче потому, что этому помогают средства диагностики в трансляторе, а также потому (а это куда важнее), что легче задать отладочную выдачу.
Для меня лично соображения повышения производительности и ускорения отладки представляются непререкаемыми доводами в пользу языка высокого уровня. Трудно даже Представить, что систему программирования я смог бы теперь написать на языке ассемблера.
Ну а каковы же обычные возражения против использования языка высокого уровня? Их три: я не смо-^ делать, что хочу; рабочая программа слишком велика; рабочая программа работает слишком медленно. Я думаю, что первое возражение более не справедливо. Все опыты показывают, что каждый может выполнить все, что ему требуется. Правда, иногда .нужно крепко потрудиться, чтобы отыскать способ, кату это сделать3'4)
Что касается размеров рабочей программы, то новые оптимизирующие трансляторы стали вполне удовлетворительными и продолжают улучшаться.
Что касается быстродействия, то оптимизирующие трансляторы ныне выдают программы, работающие быстрее, чем большинство программ, написанных в машинных кодах. Более того, проблема быстродействия обычно может быть решена следующим образом: после отладки программы, выданной транслятором, часть ее (от 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" )
Среди современных магов не перевелись хвастуны:
"Я могу написать программы, которые управляют движением самолетов, перехватывают баллистические ракеты, ведут банковские счета, руководят производственными линиями". На это следует ответ: "И я могу, и каждый это может, но будут ли эти программы работать после того, как Вы их напишете?".
Как создается работоспособная программа? Как отлаживается программа? И как объединяется множество отлаженных программ-компонентов в проверенную и надежную систему? Мы эпизодически касались этих методов; теперь настала пора рассмотреть их более систематично.
Эксплуатация оборудования для вычислительной системы сводится к замене плохих элементов, к чистке и смазке и к внесению технических изменений, исправляющих дефекты разработки. (Не все, но большая часть технических изменений исправляет именно дефекты реализации или разработки, а не архитектуры, так что они незаметны для пользователя.)
Сопровождение программы не влечет за собой чистки, смазки или ремонта. Оно сводится в основном к внесению изменений, исправляющих дефекты разработки. Однако гораздо чаще, чем в случае оборудования, такие изменения включают в себя добавление новых функций. Обычно они прекрасно видны пользователю.
Стоимость сопровождения широко используемой программы составляет обычно 40 процентов стоимости ее разработки. Что удивительно, стоимость эта в значительной мере зависит от числа пользователей. Чем больше пользователей, тем больше они найдут ошибок.
Бетти Кэмпбелл из Лаборатории ядерной физики Массачусетского Технологического Института заметила интересный цикл жизни конкретного варианта программы. Он показан на рис. 11.2. Первоначально старые ошибки, обнаруженные в предыдущих вариантах и уже устраненные в них, проявляют тенденцию к появлению в новом варианте. Новые функции нового варианта порождают новые ошибки. Эти ошибки вылавливаются, и несколько месяцев все идет хорошо. Но потом число ошибок опять начинает расти. Мисс Кемпбелл находит объяснение этому факту в том, что пользователи выходят на более высокий уровень и начинают полностью использовать все возможности, заложенные в новом варианте. Ценой многих усилии из. этого варианта вылавливаются наиболее топкие ошибки 5).
Рпс. 11.2. Количество ошибок как функция времен;! жизни одного варианта программы.
Основная проблема сопровождения программ заключается в том, что исправление одного дефекта со значительной вероятностью (20-50%) влечет за собой появление другого. Поэтому, образно говоря, весь процесс напоминает два шага вперед и шаг назад.
Почему же дефекты не исправляются более тщательно? Во-первых, даже самый мелкий дефект проявляет себя в какой-то чисто локальной неудаче. В действительности же он зачастую распространяется на всю систему, причем неочевидным образом. Попытка исправить дефект ценой минимальных усилий затрагивает лишь только локальное и очевидное, и, несмотря на существование отличной документации, очень трудно предусмотреть все далеко идущие последствия таких исправлений. Во-вторых, исправлением обычно занимается не тот же самый человек, кто написал программу; зачастую им оказывается начинающий программист или стажер.
Вследствие появления новых ошибок сопровождение программы требует гораздо больше времени на отладку каждого написанного оператора, чем на любой другой этап программирования. Теоретически после каждого исправления нужно опять пропускать весь банк тестов, разработанных для системы, с тем чтобы убедиться, что никаким неявным образом ей не был причинен ущерб. На' практике такая регрессивная отладка должна стремиться к своему теоретическому идеалу, но это очень дорого.
Очевидно, что методы разработки программ, позволяющие устранить или по меньшей мере выявить побочные эффекты, могут оказать существенное влияние на уменьшение стоимости сопровождения, равно как н методы реализации таких разработок с меньшим числом людей, сопряжении и, следовательно, ошибок.
Шаг вперед и шаг назад
Лемап и Бплсди изучали историю последовательности выпуска версий большой операционной системы6). Они обнаружили, что общее число модулей линейно с номером версии, но что число затронутых поправками модулей растет экспоненциально с ростом номера версии. Все исправления проявляют тенденцию к разрушению структуры, увеличению энтропии и неупорядоченности системы. Все меньше и меньше усилий затрачивается на исправление первоначальных недостатков проекта, все больше н больше времени уходит на исправление ошибок, вызванных предыдущими переделками. С течением времени система становится все менее упорядоченной. Рано или поздно переделки перестанут давать какой-либо результат. За каждым шагом вперед будет следовать шаг назад. И хотя в принципе система может использоваться вечно, она устареет н не сможет больше служить основой для движения вперед. К тому же меняются машины, конфигурации, потребности пользователей, так что в действительности система не может жить вечно. Возникает необходимость качественно нового и обоснованного проекта.
И таким образом, на основе статистической механической модели Леман и Биледи пришли к выводу, подтверждаемому опытом всей жизни на земле, который также применим для систем программирования: "Вещи всегда лучше, когда они совсем еще новые",- сказал Паскаль. Это же в более доходчивой форме сформулировал в своей книге7) С. Лыос.
Создание системных программ - это процесс, уменьшающий энтропию, и, следовательно, он метастабилен. Сопровождение программы - процесс, увеличивающий энтропию, и даже самое умелое осуществление его лишь отодвигает тот срок, когда система безнадежно устареет.
XII. ОСТРЫЙ ИНСТРУМЕНТ
"Хорошего работника узнают по его инструментам".
(Пословица)
Даже сейчас мпогпе программистские проекты но всем, что касается инструментария, похожи на механические мастерские. Каждый мастер-механик имеет собственный сундучок с инструментами, вещественными доказательствами его профессионального мастерства. Он собирает такой сундучок всю свою жизнь, тщательно запирает па замок и бережет его как зеницу ока. Так и программист заводит свои маленькие редакторы, программы сортировки, распечатки, средства работы с дисками и прячет их в своем файле.
Такой подход, однако, не оправдывает себя в программистском проекте. Во-первых, основной проблемой здесь является связь, а индивидуальные сундучки с инструментами скорее препятствуют установлению связи, чем способствуют этому. Во-вторых, техника изменяется, когда меняется машина или рабочий язык, так что время жизни инструментарии не велико. И, наконец, очевидно, что совместная разработка и использование универсального программистского инструментария дает гораздо больший эффект.
Однако универсальных инструментов недостаточно. Как специализированные потребности, так и персональные предпочтения обуславливают необходимость специальных инструментов, поэтому, обсуждая организацию программистской бригады, я предложил каждой бригаде иметь своего инструментальщика человека, который разрабатывает весь общий инструментарий и может дать своему руководителю-клиенту инструк-1цш по его использованию. Он создает также и специальные инструменты, потребовавшиеся руководителю.
Итак, руководитель проекта должен выработать установку и выделить ресурсы, необходимые для создания общего инструментария. В то же самое время он должен осознать потребность в специализированных инструментах и не возражать против их разработки в самих рабочих бригадах. Руководителю может показаться, что если всех отдельных разработчиков инструментария собрать в одну группу и поручить ей создание общих средств, выигрыш в эффективности будет очень велик. Но это не так.
О каких же инструментах должен думать руководитель? Что планировать и организовывать? Прежде всего, это вычислительные средства: необходимы машины и определенная целенаправленность в распределении ресурсов. Нужны операционная система и установленный стиль обслуживания. Необходим язык и необходимо выработать языковую политику. Сюда же относятся вспомогательные средства, службы отладки, генераторы тестов и система обработки текстов для ведения документации. Давайте последовательно все это рассмотрим ').
Целевые машины
Весь парк машин полезно разбить па целевые п инструментальные машины. Целевая - это та машина, для которой создается программное обеспечение и на которой оно должно в конце концов отлаживаться. Инструментальные машины средства для создания системы. Если старая машина снабжается новой операционной системой, то она может одновременно служить как целевой, так и инструментальной.
Каковы целевые машины? Группы, разрабатывающие новые супервизоры или другое математическое обеспечение, составляющее "сердце" системы, конечно, нуждается в своей собственной машине. В таких группах потребуются операторы и один-два системных программиста, отвечающих за состояние машины.
Если нужна отдельная машина, что вообще-то бывает довольно редко, то она может не обладать продельным быстродействием, но должна иметь оперативную память объемом, как минимум, миллион байтов, еще сто миллионов байтов на дисках, и терминалы. Достаточны только алфавитно-цифровыо терминалы, но оли должны работать быстрее телетайпов, т. е. быстрое, чем 15 знаков в секунду.
Отладочная машина и ее программное обеспеченно также должны иметь свой инструментарий с тем, чтобы можно было автоматически проводить различные измерения всевозможных параметров программы во ьремя отладки. Контроль использования памяти, например, представляет собой эффективное средство диагностики случаев непопятного логического поведения или неожиданно низкой производительности.
График работы. Когда вы имеете дело с новой целевой машиной, для которой создается первая операционная система, то машинного времени обычно не хватает, и его распределение становится главной про блемой. Потребность во времени для целевой машины растет по своеобразному закону. При разработке OS/360 у нас были хорошие имитаторы Системы 360 и другие средства. Из опыта предыдущей работы мы представляли, сколько машинного врем.ени нам понадобится, и потребовали от изготовителей, чтобы машины были поставлены нам заранее. По сначала они месяц за месяцем простаивали. И вдруг сразу все шестнадцать систем оказались загружены полностью и возникла проблема распределения времени. Примерный характер изменения времени использования машин показан па рис. 12.1. Все вышли на отладку своих первых блоков одновременно, а уж затем почти каждая бригада все время что-нибудь да отлаживала.
Рис. 12.1. Рост времени использования целевой машины.
Мы сначала централизовали все наши машины и библиотеку лент и поручили их обслуживание опытной профессиональной бригаде. Чтобы максимально использовать время Системы 360, мы проводили отладку в пакетном режиме на любой свободной и подходящей машине. Мы старались получать четыре выдачи в день (время оборота 2,5 ч), и настаивали на четырехчасовом обороте. Вспомогательная машина IBM 1401 с терминалами использовалась для составления графика запусков, для слежения за тысячами задач и для управления временем оборота.
Однако, от такой организации пришлось отказаться, После нескольких месяцев медленного оборота, взаимных обвинений и всеобщего недовольства мы решили распределить машинное время большими блоками. Вся группа сортировки, состоящая из 15 человек, получала, например, систему на 4-6 ч. Они сами распределяли это время между собой. Даже если машина простаивала, никто посторонний не мог ею пользоваться. ' Оказалось, что это наилучший способ распределения времени. Хотя машина использовалась несколько меньше (впрочем, не всегда), производительность возросла. Каждый член бригады может работать гораздо продуктивнее, если он получает десять выдач за шестичасовой период, чем те же десять выдач с трехчасовыми интервалами, потому что постоянная сосредоточенность почти не оставляет времени па обдумывание. После такого "рывка" бригада обычно день или два разбирает полученные результаты, а уж потом снова на шесть часов выходит на машину. Зачастую всего несколько программистов, может быть, даже только трое, распределяют между собой и плодотворно используют весь шестичасовой период. Этот способ использования целевой машины представляется наилучшим.
Так всегда было на практике, хотя никогда - в теории. Системная отладка, как астрономия, всегда была занятием для полуночников. Почти двадцать лет тому назад, занимаясь отладкой на машине IBM 701, я втянулся в работу в предутренние часы, когда в машинном зале нет начальства, спокойно спящего дома, и операторов гораздо легче склонить к нарушению правил. С тех пор сменилось три поколения вычислительных машин, техника стала совершенно другой, появились операционные системы, и только этот метод работы остался все так же предпочтительным. Он сохранился потому, что он очень продуктивен. Настало время осознать его полезность и широко распространить эту плодотворную практику.
Инструментальные машины и служба данных
Имитаторы. Если целевая машина является новой, то для нее нужен имитатор, и тогда возникает возможность приступить к отладке задолго до появления самой целевой машины. И что немаловажно, имитатор обеспечивает достоверное средство отладки даже после того, как появилась целевая машина.
Достоверный - это не то же самое, что точный. В некоторых отношениях имитатор не будет точной и заслуживающей доверия реализацией архитектуры новой машины. Но изо дня в день это будет та же самая реализация, чего никак нельзя сказать о новом оборудовании.
Мы угко привыкли к тому, что оборудование вычислительной машины почти все время работает точно. И коль скоро прикладной программист привык к тому, что поведение системы остается неизменным при каждом запуске программы, он склонен искать ошибки в своей программе, а не в машине.
Этот опыт, однако, нс применим при создании математического обеспечения для новой машины. Лабораторные варианты или первые выпуски машины никогда по работают так, как это заранее определяется; то, что они делают, не всегда надежно и, кроме того, они не остаются изо дня в день неизменяемыми. По мере того, как находятся ошибки, технические изменения вносятся во все экземпляры машины, включая и принадлежащие группе программистов. Такая нестабильная база достаточно плоха. Еще хуже периодические неполадки в оборудовании. Но хуже всего неопределенность, потому что она побуждает человека копаться в своей программе в поисках ошибки, а се может там вовсе и не быть. Таким образом, достоверный имитатор на хорошей инструментальной машине не теряет своего значения памного дольше, чем этого можно было ожидать.
Трансляторы и ассемблеры. По тем же самым причинам нужны трансляторы и ассемблеры, работающие па достоверной инструментальной машине, но транслирующие рабочую программу для целевой системы. Затем можно переходить к отладке этой программы на имитаторе.
Программируя на языке высокого уровня, можно почти закончить отладку путем трансляции и проверки рабочей программы на инструментальной машине, еще не приступая к ее проверке в кодах целевой машины. Непосредственное выполнение как альтернатива имитации, и достоверная стабильность машины обеспечивают выигрыш в эффективности.
Библиотеки программ и учет. При создании OS/360 инструментальная машина очень успешно и с большой пользой применялась для ведения библиотек программ. Система, разработанная под руководством У. Р. Кт"ау-ли, состояла из двух сопряженных моделей IBM 7010, совместно использующих большой банк данных на дисках. Машины имели также ассемблер Системы 360. Все'; машинные программы, как исходные, так и оттранслированные модули загрузки, уже проверенные или проходящие проверку, хранились в этой библиотеке. Библиотека делилась на подбиблиотеки с различными правилами обращения к ним.
Во-первых, каждая группа или отдельный программист имели в своем распоряжении определенную область, где хранились экземпляры его программ, варианты отладки и заготовки для комплексной отладки. На этой "площадке для игр" человек мог делать со своими программами все что угодно, не будучи стеснен никакими ограничениями.
Когда программист заканчивал свою часть работы и подготавливал ее к объединению с другими, он передавал экземпляры руководителю большей системы, который помещал его часть программы в подбиблиотеку объединенной системы. Теперь уже автор мог вносить изменения в свою программу только с разрешения руководителя объединенной системы. После того, как вся система собрана воедино, она должна была пройти через вес этапы комплексной отладки.
Но вот, наконец, версия системы стала готова к более широкому использованию, после чего ее следовало перенести в подбиблиотеку текущей версии. Эта копия неприкосновенна, в ней можно было только фиксировать ошибки. Она доступна для использования при объединении и проверке всех новых версий модуля. Программа-справочник на машине IBM7010 хранила сведения о каждой версии каждого модуля, его статусе, местонахождении и об изменениях в них.
Здесь необходимо выделить два понятия. Первое - это контроль, т. е. идея принадлежности программ руководителям, которые единолично могут разрешать вносить изменения. Второе - это формальное разделение и перенесение затем с "площадки для игр" для объединения в систему.
По моему мнению, это одна из наиболее хорошо сделанных вещей в проекте OS/360. Этот метод техники административного управления был независимо выра-оотан в нескольких больших программистских проектах, в том число в фирме Bell Labs, ICL и в Кембриджском Университете2). Такая техника незаменима.
Программный инструментарий. По мере того, йак появляются новые методы отладки, значение старых уменьшается, но не исчезает совсем. Поэтому нужны средства выдачи, редакторы исходных файлов, динамические выдачи памяти и даже трассировки.
Точно так же нужен полный набор средств для размещения вводимых колод на дисках, для копирования лент, распечатки файлов, внесения изменений в каталог. Если вовремя завести должность инструментальщика, то все это можно сделать заранее до того времени, когда понадобится.
Система документации. Машинная система редактирования текстов, работающая на достоверной инструментальной машине, является, может быть, самой полезной из всего инструментария н экономист больше всего труда. В нашем распоряжении была очень удобная система, разработанная Дж. Франклином. Мне кажется, что без этой системы руководства по 08/360 появились бы гораздо позже и были бы гораздо менее ясными. Говорят, что для руководств но OS/360 требуется двухметровая полка, потому что их авторы страдали недержанием речи, и что такое обилие томов придает системе своего рода непостижимость. И некоторая доля правды во всем этом есть.
Но у меня на это два возражения. Во-первых, хотя документация по OS/360 и очень велика по объему, но она снабжена продуманным планом чтения, и если использовать ее избирательно, то затраты времени сводятся к минимуму. Нужно рассматривать документацию по OS/360 как библиотеку или как энциклопедию, а не как сборник текстов для обязательного чтения.
Во-вторых, подобное изобилие гораздо предпочтительнее, чем нехватка документации, характерная для большинства систем программирования. Я охотно соглашусь, однако, с тем, что некоторые места написаны не слишком хорошо и доработка может привести к уменьшению объема. Некоторые же части напя-саны очень хорошо, например, "Concepts and Facilities".
Модель производительности. Лучше иметь, чем не иметь. Делайте модель по методу "снаружи - внутрь" (подробно мы рассмотрим этот метод в следующей главе), Используйте тот же самый нисходящий подход приразработке модели производительности, логической модели и самого программного продукта. Начинайте де-лать\модель пораньше. Прислушайтесь к тому, что она будет вам говорить.
Язык высокого уровня и диалоговое программирование
При разработке OS/360 почти десять лет тому назад не использовались два самых важных инструмента сегодняшнего системного программиста. Они и сейчас еще используются не слишком широко, хотя вйе указывает на их эффективность и возможность самого широкого применения. Это, во-первых, язык высокого уровня п, во-вторых, диалоговое программирование. Я убежден, что только инерция н леность мешают всеобщему распространению этих средств; технические трудности не могут более служить достаточно веским оправданием.
Язык высокого уровня. Основные доводы в пользу языка высокого уровня производительность и быстрота отладки. Вопрос о производительности мы обсудили ранее (гл. VIII). В цифрах оценить преимущества использования такового языка очень трудно.
Убыстрение отладки связано просто с тем, что делается меньше ошибок и их легче найти. Ошибок меньше потому, что отсутствует уровень, на котором можно сделать не только синтаксические, но и семантические ошибки, например, перепутать регистры. Найти же ошибки легче потому, что этому помогают средства диагностики в трансляторе, а также потому (а это куда важнее), что легче задать отладочную выдачу.
Для меня лично соображения повышения производительности и ускорения отладки представляются непререкаемыми доводами в пользу языка высокого уровня. Трудно даже Представить, что систему программирования я смог бы теперь написать на языке ассемблера.
Ну а каковы же обычные возражения против использования языка высокого уровня? Их три: я не смо-^ делать, что хочу; рабочая программа слишком велика; рабочая программа работает слишком медленно. Я думаю, что первое возражение более не справедливо. Все опыты показывают, что каждый может выполнить все, что ему требуется. Правда, иногда .нужно крепко потрудиться, чтобы отыскать способ, кату это сделать3'4)
Что касается размеров рабочей программы, то новые оптимизирующие трансляторы стали вполне удовлетворительными и продолжают улучшаться.
Что касается быстродействия, то оптимизирующие трансляторы ныне выдают программы, работающие быстрее, чем большинство программ, написанных в машинных кодах. Более того, проблема быстродействия обычно может быть решена следующим образом: после отладки программы, выданной транслятором, часть ее (от 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" )
Среди современных магов не перевелись хвастуны:
"Я могу написать программы, которые управляют движением самолетов, перехватывают баллистические ракеты, ведут банковские счета, руководят производственными линиями". На это следует ответ: "И я могу, и каждый это может, но будут ли эти программы работать после того, как Вы их напишете?".
Как создается работоспособная программа? Как отлаживается программа? И как объединяется множество отлаженных программ-компонентов в проверенную и надежную систему? Мы эпизодически касались этих методов; теперь настала пора рассмотреть их более систематично.