8.8 KiB
ADDED Requirements
Requirement: Сущности ядра DI
Ядро DI MUST определять сущности Scope, Module, Binding, BindingResolver, Disposable, CherryPickObserver и их роли.
Scenario: Декларация базовых сущностей
- WHEN разработчик использует публичный API ядра
- THEN сущности
Scope,Module,Binding,Disposable,CherryPickObserverдоступны и описывают контракт DI
Requirement: Жизненный цикл Scope
Scope MUST поддерживать жизненный цикл открытия, использования и корректного закрытия с освобождением ресурсов.
Scenario: Открытие root scope
- WHEN вызывается открытие root scope
- THEN создается корневой контейнер для регистраций и резолва
Scenario: Открытие named subscope
- WHEN открывается именованный subscope
- THEN subscope наследует bindings родителя и может переопределять зависимости
Scenario: Закрытие subscope
- WHEN вызывается закрытие subscope
- THEN subscope удаляется из дерева, а связанные ресурсы освобождаются
Scenario: Путь scope и разделитель
- WHEN scope открывается по иерархическому пути с разделителем
- THEN создается цепочка subscopes по каждому сегменту пути
Scenario: Пустой scopeName
- WHEN scope открывается с пустым именем
- THEN возвращается root scope
Requirement: Установка и удаление модулей
Scope MUST поддерживать установку и удаление Module, а их bindings MUST становиться доступными сразу после установки.
Scenario: Установка модуля
- WHEN модуль установлен в scope
- THEN его bindings доступны для resolve/tryResolve
Scenario: Сброс модулей
- WHEN модули сброшены
- THEN bindings модулей не доступны для резолва в этом scope
Requirement: Типы bindings
Binding MUST поддерживать прямые инстансы, синхронные провайдеры, асинхронные провайдеры и провайдеры с параметрами, а также именованные bindings.
Scenario: Именованные bindings
- WHEN зарегистрированы два bindings одного типа с разными именами
- THEN resolve с указанным именем возвращает соответствующую реализацию
Scenario: Параметризованный provider
- WHEN binding зарегистрирован с провайдером, принимающим параметры
- THEN resolve с параметрами использует переданные аргументы для создания экземпляра
Requirement: Семантика резолва и fallback
Резолв MUST искать зависимость в текущем scope и, при отсутствии, подниматься к родительским scope.
Scenario: Fallback к родителю
- WHEN зависимость отсутствует в текущем scope, но есть в родительском
- THEN резолв выполняется через родительский binding
Requirement: Синхронный и асинхронный резолв
Scope MUST предоставлять синхронный и асинхронный резолв и их nullable‑варианты.
Scenario: Resolve (sync)
- WHEN вызывается
resolve<T>()для существующей зависимости - THEN возвращается экземпляр или выбрасывается ошибка при отсутствии
Scenario: TryResolve (sync)
- WHEN вызывается
tryResolve<T>()для отсутствующей зависимости - THEN возвращается
nullбез исключения
Scenario: Resolve (async)
- WHEN вызывается
resolveAsync<T>()для зависимости с async‑провайдером - THEN возвращается
Future<T>с экземпляром
Scenario: TryResolve (async)
- WHEN вызывается
tryResolveAsync<T>()для отсутствующей зависимости - THEN возвращается
nullбез исключения
Requirement: Ошибки несоответствия sync/async
Резолв MUST выбрасывать ошибки при несоответствии sync/async режима.
Scenario: ResolveSync для async‑инстанса
- WHEN binding зарегистрирован как async‑инстанс или async‑provider, а вызывается
resolveSync - THEN выбрасывается ошибка с указанием использовать async‑резолв
Requirement: Управление Disposable
Scope MUST отслеживать экземпляры, реализующие Disposable, и вызывать dispose() при закрытии scope.
Scenario: Автоматическое освобождение
- WHEN scope закрывается
- THEN все
Disposableв scope и дочерних scope освобождаются
Requirement: Детекция циклов зависимостей
Ядро DI MUST поддерживать локальную и глобальную детекцию циклов.
Scenario: Локальный цикл
- WHEN локальная детекция включена и резолв обнаруживает цикл
- THEN резолв завершается ошибкой цикла
Scenario: Глобальный цикл
- WHEN глобальная детекция включена и цикл пересекает scope
- THEN резолв завершается ошибкой цикла
Requirement: Наблюдатель событий (Observer)
Ядро DI MUST предоставлять наблюдателя, получающего события регистрации, резолва, ошибок, lifecycle и диагностики.
Scenario: События lifecycle
- WHEN scope открывается, модули устанавливаются и зависимости резолвятся
- THEN observer получает соответствующие уведомления
Requirement: Ошибки и сообщения об ошибках
При критических сбоях резолва ядро MUST выбрасывать ошибку с понятным сообщением, а для tryResolve MUST не бросать исключения.
Scenario: Ошибка отсутствующей зависимости
- WHEN вызывается
resolve<T>()для незарегистрированной зависимости - THEN выбрасывается ошибка с сообщением о невозможности резолва
Scenario: Ошибка цикла
- WHEN обнаружен цикл зависимостей
- THEN выбрасывается ошибка с указанием цепочки
Scenario: Отсутствующие параметры для параметризованного binding
- WHEN binding зарегистрирован с
toProvideWithParams, но резолв вызывается безparams - THEN выбрасывается ошибка о необходимости передать параметры
Requirement: Точки расширения
Ядро DI MUST предоставлять точки расширения через пользовательский Module и CherryPickObserver.
Scenario: Пользовательский Module
- WHEN разработчик создает свой
Module - THEN он может зарегистрировать bindings и контролировать регистрацию
Scenario: Пользовательский Observer
- WHEN разработчик передает кастомный observer
- THEN он получает все DI‑события и может интегрировать внешние логеры/метрики