КаталогИндекс раздела
НазадОглавлениеВперед


XV. ВТОРОЕ ЛИЦО

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

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

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

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

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

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

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

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

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

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

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

  1. Назначение. Какова основная функция программы, для чего она?
  2. Ситуация. На каких машинах, в какой конфигурации и на какой операционной системе она будет работать?
  3. Область и сфера действия. Какова область входных данных? В каком диапазоне могут появиться выходные результаты?
  4. Реализуемые функции и используемые алгоритмы. Что именно она делает?
  5. Форматы ввода/вывода. Точные и полные.
  6. Рабочие процедуры, включая нормальное и аварийное окончание, описывают все, что видно с пульта и будет получено на выдачах.
  7. Варианты. Какие функции может выбирать пользователь? Как этот выбор определяется?
  8. Время исполнения. Сколько времени требует задача указанного объема при определенной конфигурации оборудования?
  9. Точность и проверка. Какова ожидаемая точность ответов? Каковы способы проверки точности?

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

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

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

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

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

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

  1. Блок-схема или граф подчиненности подпрограмм. Последнее предпочтительней. (Подробнее обсуждается ниже.)
  2. Полные описания используемых алгоритмов или ссылки на соответствующие описания в литературе.
  3. Форматы всех используемых файлов.
  4. Схема передачи информации - последовательность считывания данных или программ с ленты или диска - и описание того, что происходит на каждом этапе передачи.
  5. Обсуждение модификаций, допускаемых первоначальным проектом, сущность и расположение мест подключения и выходов из программ, свободное обсуждение идеи первого автора о возможных модификациях и о путях их осуществления. Полезны также его замечания относительно скрытых "ловушек".

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

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

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

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

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


Рис.15.1. Пример структуры программы

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


Рис. 15.2. Сравнение блок-схемы и соответствующей программы на PL/I.

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

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

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

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

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

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

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

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

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

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

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

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

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

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


Рис.15.3. Пример самодокументируемой программы

  1. Используйте отдельное имя задачи при каждом запуске программы и ведите журнал запусков, где указывайте, что было опробовано, когда и с каким результатом. Если имя состоит из мнемонической части (здесь QLT) и числа (здесь 4), то это число можно использовать как номер запуска программы, связывающий вместе распечатки и журнал. При этом методе для каждого запуска нужна новая карта задачи, но их можно делать пакетом, дублируя общую информацию.
  2. Введите в мнемоническое имя программы идентификатор версии, т. е. считайте, что будет несколько версий. Здесь индекс - это цифры года 1967.
  3. Используйте текстовое описание в качестве комментариев к процедуре.
  4. По мере возможности отсылайте к стандартной литературе, содержащей основные алгоритмы: Это экономит место, особенно если указывается более полное описание, чем можно было бы здесь привести, и позволяет осведомленному читателю пропустить то, что он знает.
  5. Укажите связь с книжным алгоритмом: а) изменения, б) специализации, в) представления.
  6. Опишите все переменные. Используйте мнемонические имена. Используйте комментарии, чтобы превратить DECLARE в полную легенду. Отметьте, что такая легенда уже содержит имена и структурные описания, необходимо только описать, для чего они предназначены. Поступая таким образом, можно избежать повторения имен и структурных описаний.
  7. Выделите инициализацию с помощью метки.
  8. Сгруппируйте операторы с помощью меток, чтобы показать их соответствие операторам в описании алгоритма в литературе.
  9. Используйте абзацы и отступы для представления структуры и логической группировки.
  10. Вручную проведите в распечатке стрелки логических переходов. Они очень полезны при отладке и внесении изменений. Стрелки можно провести справа на полях и сделать их частью текста, /доступного машине.
  11. Используйте построчные примечания или помечайте все, что не очевидно. Если используются способы, предлагаемые выше, то примечания будут короче и их будет меньше, чем обычно.
  12. Располагайте, несколько операторов на одной строке или один оператор на нескольких строчках, чтобы подчеркнуть смысловую связь или обеспечить соответствие другому описанию алгоритма.

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

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

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

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

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


НазадОглавлениеВперед
КаталогИндекс раздела