Сервісно-орієнтована архітектура

Gaphor має сервіс-орієнтовану архітектуру. Що це означає? Ну, Gaphor побудований як набір маленьких острівців (сервісів). Кожен острівець забезпечує певну частину функціональності. Наприклад, ми використовуємо окремі сервіси для завантаження/збереження моделей, забезпечення структури меню та роботи з системою скасування.

Ми визначаємо сервіси як точки входу в pyproject.toml. За допомогою точок входу програми можуть реєструвати функціональність для певних цілей. Ми також групуємо точки входу у групи точок входу. Наприклад, ми використовуємо групу точок входу console_scripts для запуску програми з командного рядка.

Послуги

Gaphor моделюється навколо концепції послуг. Кожну послугу можна зареєструвати в програмі, а потім нею можуть користуватися інші служби або інші об’єкти, що знаходяться в програмі.

Кожна служба повинна реалізовувати інтерфейс служби. Цей інтерфейс визначає один метод:

shutdown(self)

Викликається, коли послугу потрібно очистити.

Ми дозволяємо кожній службі визначати власні методи, якщо послугу також реалізовано.

Послуги мають бути визначені як точки входу у файлі pyproject.toml.

Зазвичай, сервіс виконує певну роботу у фоновому режимі. Сервіси також можуть надавати дії, які можуть бути викликані користувачами. Наприклад, комбінація клавіш Ctrl-z (скасувати) реалізована за допомогою сервісу UndoManager.

Послуга також може залежати від інших служб. Ініціалізація служби усуває ці залежності. Щоб визначити залежність служби, просто додайте її до конструктора за її іменем, визначеним у точці входу:

class MyService(Service):

    def __init__(self, event_manager, element_factory):
        self.event_manager = event_manager
        self.element_factory = element_factory
        event_manager.subscribe(self._element_changed)

    def shutdown(self):
        self.event_manager.unsubscribe(self._element_changed)

    @event_handler(ElementChanged)
    def _element_changed(self, event):

Сервіси, які виставляють дії, також повинні успадковувати інтерфейс ActionProvider. Цей інтерфейс не вимагає реалізації жодних додаткових методів. Методи дій повинні мати анотацію @action.

Приклад: ElementFactory

Гарним прикладом використовуваної служби є ElementFactory. Це одна з основних послуг.

Коли відбувається важлива подія, наприклад, створюється або знищується елемент, ця подія випромінюється. Потім ми використовуємо обробник подій для ElementFactory, який зберігає сигнали додавання/видалення у системі скасування. Іншим прикладом подій, які генеруються, є події для Element`. Ці класи, або, точніше, властивості, надсилають сповіщення щоразу, коли змінюється їхній стан.

Точки входу

Gaphor використовує основну групу :refentry point <https://packaging.python.org/en/latest/specifications/entry-points/> під назвою gaphor.services.

Послуги використовуються для виконання основних функцій програми, одночасно розбиваючи функції на окремі компоненти. Наприклад, фабрика елементів і диспетчер скасування є послугами.

Плагіни також можуть бути створені для розширення функціональності Gaphor за межі основної функціональності в якості надбудови. Наприклад, можна створити плагін для підключення даних моделі до інших додатків. Плагіни також визначаються як сервіси. Наприклад, новий плагін для експорту XMI може бути визначений наступним чином у файлі pyproject.tml:

[tool.poetry.plugins."gaphor.services"]
"xmi_export" = "gaphor.plugins.xmiexport:XMIExport"

Інтерфейси

Кожна служба (і плагін) має реалізовувати інтерфейс gaphor.abc.Service:

class gaphor.abc.Service[source]

Базовий інтерфейс для всіх сервісів Gaphor.

abstractmethod shutdown() None[source]

Вимкнення служб, звільнення ресурсів.

Іншим більш спеціалізованим сервісом, який також успадковується від gaphor.abc.Service, є сервіс UI Component. Служби, які використовують цей інтерфейс, використовуються для визначення вікон та функціональності інтерфейсу користувача. UI-компонент має реалізовувати інтерфейс gaphor.ui.abc.UIComponent:

class gaphor.ui.abc.UIComponent[source]

Компонент інтерфейсу користувача.

abstractmethod close()[source]

Закрийте компонент інтерфейсу користувача.

Компонент може вирішити приховати або знищити компоненти інтерфейсу користувача.

abstractmethod open()[source]

Створення та відображення компонентів інтерфейсу користувача (вікна).

shutdown()[source]

Вимкніть цей компонент.

Його не можна знову відкривати.

Зазвичай, сервіс та компонент інтерфейсу хочуть представити користувачеві деякі дії за допомогою пунктів меню. Кожен сервіс та компонент інтерфейсу може рекламувати дії, реалізувавши інтерфейс gaphor.abc.ActionProvider:

class gaphor.abc.ActionProvider[source]

Постачальник дій — це спеціальна служба, яка забезпечує дії за допомогою декораторів @action для своїх методів (див. gaphor/action.py).