|
|
bb:extendnohost [2016/04/06 20:33] prospero78 [Использование возможностей расширения абстракции] |
bb:extendnohost [2020/10/29 07:08] |
====== Метод расширения абстракций System ====== | |
===== Предпосылки ===== | |
Системный слой **BlackBox** представлен набором абстрактных интерфейсов, отвечающих за те или иные функции, доступные компонентам. Эти абстракции представляют собой минимально необходимые возможности для полноценной работы. В текущей версии интерфейсы подобраны так, что являются платформо-независимыми. | |
А при дальнейшем расширении абстракций необходимо учитывать, что платформо-зависимые интерфейсы могут привести к //протеканию// абстракции. | |
| |
На примере простой абстракции местоположение файла ''Files.Locator'' (далее //локатор//) рассмотрим возможные варианты решения. | |
| |
[[http://oberoncore.ru/projects/bb-docu-ru|Русская документация по BlackBox]] | |
> Файловый локатор представляет папку в файловой системе. | |
> Локаторы используются в **Блэкбоксе** и иногда в командах, которые работают с файлами, не принадлежащими **Блэкбоксу**. | |
| |
Таким образом, локатор представлен //объектом в памяти//. | |
В большинстве случаев реализация локатора содержит указание на физическую папку на диске компьютера или в сети, и путь к такой папке представлен [[http://ru.wikipedia.org/wiki/%D0%9F%D1%83%D1%82%D1%8C_%D0%BA_%D1%84%D0%B0%D0%B9%D0%BB%D1%83|текстовой строкой]] в определенном формате, специфичном для ОС. | |
| |
Однако расширяемый интерфейс локатора позволяет реализовать местоположение файла, которое не поддерживает выражение в виде строки. Следовательно, абстрактный интерфейс получения полного текстового пути к файлу является слишком конкретным и ограничивает применение локатора. | |
| |
Поэтому в ''Files.Locator'' подобная возможность отсутствует. | |
| |
И все же, при написании прикладных компонентов могут возникать задачи которые требуют доступ к строке адреса файла на диске, отображение пользователю реального пути к выбранному файлу, сохранение адреса конкретного файла в реестре, и так далее. Таким образом, возможностей интерфейса локатора становится недостаточно, а прикладной компонент неизбежно становится более платформо-зависимым. | |
| |
===== Что требуется? ===== | |
Расширить возможности объекта базового типа ''Files.Locator'' в ряде задач при сохранении неизменности интерфейса ''Files.Locator'', сохранение возможности работы с альтернативными реализациями локатора, а так же минимизация платформо-зависимости прикладного компонента. | |
| |
===== Варианты решения ===== | |
{{ :no-host-locator-evo.png?nolink |}} | |
==== Изменение алгоритма компонента ==== | |
Наиболее очевидный способ: изменение алгоритма компонента. Действительно, в ряде случаев возможно изменение алгоритмов работы таким образом, что доступ к строке станет не нужен, а базового интерфейса локатора будет достаточно. | |
==== Прямое использование реализации локатора ==== | |
Наиболее простой способ, так как мы точно знаем, какие возможности может дать конкретная реализация локатора. Полная платформо-зависимость компонента становится платой за простоту. | |
==== Герметизация абстракции локатора внутри компонента ==== | |
После применения к платформо-зависимому компоненту [[bb:nohost|метод герметизации]] получится гибкая связка компонента и хост-компонента, который для той или иной платформы будет предоставляеть реализации интерфейса получения строки пути. Удобное и быстрое решение. Однако, при развитии системы компонентов появляется вероятность дублирования реализации хост-компонента для разных прикладных компонентов, а в масштабе сообщества - появление огромного количества несовместимых хост-компонентов с пересекающимися возможностями. | |
| |
Возможность выделения конкретной реализации хост-компонента в общеупотребимую подсистему/компонент ведет к еще одной проблеме - разрастание интерфейса базового класса хост-компонента. Так как существует бесчисленное количество ситуаций применения, возможны ситуации, когда существующих возможностей станет недостаточно, и разработчики будут вносить все новые методы и функции, что вызовет несовместимость различных версий реализации и проблему хрупкости базового класса. | |
==== Использование возможностей расширения абстракции ==== | |
Учитывая проблему возможного раздувания интерфейса, а так же тот факт, что единственным способом расширения интерфейса локатора является наследование, предлагается выполнить отвязку доступных функций локатора от интерфейса базового класса. Используем возможности шаблона "Объект-сообщение" для обеспечения параметрического полиморфизма методов локатора (в рамках языка **Компонентный Паскаль** полиморфизм реализуется данным образом). | |
Для этого опишем класс-наследник локатора: ''OberFiles.Locator'', в интерфейс которого добавим метод ''.HandleMsg(VAR msg: ANYREC)''. Реализацию этого локатора разместим в модуле ''OberHostFiles.Locator''. В данной реализации мы используем возможности модуля ''HostFiles'', для простоты. При этом, понятно, что реализация локатора с хэндлером может быть размещена сразу в реализации файловой подсистемы **BlackBox**, так как ''OberFiles.Locator'' по-прежнему является абстрактным типом. | |
Важной частью системы является механизм автоматического приведения типа ''Files.Locator'' к типу ''HostFiles.Locator'', при этом фактический результат операции приведения может содержать объект-обертку, так как с различными реализациями локатора могут быть связаны различные модули-реализации ''OberFiles.Locator'' (например, HostFiles <- OberHostFiles). | |
<code oberon2> | |
PROCEDURE GuardLoc*(loc: Files.Locator): Locator; | |
VAR ret: Locator; | |
BEGIN | |
ASSERT(loc#NIL, 20); | |
WITH loc: Locator DO | |
ret:=loc; | |
ELSE | |
IF hook#NIL THEN ret:=hook.GuardLoc(loc) END; | |
END; | |
RETURN ret | |
END GuardLoc; | |
</code> | |
Опираясь на базовый тип ''ANYREC'' мы описываем протокол (набор типов сообщений) взаимодействия с локатором, при этом, сам локатор не зависит от этих протоколов, они обрабатываются только в реализации ''OberHostFiles''. | |
Таким образом, описав сообщение ''GetPathStringMsg'' мы получаем возможность запросить у локатора текстовый путь. | |
Также подобные протоколы могут быть описаны в сторонних компонентах. Такие протоколы могут иметь разную детализацию аспектов платформы, тем самым позволяя разработчику гибко регулировать платформо-зависимость своего прикладного компонента. | |
<code oberon2> | |
VAR loc: Files.Locator; ober: OberFiles.Locator; gpm: OberProtocol.GetPathStringMsg; | |
BEGIN | |
loc:=Files.dir.This(''); | |
ober:=OberFiles.GuardLoc(loc); | |
IF ober#NIL THEN | |
ober.HandleMsg(gpm); | |
ELSE Log.String('данный тип фс ещё не поддерживается'); Log.Ln; END; | |
IF gpm.path#NIL THEN Log.String(gpm.path$); Log.Ln END; | |
END; | |
</code> | |
Но само наличие таких протоколов не гарантирует, что реализация локатора их поддерживает, и это понятно, ведь сообщения это способ ослабления связности компонентов. Однако, в интересах разработчиков реализаций абстрактных интерфейсов поддерживать наибольшее количество протоколов. Такие реализации смогут сообщать клиентам о поддерживаемых протоколах. | |
===== Результаты ===== | |
Реализовав описанный способ расширения мы решили проблему наращивания функциональности локатора без изменения базового типа, избежав проблему появления хрупкого базового класса с помощью параметрического полиморфизма, а платформо-зависимость клиентских модулей может регулироваться посредством выбора нужного протокола. | |
Таким образом, подсистема с набором подобных уточняющих абстракций, размещенная в общеупотребимой (а возможно и стандартной для сборки BlackBox) подсистеме сможет обеспечить развитие возможностей с сохранением обратной совместимости компонентов и интерфейсов. | |
===== Пример использования ===== | |
Прототип реализации для эталона BlackBox размещен в подсистеме [[https://bitbucket.org/petryxa/sith|Sith]]. | |
| |
| |
--- //[[petryxa.clever@gmail.com|Кушнир П. М.]] 2013/12/20 21:34// | |