Literate Programming
Давайте изменим традиционные приоритеты в создании программ:
вместо представления о нашей задаче как о создании инструкций "Что делать?"
для компьютера сконцентрируемся на объяснении другим людям описаний нашего видения
того, что под управлением программы должен делать компьютер.
Дональд Кнут
Термин "грамотное программирование" (Literate Programming -- LP)
был изобретен Д. Кнутом -- автором алгоритмических основ "компьютерного
типографского набора", знаменитой программной системы TeX и, наконец, единственного
фундаментального энциклопедического труда в области компьютинга -- "Искусство
программирования". Звучание дословного перевода сразу уместно будет усилить
(или даже уточнить) вариантом, основанным на созвучии слов literate и "литература"
-- "литературное программирование" (ЛП). Как ни странно, но уточнение,
построенное на таком весьма опасном допущении (аналогии всегда опасны), окажется
намного удачнее, чем точный дословный перевод.
![]() |
Текстовый редактор Emacs -- редкий
представитель инструментальных средств, интерактивно поддерживающих методологию
ЛП |
Выбранная в качестве эпиграфа цитата, датируемая далеким 1984 г. (именно тогда
увидела свет первая официально зарегистрированная публикация, посвященная ЛП,
-- статья Д. Кнута "Literate programming"), дает точное и краткое
описание главного в любой методологии -- цели. И здесь следует сделать первое
важнейшее отступление, а именно, попытаться воссоздать характер программирования
как массового явления тех времен. Без уточнения этой необходимой детали слишком
многое из сказанного впоследствии потребует дополнительных сложных и спорных
пояснений.
В конце 70-х -- начале 80-х годов прошлого столетия программирование уже выросло
из "коротких штанишек", а производительность компьютеров достигла
уровня, допускающего решение сложных наукоемких задач. Но подобные компьютеры
(и компьютеризация как массовое явление) все еще оставались атрибутом, если
так можно выразиться, "серьезных организаций" -- оборонных, крупных
научных и исследовательских, больших корпораций и банков. Высокая стоимость
аппаратных средств в те времена, как ни странно, играла и положительную роль
-- после бурного периода развития с его неизбежными ошибками, провалами и достижениями
уже было понятно, что программы стоят дороже, чем компьютеры, поэтому высокие
бюджеты программных проектов никого не пугали. Возможно, именно по этой причине
многие из созданных в те времена прикладных программных систем стали "долгожителями":
несмотря на убогость пользовательских интерфейсов, в них заложена мощнейшая
алгоритмика, за которой стоят иногда тысячи человеко-лет кропотливого процесса
разработки. В целом, модель "дорогие компьютеры -- хорошая производительность
-- большой бюджет процесса разработки ПО -- высокая алгоритмическая сложность"
хорошо характеризует этот период.
Идея ЛП, как детище своего времени, очень точно соответствует нашей примитивной
модели -- и интерес к этой идее, и развитие инструментальных средств и самой
идеи постепенно угасали с популяризацией и персонализацией компьютеров. Этот
очевидный факт можно пояснить, не выходя за рамки принятой модели -- повышение
доступности компьютеров означает и глобальное смещение приоритетов в алгоритмической
основе ПО. Естественно, алгоритмически сложное ПО никуда не исчезает, но на
общем фоне его роль уже далеко не столь важна, как в период создания Д. Кнутом
идей ЛП. Сегодня правят бал пользовательские интерфейсы, а сложная алгоритмика
в панике упрятывается в повторно используемые компоненты -- в панике из-за того,
что массовый рынок требует слишком много программ "сразу и сейчас",
а для разработки такого количества ПО просто невозможно найти необходимое количество
программистов класса Д. Кнута.
И все-таки области, где применение идей ЛП не теряет своей актуальности, никуда
не исчезают -- управляющие программы для встраиваемых систем, высоконадежные
программные комплексы класса "mission critical", критическое системное
ПО и, наконец, -- столь модное сегодня "открытое ПО". О последнем
стоит сказать особо -- именно идеи "открытого ПО" (распространяемого
на уровне исходных текстов), казалось бы, идеально согласуются с целью ЛП. Ведь
доступность исходных текстов -- не самоцель различных сообществ и не прихоть
авторов той или иной лицензии, напротив, это критический фактор жизнеспособности
программ. Казалось бы, что именно здесь идее ЛП суждено было обосноваться прочно
и надолго, и "открытое ПО" необходимо создавать именно на основе принципа
"объясняй человеку, как должен действовать компьютер". На деле же...
фраза "я слишком ленив, чтобы писать документацию" (I'm too lazy...)
-- чуть ли не неизменный атрибут массы свободно распространяемых программ.
Детализация
Причина, из-за которой мое объяснение слишком длинное,
-- отсутствие времени для того, чтобы сделать его короче.
Блез Паскаль
Цель ЛП прозрачна и даже благородна. Ее можно сформулировать и другими словами,
а именно: "главное в работоспособной программе -- не управляющие инструкции
компьютеру, а знания разработчика программы, выраженные в максимально удобной
для понимания сторонним человеком форме". В реальности большинство программистов...
сталкивались с образчиками ЛП при изучении посвященных алгоритмическим основам
своей профессии книг, авторы которых практически всегда прибегают к приему описания
реализаций программ на псевдокоде -- гибриде языка программирования и естественного
языка. Впрочем, крохотный пример может показаться не лишним, а заодно и дать
первое ощущение "привкуса" ЛП:
Стиль C и C++
for( ic=0, ic<MaxCusts, ic++ ) |
@<Для каждого из зарегистрированных потребителей, достигшего совершеннолетия>@ |
Давайте сразу обратим внимание на пары символов '@<' и '>@'. Они своей
симметрией наводят на аналогию с... символами-ограничителями тегов в языках
разметки, например HTML. И, как ни странно, во второй раз аналогия не подвела
-- все воплощения идеи ЛП являются специализированными языками разметки, поддержанными
инструментально.
Естественно, у читателя должен возникнуть вопрос -- "Ну и что это дает?".
Действительно, зачем вводить еще один язык, если можно (и нужно) просто комментировать
текст программы? Чтобы ответить на подобные вопросы, достаточно узнать самое
главное о соотношении синтаксиса и семантики языков ЛП.
Синтаксически языки ЛП крайне просты и представляют собой небольшой перечень
правил записи объединения высокоуровневых фрагментов псевдокода, допускающего
описание программы на естественном языке, и фрагментов-"реализаций"
этого псевдокода, в которых последний "реализуется" на некотором языке
программирования. Принципиальное свойство языка ЛП -- произвольный (выбираемый
программистом) порядок следования в ЛП-программе фрагментов-"реализаций".
Семантика языка ЛП, несмотря на простоту синтаксиса, куда более сложна. Фактически
язык ЛП формирует принципиально новую парадигму программирования, не зависящую
(или минимально зависящую) от языка реализации программы. К особенностям этой
"ЛП-парадигмы" разные исследователи и программисты-практики относят
"плавность" перехода от описания проблемы (постановки задачи) к реализации
(программе), полноценную поддержку разных методик анализа и разработки (например,
гибридной: нисходящий анализ и восходящая реализация), эффективное воплощение
принципа "разделяй и властвуй" и т. д. Сторонники наиболее радикальной
точки зрения на ЛП считают, что такие особенности позволяют говорить о ЛП-языках
как о принципиально новых языках программирования, поддерживающих стиль программирования,
при котором "...дисциплинированно делается именно то, что нужно делать".
Ну а теперь можно и ответить на поставленный вопрос. Вспомним принципиальную
синтаксическую особенность языков ЛП -- произвольность порядка и отсутствие
упоминаний о каких-либо ограничениях на содержание фрагментов-"реализаций".
Казалось бы, незначительный нюанс, но в ЛП, как и в жизни, все строится на них.
Вследствие таких особенностей об уровне применимости ЛП-подхода можно и не говорить
-- он "работает" от самого высокого уровня (проектирования) до самого
низкого, превращая и кодирование в процесс высокоуровневой разработки.
Пора объяснений
То, что написано без усилий, читается без удовольствия.
Сэмюэль Джонсон
Во всех материалах, посвященных ЛП, очень трудно отделить концептуальную часть
от реалий применений. Впрочем, этим грешат все описания методологий, концепций
и парадигм программирования -- чтобы по-настоящему "почувствовать вкус",
требуется реальный пример, а не потешная программка класса "Hello, world",
ведь материал адресуется тем, для кого "потешный" уровень программирования
-- давно пройденный этап. Журнальная статья тем более не позволяет приводить
"реальные примеры". Мы ограничимся только обсуждением нюансов.
Псевдокод ЛП-программ фактически представляет собой описание структуры будущего
программного "шедевра". Абсолютно неформальное, допускающее включение
математических формул, иллюстраций, чего угодно -- вплоть до мультимедийных
"вставок", такое описание-документация "по ходу дела" дополняется
новыми фрагментами псевдокода и фрагментами-"реализациями". При этом
ЛП-программист не должен следить за сложной в больших программах "адресацией"
-- соответствием команд псевдокода и фрагментов-"реализаций", так
как сами фразы на псевдокоде являются "адресом". То есть, если где-то
в ЛП-программе встретилась фраза псевдокода "@< Вывод сообщения на печать
>@", впоследствии программист может "овеществить" ее следующим
фрагментом-"реализацией":
@< Вывод сообщения об ошибке на печать >@= |