Глава 15 Обратная сторона

Чего мы не понимаем, тем не владеем.

ГЕТЕ

О, дайте мне выступить комментатором, Скользящим по поверхности и будоражащим умы.

КРАББ

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

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

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

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

Томас Дж. Уотсон Старший (Thomas J. Watson, Sr.) рассказал мне историю своего первого опыта в качестве продавца кассовых аппаратов в северной части штата Нью-Йорк. Исполненный энтузиазма, он отправился в путь в своем фургоне, нагруженном кассовыми аппаратами. Он прилежно объехал свой участок, но ничего не продал. Обескураженный, он сообщил об этом своему хозяину. Послушав некоторое время, управляющий сказал: «Помоги мне загрузить несколько касс в фургон, запрягай лошадь, и поедем снова.» Так они и сделали, и обходя покупателей одного за другим, старик показывал, как продавать кассовые аппараты. Судя по всему, урок пошел впрок.

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

Какая документация требуется?

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

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

*Томас Дж. Уотсон Старший — основатель компании IBM (примеч. перев.)

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

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

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

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

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

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

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

7. Опции. Какой выбор предоставляется пользователю в отношении функций? Каким образом нужно его задавать?

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

9. Точность и проверка. Какова ожидаемая точность результатов? Какие имеются средства проверки точности?

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

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

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

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

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

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

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

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

1. Блок-схема или граф подпрограммной организации. Подробнее об этом см. ниже.

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

3. Разъяснение структуры всех используемых файлов.

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

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

Бич блок-схем

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

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

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

Рис. 15.1 Граф структуры программы (пример W. V. Wright)

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

Подробная пошаговая блок-схема является досадным анахронизмом, пригодным только для новичков в алгоритмическом мышлении. Введенные Голдштайном и фон Нейманом[1]прямоугольники вместе со своим содержимым служили языком высокого уровня, объединяя непостижимые операторы машинного языка в осмысленные

группы. Как давно понял Иверсон,[2]в систематическом языке высокого уровня группировка уже проведена, и каждый прямоугольник содержит оператор (рис. 15.2). Поэтому сами прямоугольники являются утомительным и отнимающим место упражнением в черчении и вполне могут быть удалены. Тогда остаются только стрелки. Стрелки, связывающие один оператор с другим, расположенным в следующей строке, излишни, и их можно удалить. Тогда остаются только GO TO, и если придерживаться хорошей практики программирования и использовать блочные структуры для минимизации числа GO TO, таких стрелок окажется немного, но они очень способствуют пониманию. Вполне можно нарисовать их на листинге и вовсе избавиться от блок-схемы.

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

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

Самодокументирующиеся программы

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

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

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

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

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

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

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

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

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

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

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

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

Некоторые приемы. На рисунке 15.3 показана самодокументирующаяся программа на языке PL/I.[3]Числа в кружочках не являются ее частью, а служат метадокументацией для ссылок при обсуждении.

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

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

3. Включите текстовое описание в качестве комментариев к PROCEDURE.

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

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

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

7. Поставьте метку в начале инициализации.

8. Поставьте метки перед группами операторов, соответствующие операторам алгоритма, описанного в книге.

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

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

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

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

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

Рис. 15.3 Самодокументирующаяся программа

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

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

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

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

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

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





 

Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх