XV. Второе лицо

"Mы не обладаем тем, чего не понимаем".
(Гете)

"О, дайте мне талант комментатора, который,
не углубляясь в суть явлений, будоражит умы людей".
(Краббе)

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

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

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

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

Томас Дж. Уотсон-старший *) рассказывал как-то о своем первом опыте в качестве коммивояжера, продающего кассовые аппараты. Полный энтузиазма, он отправился в путь, погрузив кассовые аппараты в фургон. Он прилежно изъездил всю местность, но так и не продал ни одного аппарата. Совершенно подавленный неудачей, он доложил о пей хозяину. Тот выслушал отчет, а затем сказал: "Помогите мне погрузить аппараты в фургон, запрягите лошадь, и снова в путь". Так они в сделали, объехали одного покупателя аа другим, и старший показывал, как, продавать кассовые аппараты. Дальнейшее показало, что урок не пропал зря.

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

Какая документация нужна?

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

Для использования программы.

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

  1. Назначение. Какова основная функция программы, для чего она?

  2. Ситуация. На каких мшинах, в какой конфигурации и на какой операционной системе она будет работать?

  3. Область и сфера действия. Какова область входных данных? В каком диапазоне могут появиться выходные результаты?

  4. Реализуемые функции и используемые алгоритмы. Что именно она делает?

  5. Форматы ввода/вывода. Точные и полные.

  6. Рабочие процедуры, включая нормальное И аварийное окончание, описывают все, что видно с пульта и будет получено на выдачах.

  7. Варианты. Какие функции может выбирать пользователь? Как этот выбор определяется?

  8. Время исполнения. Сколько времени требует задача указанного объема при определенной конфигурации оборудования?

  9. Точность и проверка. Какова ожидаемая точность ответов? Каковы способы проверки точности?

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

Для доверия к программе.

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

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

Далее, нужны тесты, которые обычно пропускаются после того, как в программу внесены изменения. Они распределяются на три класса в соответствии с областью входных данных.

  1. Главные тесты, которые проверяют основные функции программы для наиболее типичных данных.

  2. Предельно допустимые тесты, которые устанавливают границы области входных данных, проверяя, работает ли программа с максимально допустимыми величинами, с минимально допустимыми величинами или с какими-либо исключениями.

  3. Тесты, устанавливающие границу области входных данных извне, проверяющие, выдаются ли в случае ввода недопустимых данных соответствующие диагностические сообщения.

Для модификации программы.

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

  1. Блок-схема или граф подчиненности подпрограмм. Последнее предпочтительней. (Подробнее обсуждается ниже.)

  2. Полные описания используемых алгоритмов или ссылки на соответствующие описания в литературе.

  3. Форматы всех используемых файлов.

  4. Схема передачи информации - последовательность считывания данных или программ с ленты или диска - и описание того, что происходит на каждом этапе передачи.

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

Несостоятельность блок-схем

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

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

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

Конечно, такой граф и не следует стандартам блок-схем, и пе нуждается в них. Все эти правила относительно вида элементов, стрелок, порядка нумерации и т. д. нужны только для того, чтобы можно было попять подробные блок-схемы. Подробные блок-схемы, однако, устарели; они только мешают, и в лучшем случае пригодны для обучения повичков, еще не умеющих алгоритмически мыслить. В свое время предложенные Голдстайном и Нейманом ') маленькие квадратики на блок-схемах вместе со своим содержанием выступали в качестве языков высокого уровня, объединяя абсолютно непонятные операторы машинного языка в группы, имеющие определенный смысл. Как давно уже указал Айверсон 2), в систематическом языке высокого уровня такая группировка уже осуществлена, так что каждый квадратик просто соответствует оператору (рис. 15.2). Тогда сами квадратики превращаются в случайное и ненужное упражнение по рисованию, и от них можно отказаться. Но теперь не остается ничего, кроме стрелок. Стрелки, соединяющие оператор со следующим за ним, не нужны, сотрем их. Остаются только операторы перехода. Но если следовать хорошей практике ,а использовать блочные структуры для минимизации числа операторов перехода, то останется совсем/немного стрелок, вот они-то очень сильно облегчают понимание. Эти стрелки можно перенести прямо ни распечатку программы и совсем избавиться от блок-схемы.

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

Апостол Петр так говорил о новообращенных язычниках и иудейских законах: "Что же вы желаете возложить на выи (их) иго, которого не могли понести ни отцы наши, ни мы?" (Деяние 15, 10). Я хотел бы сказать то же самое о начинающих программистах п устаревшей практике .использования блок-схем.

Самодокументированные программы

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

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

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

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

Теперь очевидно, что введение блок-схем в такую программу - задача неприятная, хотя и возможная. Но стоит только признать, что блок-схемы устарели и нужно использовать язык высокого уровня, как появляется возможность объединения программы и документации.

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

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

Подход.

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

Вторая идея сводится к использованию пространства и форматов выдачи для повышения читабельности программы и для представления структуры подчиненности и вложенности в программе.

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

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

Некоторые методы

Самодокументированная программа, написанная на PL/I, приведена на стр. 135- 137. Цифры в кружках не относятся к ней; это - метадокументация, используемая при обсуждении примера.

  1. Используйте отдельное имя задачи при каждом запуске программы и ведите журнал запусков, где указывайте, что было опробовано, когда и с каким результатом. Если имя состоит из мнемонической части (здесь QLT) и числа (здесь 4), то это число можно использовать как номер запуска программы, связывающий вместе распечатки и журнал. При этом методе для каждого запуска нужна новая карта задачи, но их можно делать пакетом, дублируя общую информацию.

  2. Введите в мнемоническое имя программы идентификатор версии, т. е. считайте, что будет несколько версий. Здесь индекс - это цифры года 1967.

  3. Используйте текстовое описание в качестве комментариев к процедуре.

  4. По мере возможности отсылайте к стандартной литературе, содержащей основные алгоритмы: Это экономит место, особенно если указывается более полное описание, чем можно было бы здесь привести, и позволяет осведомленному читателю пропустить то, что он знает.

  5. Укажите связь с книжным алгоритмом: а) изменения, б) специализации, в) представления.

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

  7. Выделите инициализацию с помощью метки.

  8. Сгруппируйте операторы с помощью меток, чтобы показать их соответствие операторам в описании алгоритма в литературе.

  9. Используйте абзацы и отступы для представления структуры и логической группировки

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

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

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

Почему бы и нет?

Каковы недостатки такого подхода к документации? Их несколько, они были вполне реальны, но с течением времени превратились в воображаемые.

Наиболее серьезное возражение заключается в том, что увеличивается размер исходной программы, которую нужно хранить в памяти. Поскольку дело идет к тому, что мы будем хранить исходную программу в памяти, вводя ее непосредственно с терминала, это соображение становится все более важным. Я сам поймал себя на том, что мои комментарии к программе. написанной на APL и хранимой на дисках, всегда короче, чем когда я пишу на PL/I и собираюсь хранить все примечания на перфокартах.

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

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

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

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

Next