Программы, в которых главные процессы пытаются интерактивно обмениваться данными с подчиненными мини-языками, где данная проблема тщательно не проработана, подвержены взаимоблокировкам при рассинхронизации главного и подчиненного процессов (проблема, впервые упомянутая в главе 7).
Существуют обходные пути для управления мини-языками, разработанными не так тщательно. Прототипом для большинства из них является Tcl-пакет
В других языках доступны эквиваленты пакета
При разработке мини-языка следует помнить о данной проблеме. Хорошей идеей может быть добавление опции, которая изменяет диалоговое поведение, и ответы становятся более похожими на протокол прикладного уровня с недвусмысленными разделителями конца вывода и аналогом заполнения байтами.
9 Генерация кода: повышение уровня спецификации
В главе 1 отмечалось, что людям гораздо удобнее мысленно представить себе данные, чем анализировать управляющую логику программы. Для того чтобы понять это, следует сравнить выразительность и дидактическую силу диаграммы 50-узло-вого дерева указателей с блок-схемой программы, состоящей из 50 строк. Или (что еще лучше) диаграмму инициализатора массива, выражающего таблицу преобразования, с эквивалентным оператором выбора. Различия в прозрачности и ясности поразительны'.
Данные более понятны, чем программная логика. Это верно независимо от того, являются ли данные обычной таблицей, декларативным языком разметки, системой шаблонов или набором макросов, которые расширяют программную логику. Хорошей практикой является перемещение как можно больше сложности конструкции из процедурного кода в данные, а также выбор форм представления данных, которые удобны для человека, осуществляющего сопровождение и манипулирующего этими данными. Преобразование таких форм в формы, пригодные для машинной обработки, — задача машин, а не людей.
Другим важным преимуществом высокоуровневых, более декларативных форм записи является то, что они лучше приспособлены к проверке во время компиляции. Для процедурных форм записи характерно сложное поведение во время выполнения программ, которое трудно анализировать на этапе компиляции. Декларативные нотации предоставляют гораздо больше возможностей для обнаружения ошибок, поскольку позволяют полнее понять запланированное поведение.
Это понимание теоретически обосновывает набор практических приемов, которые всегда были важной частью инструментария Unix-программиста — языки очень высокого уровня, программы, управляемые данными, генераторы кода и узкоспециальные мини-языки. Объединяет их то, что все они являются способами, позволяющими поднять генерацию кода на несколько уровней выше, чтобы спецификации могли быть меньше. Ранее отмечалось, что плотность дефектов стремится к почти постоянному значению в различных языках программирования. Все указанные практические приемы означают сокращение количества строк и, соответственно, уменьшение вероятности появления ошибок.
В главе 8 описывалось использование специализированных мини-языков. В главе 14 представлены аргументы в пользу языков очень высокого уровня. В данной главе рассматривается несколько примеров конструкции программ, управляемых данными, а также ряд примеров генерации особого кода. Некоторые средства генерации кода описаны в главе 15. Как и мини-языки, данные методы позволяют радикально сократить количество строк кода в программах и соответственно уменьшить время отладки и затраты на сопровождение.
9.1 Создание программ, управляемых данными