Одним из последствий того влияния, которое стиль Unix-программирования оказал на модульность и четко определенные API-интерфейсы, является устойчивая тенденция к разложению программ на фрагменты связующего уровня, объединяющего семейства библиотек, особенно общих библиотек (эквивалентов структур, которые в Windows и других операционных системах называются динамически подключаемыми библиотеками или DLL (Dynamically-Linked Libraries)).

Если подходить к проектированию тщательно и обдуманно, то часто возникает возможность разделить программу таким образом, чтобы она состояла из главной части поддержки пользовательского интерфейса (т.е. политики) и совокупности служебных подпрограмм (т.е. механизма) без связующего уровня вообще. Данный подход представляется особенно целесообразным в ситуации, когда программа должна выполнять большое количество узкоспециальных операций с такими структурами данных, как графические изображения, пакеты сетевых протоколов или блоки управления аппаратного интерфейса. В статье "The Discipline and Method Architecture for Reusable Libraries" [87] собрано несколько общих полезных, конструктивных советов, исходящих из традиций Unix, особенно полезных для решения проблем управления ресурсами в библиотеках такого вида.

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

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

API-интерфейсы должны сопутствовать программам и наоборот. API, для использования которого необходимо написать C-код и который невозможно без труда вызвать из командной строки, очень тяжело изучать и использовать. И наоборот, невероятно сложно использовать интерфейсы, единственной открытой и документированной формой которых является какая-либо программа и которые невозможно просто вызвать из программы на С, — например, route(1) в прежних Linux-системах.

Генри Спенсер.

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

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

<p>4.4.1. Учебный пример: подключаемые подпрограммы GIMP</p>

Программа GIMP (GNU Image Manipulation program— программа обработки изображений) разрабатывалась как графический редактор с управлением посредством интерактивного GUI-интерфейса. Однако GIMP построена как библиотека подпрограмм обработки изображений и вспомогательных подпрограмм, которые вызываются сравнительно тонким уровнем управляющего кода. Управляющий код "знает" о GUI, но не имеет непосредственной информации о форматах изображений. Библиотечные подпрограммы, напротив, распознают форматы изображений, но не имеют информации о GUI-интерфейсе.

Библиотечный уровень документирован (и фактически распространяется в виде пакета "libgimp" для использования другими программами). Это означает, что программы на языке С, которые называются "подключаемыми подпрограммами", могут динамически загружаться в GIMP и вызывать библиотеку для обработки изображений, фактически принимая на себя управление на том же уровне, что и GUI-интерфейс (см. рис. 4.2).

Рис. 4.2. Связи между вызывающей и вызываемой программой в редакторе GIMP с загруженной подключаемой подпрограммой

Перейти на страницу:

Все книги серии Программирование для профессионалов

Похожие книги