Глава 18. Конструирование систем из коробочных компонентов
Конструирование систем из коробочных компонентов (в соавторстве с Робертом С. Сикордом и Мэтью Бассом) [10] На блюде все это смотрится так красиво — чьи-то пальчики основательно потрудились! Джулия Чайлд о повой французской кухне Мы постоянно делаем упор на связь между требованиями по качеству и архитектурой. Утверждение это основывается на допущении о том, что контроль над проектным решением системы подразумевает контроль над реализуемыми ею атрибутами качества. Чем дальше, тем больше оно опровергается реальной практикой. Готовые компоненты для конструирования систем со временем получают широкое распространение — связано это с экономическими соображениями, а также с тем, что во многих технических областях для разработки приложений требуются крайне специализированные знания. Компоненты, с одной стороны, вносят в процесс проектирования существенные коррективы, но с другой — ограничивают архитектуру. Отбираемые для реализации определенного функционального набора, компоненты выражают те или иные архитектурные допущения (а значит, и допущения по качеству). Задача архитектора состоит в том, чтобы обеспечить корректность выбора этих допущений и их совместимость. Начиная с 1960-х годов принятие многих проектных решений в значительной степени зависит от конкретной операционной системы. Системы управления базами данных сформировались как фактор влияния в начале 1970-x. Повсеместное распространение компьютеров привело к повышению возможностей использования для реализации системных задач компонентов, разработанных третьей стороной. Само по себе наличие компонентов не является принудительным стимулом к их использованию (и этом контексте см. врезку «Quack.com»), что, однако, не сокращает потребность в изучении механизмов их внедрения в систему Процесс отбора коробочных компонентов для системы предполагает поиск сборок (assemblies) совместимых компонентов, формулирование механизма реализации с их помощью атрибутов качества и принятие решений относительно возможности их интеграции в конструируемую систему. QUACK.COM Истоки Компания Quack.com основана в конце 1998 года двумя бывшими сотрудниками Института программной инженерии (Джероми Карье (Jeromy Carriere) и Стивом Вудсом (Steve Woods)), а также профессором Гавайского университета Алексом Квилиси (Alex Quilici). Вооружившись идеей обеспечить доступ к коммерческой информации и данным иного характера no телефону, они сконструировали демонстрационную версию программы и к концу лета 1999-го добились финансирования со стороны ряда «благодетелей» и венчурных компаний. Осознавая важность голосовой архитектуры, они выстроили «реальную» систему в виде голосового портала поверх комплекта инструментов и платформы публикации голосовых приложений. В результате им удалось оперативно сконструировать и организовать сопровождение широкого ряда приложений. В принципе, спроектированная ими платформа имела все шансы на доминирование в зарождающейся индустрии. Через десять месяцев после начала финансирования они выпустили предварительную версию потребительского голосового веб-портапа. Он предоставлял услуги доступа к информации о погоде, кинофильмах, курсах акций и прочим данным потелефону, 31 августа 2000-го компания вошла в состав America Online. Вскоре — 25 октября 2000 года — AOL выпустила приложение AOLbyPhone, сконструированное группой разработчиков Quack на основе их же платформы и инструментального набора. История Quack.com наглядно выражает роль и ограничения, присущие коробочным компонентам. На основе вышеизложенных сведений мы можем сделать вывод о том, что компании требовалось вывести свой голосовой портал на рынок как можно скорее. Сказывалась дея- тельность в этой области других начинающих компаний, причем некоторые из них располагали более серьезной финансовой поддержкой. Сотрудники Quack пытались найти как можно больше готовых к употреблению компонентов, и результаты этого поиска оказали на конечную архитектуру серьезное влияние. Именно по этой причине компании удалось выйти на рынок всего через девять месяцев после начала внешнего финансирования. Первый портал Quack, внесший весомый вклад в последующий успех проекта, оказался вполне полезным сам по себе, однако широкого внимания пользователей так и не получил. После приобретения проекта корпорацией AOL коммерческие приоритеты резко поменялись. Располагая базой из 34 000 000 подписчиков, AOL вывела на первый план такие коммерческие факторы, как готовность и производительность. Портал Quack.com предстояло подготовить к более интенсивному режиму использования и обеспечить соответствие более жестким требованиям по готовности. Для подгонки проекта под новые требования было решено переписать компоненты. Вертикальное масштабирование и повышение готовности в рамках гибкой архитектуры не представляло особых проблем; в то же время предсказать реакцию компонентов на предполагаемые изменения оказалось категорически невозможно. Получить контроль над производительностью и готовностью системы в целом можно было лишь путем их переписывания (в порядке убывания критичности). Многие другие системы прошли аналогичный этап. Недавно мы посетили небольшую начинающую компанию, занятую построением новой линейки программных продуктов. Понимая, что второго шанса произвести первое впечатление не будет, ее сотрудники поставили надежность и масштабируемость на вершину списка архитектурных задач. По словам их архитектора, «если функция не слишком важна, мы ограничиваемся коробочным компонентом. Если в отношении того или иного аспекта системы существует официальный или фактический стандарт, подходящий коробочный компонент можно выбрать — скорее всего, этот стандарт соблюдается разными производителями. Если же у нас есть какие-то сомнения и мы не можем найти очевидных решений, значит, нужно конструировать компонент собственными силами». Прежде чем перейти к работе над новым проектом, этот архитектор участвовал в создании крупной поисковой системы и контент-провайдера. За четыре года число суточных посещений увеличилось с 45 000 до 45 000 000. Работая с системой многомиллионной посещаемости, он очень быстро научился действовать так, чтобы не просыпаться по ночам в связи с очередной проблемой, угрожающей коммерческой деятельности. Как средство пакетирования функциональности и ее оперативного внедрения коробочные компоненты очень удобны. С другой стороны, они не позволяют архитектору получить полный контроль над атрибутами качества в системе. Подобно многим другим средствам программной инженерии, компоненты очень полезны, но решения всех проблем от нихждать не приходится. - LJB и PCC В настоящей главе мы рассмотрим упрощенный процесс отбора компонентов исходя из практических соображений. Сначала формулируются гипотезы о том, как должны «работать» выбранные компоненты. Затем для проверки этих гипотез строятся простые макеты. Наконец, после оценки функционирования макетов, на случай опровержения гипотез составляется запасной план. Основной принцип этой методики состоит в том, что отбирать единичные компоненты не имеет смысла. Отбирать и тестировать нужно сборки совместно функционирующих компонентов. Кроме того, ниже мы опишем приложение данного процесса к недавно созданной системе. 18.1. Воздействие компонентов на архитектуру Предположим, вы разрабатываете программное обеспечение системы управления химическим предприятием. Специальные дисплеи на этом предприятии информируют операторов о состоянии проводимых реакций. Одна из основных задач разрабатываемого программного обеспечения заключается в выводе информации на эти дисплеи. Вам известно, что среди продуктов, предлагаемых одним из производителей, числятся элементы управления пользовательским интерфейсом, способные решить эту задачу. Поскольку купить проще, чем сконструировать, вы собираетесь приобрести эти элементы управления, которые, кстати, написаны в единственной версии — на Visual Basic. Какое влияние на архитектуру окажет принятое решение? Либо на Visual Basic с присущей ему ориентированностью на обратные вызовы придется написать всю систему, либо операторскую часть нужно каким-то образом изолировать от всех остальных частей системы. Это основополагающее структурное решение, необходимость в принятии которого обусловливается отбором единичного компонента для конструирования отдельной части системы. Применение в разработке программных средств коробочных компонентов, при всем удобстве, способствует появлению дополнительных проблем. В частности, очень важным с точки зрения архитектуры ограничением являются возможности и обязанности компонентов. Все компоненты, за исключением самых простых, основываются на допущении об использовании того или иного архитектурного образца, нарушать которое довольно сложно. К примеру, HTTP-сервер предполагает применение клиент-серверного архитектурного образца с определенными интерфейсами и механизмами интегрирования серверной функциональности. Если проектируемая архитектура не соответствует допущениям, заложенным в компоненте HTTP-сервера, задача интеграции очень сильно усложняется. Поскольку любые компоненты направлены на соответствие определенному архитектурному образцу, решение относительно сборки компонентов, которые предполагается отобрать (или которые уже отобраны) для проектируемой системы, имеет смысл принимать загодя, еще до выбора архитектуры как таковой. Присущие компонентам архитектурные допущения и механизмы их успешной интеграции зачастую обусловливаются или, по меньшей мере, сильно зависят от конкретного набора компонентов. Следовательно, решения относительно отбора компонентов и механизма их взаимодействия необходимо принимать до завершения работы над архитектурой. 18.2. Архитектурное несоответствие Далеко не все компоненты способны к взаимодействию — даже если это коммерческие продукты, совместимость которых утверждается производителем. Зачастую они «почти совместимы», причем «почти» в данном случае означает фактическую несовместимость. Бывают и более хитрые ситуации — компоненты внешне демонстрируют способность к совместной работе (собранный код компилируется и даже исполняется), и тем не менее из-за того что реальный механизм взаимодействия компонентов не отвечает ожиданиям, реакции оказываются некорректными. Подобного рода ошибки могут быть едва заметны — особенно в системах реального времени и в параллельных системах, в которых компоненты основываются на безобидных на первый взгляд допущениях о времени и относительной последовательности операций. Короче говоря, компонент, если он не разработан специально для вашей системы, может не соответствовать всем вашим требованиям, более того, он может отказаться работать совместно с другими компонентами. Хуже всего то, что для проверки применимости компонента его, как правило, нужно сначала приобрести. Дело в том, что предоставляемой информации об атрибутах качества интерфейсов компонентов обычно оказывается недостаточно. Насколько безопасен ваш компилятор? Насколько надежна ваша почтовая система? Насколько точна математическая библиотека, к которой обращаются ваши приложения? И что делать, если окажется, что эти элементы «недостаточно» безопасны/надежны/точны? Подобного рода препятствия к успешной интеграции компонентных систем Гарлан (Garlan), Аллен (Allen) и Окерблум (Ockerbloom) назвали архитектурным несоответствием (architectural mismatch). Эту проблему они рассматривают как несогласованность допущений, принимаемых в раздельно разработанных компонентах. Во многих случаях эта несогласованность обнаруживает себя в архитектуре — например, если два компонента не могут договориться о том, кто из них кого запускает. Архитектурные несоответствия чаще всего обнаруживаются и период интеграции — система элементарно отказывается компилироваться, компоноваться или исполняться. Архитектурное несоответствие есть частный случай интерфейсного несоответствия (interface mismatch). В данном случае имеется в виду определение интерфейса по Парнасу (Parnas) — допущения компонентов друг о друге. Это определение шире стандартного понятия интерфейса, которое, к сожалению, прочно прижилось в современной практике и соответствует интерфейсу прикладного программирования компонента (пример тому — спецификация интерфейса). Интерфейс прикладного программирования содержит имена программ и их параметров, а также (иногда) доносит отдельные сведения об их поведении; тем не менее, это лишь малая часть информации, необходимой для обеспечения корректного использования компонента. В полную спецификацию интерфейса должны входить сведения о побочных эффектах, потреблении глобальных ресурсов, требованиям по координации и пр. Подобно архитектурному несоответствию, интерфейсное несоответствие обнаруживается в период интеграции и может выступать причиной возникновения упомянутых выше хитроумных ошибок в период исполнения. Допущения можно разделить на два подвида. Допущения о предоставляемых услугах (provides assumptions) характеризуют службы, которые компонент предоставляет пользователям или клиентам. Допущения о требованиях (requires assumptions) подробно описывают службы и ресурсы, необходимые для корректного функционирования компонента. Несоответствие между двумя компонентами происходит в случае, если принимаемые ими допущения двух обозначенных разновидностей не совпадают. Как бороться с интерфейсным несоответствием? Помимо изменения требований — так, чтобы вчерашние дефекты стали сегодняшними характеристиками (да, иногда можно сделать и так), — есть еще три способа. ♦ Специфицирование и проверка компонентов системы позволяет предотвращать несоответствия. ♦ Обнаруживать те несоответствия, которые не удалось предотвратить, помогает тщательная квалификация компонентов. ♦ Исправлять выявленные несоответствия следует методом адаптации компонентов. Методики исправления интерфейсных несоответствий Проблема исправления несоответствий (или «исправления компонентов/интерфейсов») до сих пор не удостоена систематического анализа. Термины наподобие «связки компонентов» отражают характер интеграционного кода и соответствуют статусу «второй сорт», присваиваемому их разработке. Исправление интерфейсных несоответствий зачастую трактуется как задача хакеров и (иногда) неопытных программистов, у которых эстетическое ощущение не опустошено тысячами «поделок», из которых состоит процесс интегрировании коробочных компонентов. По нашему мнению, это тот самый случай, когда надежность цепочки равна надежности ее слабого звена. Иначе говоря, от качества исправления компонента напрямую зависит успех (или неспособность) реализации общесистемных задач no качеству наподобие готовности и модифицируемости. Первым шагом на пути систематизации процесса исправления интерфейса мы считаем классификацию основных методик, которыми эта задача решается, и их характеристик. Есть очевидный метод исправления. Заключается он в том, чтобы изменить код проблемного компонента. Это решение далеко не всегда осуществимо — коммерческие продукты довольно редко сопровождаются исходным кодом. Если же речь идет о старом компоненте, то найти его исходный код или человека, который способен в нем разобраться, обычно оказывается крайне сложно. Даже если такая возможность есть, во многих случаях корректировать код компонента нежелательно. Компоненты по определению используются во множестве систем. Таким образом, если изменения, направленные на обеспечение работоспособности компонента в новой системе, приведут к тому, что он перестанет работать в старых системах, сопровождать придется уже не одну, а несколько его версий. В качестве альтернативы изменению кода одного или обоих несоответствующих компонентов возможно введение кода, согласующего их взаимодействие. Исправительный код делится на три класса: оболочки, мосты и посредники. Оболочки Термин «оболочка» (wrapper) предполагает инкапсуляцию, посредством которой компонент упаковывается в альтернативную абстракцию. Иначе говоря, клиент обращается к службам «завернутого» компонента исключительно через предоставляемый оболочкой альтернативный интерфейс. Можно сказать, что оборачивание — это создание альтернативного интерфейса компонента. Трансляция интерфейса подразумевает проведение трех операций: ♦ трансляцию элемента интерфейса компонента в альтернативный элемент; ♦ сокрытие элемента интерфейса компонента; ♦ недопущение модификации элемента базового интерфейса компонента. Предположим, что в нашем распоряжении унаследованный компонент, предоставляющий программный доступ к службам визуализации графики. При этом программная служба существует в виде библиотек Fortran, а визуализация графики осуществляется в терминах специальных графических примитивов. Задача в том, чтобы, во-первых, сделать компоненты доступными клиентам через CORBA, а во-вторых, заменить специальные графические примитивы графическими элементами X Window System. Для специфицирования нового интерфейса, обеспечивающего доступность служб компонентов клиентам CORBA, имеет смысл обратиться к языку описания интерфейсов (interface description language, IDL) — это решение удачнее связывания с библиотеками Fortran. В качестве кода, исправляющего допущения интерфейсов о предоставляемых службах, выступает «скелетный код» на С++, который генерируется компилятором IDL автоматически. Кроме того, в состав исправительного кода входит рукописный код, привязывающий скелет к функциональности компонента. Что касается оборачивания допущений о требованиях компонентною интерфейса, необходимого для окончательного перехода от специальных графических элементов к системе X Window, то здесь есть несколько вариантов. Одно из решений заключается в том, чтобы написать уровень для библиотеки трансляции, чей API соответствует API специальных графических примитивов; реализация этой библиотеки будет проводить трансляцию вызовов специальных графических элементов в вызовы X Window. Мосты Мост (bridge) осуществляет преобразование допущений о требованиях одного компонента в допущения о предоставляемых услугах другого компонента. Основное различие между мостом и оболочкой состоит в том, что код исправления, из которого состоит мост, не зависит ни от одного конкретного компонента. Кроме того, мост в обязательном порядке явно вызывает внешний агент — в этом качестве может выступать один из тех компонентов, которые соединяются мостом. Последнее обстоятельство свидетельствует о переходном характере мостов, а также о том, что конкретная трансляция определяется в период конструирования моста (например, во время его компиляции). Почему указанные различия так важны, станет ясно из обзора посредников. Как правило, мосты осуществляют более узкий, чем оболочки, круг трансляций интерфейсов — связано это с тем, что они специализируются на конкретных допущениях. Чем больше допущений принято для моста, тем меньше компонентов, с которыми его можно применить. Предположим, что в нашем распоряжении два унаследованных компонента. Один создает выходные макеты проектных документов на PostScript, а другой отображает документы в формате PDF (Portable Document Format). Задача — интегрировать эти компоненты, чтобы в отношении любого проектного документа можно было запустить компонент отображения. Наиболее очевидным решением исправления интерфейса для данного сценария представляется простой мост, транслирующий PostScript в PDF. Писать его можно независимо от конкретных характеристик двух наших гипотетических компонентов — к примеру, имеет смысл создать механизм, извлекающий данные из одного компонента и наполняющий ими другой. В этом контексте на ум сразу приходят фильтры UNIX, однако это не единственный механизм, способный выполнить поставленную задачу. Для исполнения такого моста можно написать сценарий. Он должен будет разбираться со спецификой интерфейсов интегрируемых компонентов. Следовательно, поскольку внешний агент/оболочка (shell) имеет дело с интерфейсами на обоих концах отношения интеграции, он не подпадает под наше определение оболочки (wrapper). С другой стороны, можно сделать так, чтобы каждый из двух компонентов мог самостоятельно запускать фильтр. В этом случае механизм исправления будет представлять собой гибрид оболочки и фильтра — в оболочке будет содержаться исправительный код, необходимый для определения потребности в запуске моста и для инициирования самого запуска. Посредники Посредники сочетают свойства мостов и оболочек. Основное различие между мостами и посредниками состоит в том, что последние, помимо прочего, осуществляют планирование, которое, в конечном счете, приводит к заданию трансляции в период прогона (как вы помните, мосты устанавливают трансляцию в период своего конструирования). Общность посредника и оболочки выражается также в том, что и те и другие становятся более явными компонентами общей системной архитектуры. Другими словами, примитивные семантически, носящие зачастую переходный характер, мосты представляют собой вспомогательные механизмы исправления, выполняющие в рамках проектного решения неявную роль; что же касается посредников, то их семантическая сложность и автономия (устойчивость) в период прогона позволяют им исполнять в программной архитектуре более заметную роль. Для иллюстрации посредников обратимся к присущей им функции планирования в период прогона — благо именно в этом состоит разница между посредниками и мостами. Возьмем, к примеру, сценарий интеллектуального слияния данных. Рассмотрим датчик, генерирующий высокоточные данные в больших объемах. В период исполнения действуют разные потребители информации с разными рабочими допущениями о точности данных. Одному потребителю, который, скажем, допускает низкую точность данных, нужно «выдрать» из потока данных определенную информацию. Другому потребителю с аналогичными требованиями по точности, но иными характеристиками по части пропускной способности, требуется временная буферизация данных. В каждом из этих случаев согласование датчика и его потребителей выполняет посредник. Рассмотрим другой сценарий — сборка последовательности мостов в период прогона, направленная на интеграцию компонентов, при условии, что их требования по интеграции становятся известны именно в этот период. К примеру, один компонент производит данные в формате D0, а другой потребляет данные в формате D2. Прямого моста D°->D2 может и не быть, зато есть мосты D°->D' и D'->D2, которые можно сцепить. Роль посредника, таким образом, будет заключаться в том, чтобы собрать эти мосты и тем самым провести преобразование D°->D2. Этот сценарий одновременно распространяется на традиционное понятие настольной интеграции и на более экзотичные адаптивные системы периода прогона. Методики обнаружения интерфейсных несоответствий Для того чтобы исправить несоответствие, его сначала нужно обнаружить. Представленный ниже процесс выявления несоответствий являет собой усовершенствованный вариант квалификации компонентов. Термин квалификация компонентов (component qualification) обозначает процесс, в ходе которого проверяется соответствие коммерческого компонента ряду критериев «годности к использованию». Среди неотъемлемых процессов квалификации компонентов — макетная интеграция компонентов-кандидатов. На этом этапе интеграции выявляются малозаметные, трудно поддающиеся обнаружению разновидности интерфейсных несоответствий — например, состязания за ресурсы. Фактически, потребность в проведении этого этапа обусловливается недостаточностью наших познаний в области интерфейсов компонентов. Проверка эта исходит из наблюдения, согласно которому для предоставления каждой службы компонента необходимо удовлетворить ряд принимаемых им допущений о требованиях. Ведь служба — это не более чем удобный способ описания механизма пакетирования функциональности компонента в расчете на ее применение клиентами. Таким образом, квалификация предполагает: ♦ выявление для каждой службы, которую предполагается задействовать в системе, принимаемых компонентом допущений о требованиях; ♦ удовлетворение каждого допущения о требованиях соответствующим допущением о предоставляемых услугах, принимаемым системой. Перейдем к конкретике и рассмотрим квалификацию компонента, предоставляющего многопоточным приложениям службы управления примитивными данными. В частности, этот компонент позволяет записывать значения данных в указанное местоположение (которое может задаваться с помощью ключа). В целях предоставления многопоточной службы хранения компоненту требуется от операционной системы ряд ресурсов — к примеру, файловая система и примитивы блокировки. Перечень принимаемых компонентом допущений о требованиях может быть (а может и не быть) составлен производителем компонента; если таковой отсутствует, значит, выявлением этих требований приходится заниматься оценщику компонента. В любом случае, конкретное отображение позволит сделать выводы о воздействии обновления операционной системы на данное отношение интеграции. Иными словами, меняется ли в ходе обновления операционной системы семантика операций fwrite и fLock? В упомянутый перечень можно внести дополнительные допущения — к примеру, возможно такое допущение о представляемых услугах, согласно которому у устройства хранения должен быть интерфейс CORBA. В зависимости от конкретной реализации брокера объектных запросов это допущение предполагает или не предполагает появления нового допущения о предоставляемых услугах, согласно которому на базовой машине, размещающей данное устройство хранения, должен исполняться процесс брокера объектных запросов. На основе перечня допущений иногда выявляются значительно более интригующие зависимости. К примеру, тот же самый гипотетический компонент может устанавливать заданное (но переменное) число клиентов, работающих с одним внешним процессом диспетчера данных, — соответственно, для всех клиентов сверх заданного количества нужно выделять дополнительные процессы. Подобные допущения позволяют точно определиться с тем, соответствует ли компонент всем ограничениям по ресурсам системы. Методики предотвращения интерфейсных несоответствий Согласно одному из методов предотвращения интерфейсных несоответствий, с самых ранних стадий проектирования следует систематически устанавливать как можно больше допущений об интерфейсе компонента. Возможно ли специфицировать все допущения, принимаемые компонентом о своем окружении, а также те нз них, которые ему дозволено принимать используемыми компонентами? Естественно, нет. Имеет ли смысл выделить важное подмножество допущений и есть ли у нас свидетельства, подтверждающие эффективность такого подхода? Да, есть. В проектном решении программного обеспечения A-7E, обзор которого содержится в главе 3, система подразделяется на иерархическое дерево модулей. На его высшем уровне содержится три модуля, а на листьях их 120. Для каждого листового модуля составлена спецификация интерфейса, в которой обозначаются программа доступа (в объектном проектировании эти программы называются методами), требуемые и возвращаемые параметры, видимые следствия вызова программы, параметры генерации системы, предусматривающие регулировку модуля в период компиляции, а также ряд допущений (примерно по дюжине на каждый модуль). В допущениях выражались утверждения относительно достаточности (sufficiency) предоставляемых каждым модулем служб, а также возможности реализации (implementability) каждой службы в категориях требуемых модулям ресурсов. Среди конкретных тематических областей числились потребление совместно используемых ресурсов, следствия прохождения через средства модуля множества потоков управления, а также производительность. Эти допущения должны были оставаться неизменными на протяжении всего жизненного цикла системы, в которой модифицируемость позиционировалось как основная проектная задача. Обращаясь к допущениям, проектировщики модулей проверяли, в полной ли мере им удалось инкапсулировать в своих модулях области изменений. Специалисты в предметной и прикладной областях с помощью допущений проводили оценочные мероприятия, а пользователи модулей удостоверяли их пригодность. По убеждению участников проекта A-7, внимательное отношение к интерфейсам модулей, по сути, исключает необходимость проведения этапа интеграции (в рамках жизненного цикла программы). Почему? Средством предотвращения архитектурных несоответствий они избрали тщательное специфицирование — в частности, проверку достоверности явных перечней допущений силами специалистов в предметной и прикладной областях. Определение интерфейса как набора допущений, выводящее его за рамки интерфейса прикладного программирования, расширяет понимание процесса специфицирования интерфейсов компонентов, взаимодействующих друг с другом в различных контекстах. Приватные интерфейсы (private interfaces) раскрывают только те принимаемые базовым интерфейсом компонента допущения о предоставляемых услугах и требованиях, которые являются значимыми в контексте требований по интеграции в конкретной системе или даже в контексте ее отдельных компонентов. Таким образом, информация о ненужных средствах, присутствие которых приводит к излишнему усложнению системы, скрывается. Мы перечислили преимущества нескольких различных интерфейсов для одного компонента в противоположность единому многоаспектному базовому интерфейсу. Ужесточение контроля над межкомпонентными зависимостями увеличивает возможности манипулирования отдельными видами развития систем — в частности, предсказуемость воздействия модернизации коммерческого компонента на новую версию. Оболочки как стратегия исправления ориентированы на обеспечение конфиденциальности. Архитектурные образцы, со своей стороны, предусматривают стандартные формы удовлетворения допущений интерфейсов о предоставляемых услугах и требованиях — в системе на основе архитектурного образца, определяющего компактный набор типов компонентов, количество производных базового интерфейса значительно сокращается. Параметризованным (parameterized) называется интерфейс, предусматривающий возможность изменения допущений о предоставляемых службах и требованиях перед вызовом службы соответствующего компонента; эта возможность обеспечивается путем изменения значения переменной. В языках программирования давно сформировались методики параметризации с развитой семантикой, позволяющие регулировать интерфейс компонента с момента его проектирования и кодирования до момента вызова его служб (примеры таких методик — настраиваемость в Ada и полиморфизм в ML). Возможность настройки в коммерческих продуктах часто обеспечивается за счет параметризации (например, файлов ресурсов и переменных среды). Параметризованные интерфейсы предусматривают создание адаптационного кода, который по отношению к компоненту является одновременно внешним (в том, что касается настройки значений параметров) и внутренним (по части приспособления к значениям параметров). Подобно посреднику, который определяется как мост с логикой планирования, согласованный интерфейс (negotiated interface) представляет собой параметризованный интерфейс с логикой самоисправления. Параметризация такого интерфейса производится либо его же средствами, либо внешним агентом. Можно даже утверждать, что согласованные интерфейсы характерны для программных средств с автоматическим конфигурированием — согласование при этом проходит в форме одностороннего диалога по принципу «решайте сами», проводящегося между программой конструирования компонентов и базовой платформой. Есть и другой вариант — некоторые продукты (в частности, модемы) в период прогона (вместо периода установки) определяют взаимоприемлемые параметры связи путем регулярного запуска специальных протоколов. Подобно оболочкам, которые в качестве стратегий исправления устанавливают полупрозрачность, посредники выражают стратегию исправления, направленную на введение в несогласованные компоненты согласованных интерфейсов.
|