Компоненты: абстрактные классы¶
Эта страница описывает роль и устройство абстрактных классов в архитектуре QTasks. Абстрактные классы формируют контракты компонентов и являются ключевым механизмом согласованности всей системы.
В QTasks абстрактные классы — это не вспомогательный элемент, а основа архитектуры: именно они определяют допустимое поведение компонентов, их интерфейсы и точки расширения.
Роль абстрактных классов¶
Каждый основной и дополнительный компонент QTasks обязан наследоваться от соответствующего абстрактного класса. Эти классы:
- задают контракт взаимодействия компонента с системой;
- фиксируют обязательные методы и их сигнатуры;
- определяют модель синхронного и асинхронного выполнения;
- служат единым источником документации и типизации.
Если компонент не реализует обязательный метод, объявленный через @abstractmethod,
его создание приводит к ошибке на уровне Python, ещё до запуска системы.
Базовое именование¶
Все абстрактные классы компонентов следуют единому шаблону именования:
Base<Component>— абстрактный класс;(A)sync<СпособРаботы><Component>— конкретная реализация.
Пример:
BaseStorage— контракт компонента хранения;AsyncRedisStorage— асинхронная реализация хранилища на базе Redis.
Такое именование делает архитектуру самодокументируемой и позволяет сразу определить роль и модель выполнения компонента.
Разделение на Async и Sync¶
Абстрактные классы используют параметризацию через Generic[TAsyncFlag] для строгого
разделения синхронных и асинхронных компонентов.
TAsyncFlag = True— асинхронный компонент;TAsyncFlag = False— синхронный компонент.
Это разделение отражается в типах методов через @overload, например:
self: BaseBroker[Literal[True]]— асинхронный контекст;self: BaseBroker[Literal[False]]— синхронный контекст.
Архитектурное правило:
- асинхронные компоненты могут работать с синхронными функциями;
- синхронные компоненты не допускают вызова асинхронных функций.
Это ограничение намеренно жёсткое и предотвращает неявные ошибки исполнения.
Конструктор компонента¶
Каждый абстрактный класс определяет собственный __init__, через который проходит
инициализация компонента.
Через конструктор:
- передаются обязательные зависимости;
- задаются параметры конфигурации;
- фиксируются инварианты компонента.
Набор параметров различается между базовыми классами, но сама идея централизованной инициализации является общей для всех компонентов.
Обязательные методы и поведение по умолчанию¶
Абстрактные классы в QTasks могут содержать:
- методы, помеченные
@abstractmethod, которые обязаны быть реализованы; - методы с реализацией по умолчанию;
- вспомогательные методы, используемые внутри компонента.
Таким образом, контракт включает не только сигнатуры, но и базовое поведение, которое считается корректным для данного типа компонента.
Документация и типизация¶
Каждый метод в абстрактных классах сопровождается документацией в формате Google docstring.
Это обеспечивает:
- единый стиль документации во всём QTasks;
- синхронизацию архитектурного описания и кода;
- корректную работу IDE, статического анализа и автодополнения.
Абстрактный класс является каноническим источником информации о том, как компонент должен себя вести.
Абстрактные классы плагинов¶
Та же архитектурная модель применяется и к плагинам.
- базовый класс плагинов:
BasePlugin; - конкретные реализации следуют тому же шаблону
(A)sync<СпособРаботы>Plugin.
Пример:
BasePlugin;AsyncPydanticWrapperPlugin.
Это обеспечивает единообразие между компонентами и плагинами и упрощает их совместное использование.
Архитектурные инварианты¶
- любой компонент обязан наследоваться от
Base<Component>; - несоблюдение контракта приводит к ошибке на этапе создания класса;
- разделение Async/Sync фиксируется на уровне типов;
- документация и типизация являются частью контракта.
Эти правила делают архитектуру QTasks строгой, предсказуемой и расширяемой без скрытых соглашений.