~~ODT~~ # Проблема герметичности #

Блэкбокс с точки зрения пользователя является обычным приложением. То есть, для работы ему необходима операционная система.

Блэкбокс с точки зрения программной архитектуры является компонентным каркасом, то есть средой для запуска и управления компонентами и их работой.

Схема

Рис.1. Переход от «хоста» к «платформе»

Компонент с точки зрения каркаса является совокупностью скомпилированных модулей. Модули могут использовать возможности других модулей, таким образом появляется зависимость (обозначена стрелкой по направлению от зависимого модуля к необходимому).

Среди всех компонентов можно выделить такие, которые не зависят от операционной системы и такие, которые зависят от неё.

В отдельную группу можно выделить компоненты, необходимые для работы каркаса - системный слой. Остальные компоненты не являются необходимыми, и могут быть выделены в прикладной слой.

Зависящие от операционной системы компоненты системного слоя составляют некий «прокладочный» слой, позволяющий каркасу как бы «плавать» на нижележащей операционной системе. Если прикладные компоненты зависят только от «прокладки», то появляется возможность заменить «прокладку», перенеся тем самым каркас на другую операционную систему без повреждений прикладного слоя.

Рассмотрим устройство системного слоя в [эталоне](http://oberoncore.ru/blackbox/oberoncore_official_position) BlackBox. Основой системы является модуль *Kernel*, который реализует поддержку времени выполнения для приложений BlackBox (см. [документацию](http://oberoncore.ru/library/ermakov_vnutrennij_interfejs_kernel) *Kernel*). Модуль *Kernel* использует возможности операционной системы (на рисунке эта зависимость обозначена красной стрелкой). Для работы клиентских (прикладных) модулей необходимы базовые абстракции файловой системы, оконной системы, отображений, контейнеров, диалогов и т.п. В эталоне эти абстракции собраны в подсистеме *System* (см. рис.), часть реализаций которых платформо-независима, а часть платформо-зависима. Платформо-независимые реализации *System* содержатся в подсистеме *Std*. В то же время, в подсистеме *Std* есть такие абстракции, которым тоже необходима платформо-зависимая реализация (например, элементы управления и диалоговые окна). Платформо-зависимые реализации *System* и *Std* содержатся в подсистеме *Host*.

Разделение *System* на абстрактный интерфейс и платформо-зависимую реализацию позволяет добиться герметичности платформо-независимой части системного слоя. Герметичность позволяет заменять платформо-зависимые системные модули без модификации клиентских модулей.

Герметичность здесь понимается как отсуствие протечек абстракций системного и прикладного слоя.

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

# Решение проблемы нарушения герметичности #

## Модификация модуля Kernel ##

На схеме показаны зависимости прикладного и системного слоя от модуля *Kernel*.

Эти зависимости не позволяют нам произвести безопасную замену модуля *Kernel*, например, при замене операционной системы. Безопасность, в данном случае, это соблюдение контрактов интерфейса. Текущий интерфейс модуля *Kernel* явно зависит от модуля *WinApi*, что предполагает изменение этого интерфейса (а значит контрактов), при смене ОС. Это и есть нарушение герметичности системного слоя БлэкБокса.

В целях устранения данного нарушения герметичности предлагается разделение интерфейса модуля *Kernel* на платформо-независимую (условно: Oberkernel) и платформо-зависимую части.

Плюсом данного решения является полное изолирование клиентских модулей от платформы.

Минусом является то, что модуль *Kernel* это специфический системный модуль: невозможно наверняка предугадать абстракции, которые могут понадобиться клиентам. А необходимые для работы каркаса низкоуровневые функции *Kernel* (ассемблерный код, прямая работа с памятью) не могут быть реализованы (или хотя бы представлены в виде абстракций) платформо-независимо.

Решением данной проблемы может стать использование специальных соглашений и разделение платформо-зависимых компонентов на абстракции и платформо-зависимые реализации (Host-компоненты).

## Устранение зависимостей от подсистемы Host ##

Модули подсистем *Std* и *System*, входящие в эталон BlackBox, по большей части являются платформо-независимыми. Однако, в некоторых местах обнаруживаются прямые (импорт) или косвенные (через строковые константы/ресурсы, отображения на формах и т.д.) зависимости от подсистемы *Host*.

Эти зависимости в той или иной степени обеспечивают функционирование эталона, при этом ухудшая его платформо-независимость. Так как функциональность *Host* нужна системному слою, то необходимо сохранить её, но уже с использованием герметичных решений.

Для устранения зависимости подсистемы *Std* от *Host* введём ряд дополнительных абстракций в подсистему *System*, которые заместят необходимые ранее зависимости. А подсистему *Host* дополним подсистемой *Oberhost* (рабочее название, которое может измениться в дальнейшем), в которой находятся реализации этих абстракций.

Некоторые прямые и косвенные зависимости (формы, строковые ресурсы) подсистем *Std* и *System* могут быть перемещены в подсистему *Host* целиком, или частично. Например, модуль *StdMenuTool* или содержимое меню *(System)Menus*, которое состоит из текстовых команд зависящих от подсистемы *Host*. Такие команды могут быть размещены в меню *(Host)Menus*.

Прикладные компоненты с зависимостями от *Host*, должны быть аналогичным образом преобразованы в набор абстракций и Host-реализаций.


Кушнир П.М., Кузьмицкий И.А.

Ярославль, 2013 г.