Ритчи и Томпсон жили по этому принципу. Долгое время после того как ресурсные ограничения на ранних Unix-программах были смягчены, они работали над тем, чтобы поддерживать С в виде настолько тонкого уровня над аппаратным обеспечением, насколько это возможно.
Когда я просил о какой-либо особенно экстравагантной функции в С, Деннис обычно говорил мне: "Если тебе нужен PL/1, ты знаешь, где его взять". Ему не приходилось общаться с каким-либо маркетологом, утверждающим: "На диаграмме продаж нам нужна галочка в рамочке!".
Майк Леcк.
История С также подтверждает важность существования работающей эталонной реализации до стандартизации. Повторно данная тема затрагивается в главе 17, где рассматривается развитие стандартов С и Unix.
Одним из последствий того влияния, которое стиль 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 ) — библиотека с набором известных входных точек, которая динамически загружается после запуска и предназначена для решения специализированной задачи. Для работы таких подпрограмм необходимо, чтобы вызывающая программа была организована в значительной степени как документированная служебная библиотека, в которую подключаемая подпрограмма может направить обратный вызов.
4.4.1. Учебный пример: подключаемые подпрограммы GIMP
Программа GIMP (GNU Image Manipulation program— программа обработки изображений) разрабатывалась как графический редактор с управлением посредством интерактивного GUI-интерфейса. Однако GIMP построена как библиотека подпрограмм обработки изображений и вспомогательных подпрограмм, которые вызываются сравнительно тонким уровнем управляющего кода. Управляющий код "знает" о GUI, но не имеет непосредственной информации о форматах изображений. Библиотечные подпрограммы, напротив, распознают форматы изображений, но не имеют информации о GUI-интерфейсе.
Читать дальше