Искусство программирования для Unix - Реймонд Эрик Стивен
Шрифт:
Интервал:
Закладка:
• В часть "отображение" входит то, что приводит объекты предметной области в визуальную форму. В приложении с действительно четко разделенными "моделью/отображением/контроллером" компонент отображения извещается об обновлениях модели и отвечает скорее самостоятельно, а не под синхронным управлением контроллера или явных запросов на обновление.
• Компонент "контроллер" обрабатывает пользовательские запросы и передает их модели в виде команд.
На практике части "отображение" и "контроллер" часто сильнее связаны друг с другом, чем с моделью. Например, в большинстве GUI-интерфейсов комбинируется поведение частей "отображения" и "контроллера". Они разделяются только в тех случаях, когда приложение требует нескольких видов отображения модели.
Схема модель/отображение/контроллер в операционной системе Unix распространена гораздо шире, чем в других средах, именно потому, что существует прочная традиция "решать одну задачу хорошо", а IPC-методы являются одновременно простыми и гибкими.
Особенно мощная форма данной методики связывает интерфейс политики (часто GUI-интерфейс, комбинирующий функции отображения и контроллера) с ядром (моделью), который содержит интерпретатор для узкоспециального мини-языка. Данная модель проектирования рассматривалась в главе 8, где основное внимание было уделено конструкциям мини-языков. Здесь рассматриваются различные способы, с помощью которых такие ядра могут формировать компоненты более крупных систем кода.
Существует несколько основных вариантов данной модели проектирования.
11.6.8.1. Пара конфигуратор/актор
В данной паре интерфейсная часть управляет средой запуска фильтра или программы, подобной демону, которая затем выполняется, не требуя пользовательских команд.
Хорошим примером пары конфигуратор/актор являются программы fetchmail(l) и fetchmailconf(1) (которые уже использовались как учебные примеры воспринимаемости и создания программ, управляемых данными, а также рассматриваются в главе 14 как учебные примеры использования языка Python). Утилита fetchmailconf представляет собой интерактивный конфигуратор файлов профилей, который поставляется с программой fetchmail. fetchmailconf также может служить в качестве GUI-упаковщика, который запускает fetchmail либо в приоритетном, либо в фоновом режиме.
Данная модель проектирования позволяет обеим программам, fetchmail и fetchmailconf, специализироваться в том, что они делают хорошо, и конечно, позволяет писать их на различных языках, которые целесообразно использовать в данных предметных областях. Программу fetchmail, которая обычно запускается в фоновом режиме как демон, не требуется объединять с GUI-кодом, и наоборот, fetchmailconf может специализироваться на сложном GUI-представлении, не требуя от fetchmail затрат размера и сложности. Наконец, ввиду того, что информационные каналы между ними являются узкими и четко определенными, остается возможность управлять программой fetchmail из командной строки, а также из сценариев, отличных от fetchmailconf.
Термин "конфигуратор/актор" придуман автором данной книги.
11.6.8.2. Пара спулер/демон
Облегченный вариант пары конфигуратор/актор может оказаться полезным в ситуациях, когда требуется сериализованный доступ к общему ресурсу в пакетном режиме, т.е. когда четко определенный поток заданий или последовательность запросов требует некоторого совместно используемого ресурса, но ни одна отдельная задача не требует взаимодействия с пользователем.
В данной модели спулер или клиентская часть просто помещает запросы на выполнение заданий и данные в спул-область. Запросы на выполнение заданий и данные — просто файлы, а спул-областью, как правило, является каталог. Расположение данного каталога и формат запросов согласовывается между спулером и демоцом.
Демон постоянно работает в фоновом режиме, опрашивая спул-каталог в поисках задания. Когда он находит запрос на выполнение задания, то пытается обработать связанные с ним данные. Если обработка прошла успешно, то запрос и данные из спул-области удаляются.
Классическим примером данной модели является система спулера печати Unix, lpr( 1 )/lpd(1). Интерфейсной частью в данном случае является утилита 1рг( 1), просто помещающая предназначенные для печати файлы в спул-область, которая периодически сканируется демоном Ipd. Задача данного демона — сериализация доступа к печатающим устройствам.
Другим классическим примером является пара at(1)/atd(1), обеспечивающая выполнение команд по расписанию. Третьим исторически важным примером, хотя и не распространенным в настоящее время, была программа UUCP (Unix-to-Unix Copy Program), широко применявшаяся в качестве почтового транспорта на коммутируемых линиях до того, как в начале 90-х годов прошлого века не начался взрывной рост Internet.
Модель спулер/демон и сейчас остается важной в программах транспортировки почты (которые по своей природе являются пакетными). Интерфейсные части почтовых транспортных программ, таких как sendmail(1) и qmail(1), обычно предпринимают одну попытку немедленной доставки почты через SMTP-сервер и внешнее Internet-соединение. Если попытка не удалась, то почта помещается в спул-область; демон-версия или режим почтового транспорта попытается доставить почту позднее.
Как правило, система спулер/демон состоит из четырех частей: модуль запуска задания, организатор очереди, утилита отмены задания и спулер-демон. Фактически присутствие первых трех частей определенно указывает на то, что за ними находится спулер-демон.
Понятия "спулер" и "демон" — прочно укоренившийся жаргон в Unix-сообществе (фактически термин "спулер" появился во время ранних мэйнфреймов).
11.6.8.3. Пара драйвер/ядро
В данной модели, в отличие от пары конфигуратор/актор или спулер/демон, интерфейсная часть подает команды и интерпретирует вывод от ядра после запуска. Ядро имеет простую модель интерфейса. Используемый IPC-метод является деталью реализации: ядро может быть подчиненным процессом драйвера (в том смысле, который обсуждался в главе 7), или ядро и драйвер могут взаимодействовать через сокеты, общую память, или посредством любого другого IPC-метода. Ключевыми моментами в данном случае являются (а) интерактивность пары и (b) способность ядра к самостоятельной работе со своим собственным интерфейсом.
Написание таких пар сложнее, чем написание пар конфигуратор/актор, поскольку они теснее и сложнее связаны. Драйверу необходимы сведения не только об ожидаемой среде запуска ядра, но и о его наборе команд, а также о форматах ответов.
Однако если ядро спроектировано с возможностью использования в сценариях, то нередко драйверная часть пишется не автором ядра, а другим разработчиком, или несколько драйверов могут подключаться к определенному ядру. Превосходный пример в обоих случаях представлен программами^^ иghostview(l), которые являются драйверами для gs(1), интерпретатора Ghostscript. Ghostscript переводит
PostScript в различные графические форматы и низкоуровневые языки управления принтерами. Программы gv и ghostview обеспечивают GUI-упаковщики для весьма уникальных ключей вызова и синтаксиса команд Ghostscript.
Другим превосходным примером данной модели является комбинация программ xcdroast/cdrtools. В дистрибутив cdrtools входит программа cdrecord(1) с интерфейсом командной строки. Код cdrecord специализируется на работе с аппаратным обеспечением приводов CD-ROM. Программа xcdroast представляет собой GUI-интерфейс и предназначена для того, чтобы создать комфортные условия работы для пользователя. Для выполнения большей части работы программа xcdroast{ 1) вызывает cdrecord( 1).