Да, даже при 10–20 sub-стратегиях это тоже нормально — если они разделены по доменам ответственности.
Но есть важный нюанс:
не смешивать все эти стратегии в один «монолитный» интерфейс, а оставить их независимыми.
Много стратегий — это нормально, если они независимы
Пример: ваш сложный объект рассматривается с разных сторон:
Поведение (behavior)
Расписание (scheduler)
Метрики (metrics)
Тунинг (tuner)
Авторизация (auth)
Логирование (logging)
Кэширование (cache)
Retry-политика (retry)
Сериализация (serializer)
Сжатие (compressor)
и т.д.
Если у вас будет:
он станет неудобным:
Много типов параметров.
Конструктор с 10+ аргументами.
Сложность чтения и поддержки.
Поэтому при 10–20 стратегиях лучше не делать один класс с 10+ дженериками, а:
Разбить на несколько компонентов (например,
ProcessingService,SchedulingService,LoggingService).Или использовать композицию через интерфейс — собирать сложный сервис из нескольких небольших сервисов, каждый со своей стратегией.
Но принцип «не смешивать стратегии» остается: каждый аспект — отдельный интерфейс и отдельный набор стратегий.
Не смешивать отдельные стратегии — это правильно
Вы спросили:
Если у меня есть сложный объект, который рассматривается с разных сторон,
то мы все равно не должны смешивать наши отдельные стратегии.
Да, не должны смешивать, и это правильно.
Почему:
Разная ответственность
Scheduler отвечает за расписание, а Bridge не должен знать, как оно работает.
Metrics отвечает за сбор метрик, а Behavior не должен за них заботиться.
Разная динамика изменений
Те, кто меняет логику поведения, не должны дергать код метрик.
Те, кто меняет способ кэширования, не должны менять код scheduler.
Принцип единой ответственности (SRP)
Каждый интерфейс стратегии — одна ответственность.
Смешивание нарушает SRP и усложняет тестирование.Чистая архитектура
В чистой архитекттуре интерфейсы (включая стратегии) должны быть маленькими и специализированными, а зависимости направлены от инфраструктуры к бизнес-логике.
Как практично организовать 10–20 стратегий
Вариант 1: Несколько небольших сервисов
Не один класс с 20 дженериками, а несколько:
Тогда:
Каждый сервис имеет мало стратегий (2–4).
Конструкторы небольшие.
Логика разделена по доменам.
В DI вы регистрируйте их независимо:
Вариант 2: Композитный сервис с «под-сервисами»
Если нужен один «главный» сервис, пусть он собирает другие:
Здесь:
Универсальный
BackgroundServiceне перегружен 20 дженериками.Каждый под-сервис — отдельная стратегия своей области.
Вариант 3: Функциональные стратегии (делегаты)
Для маленьких стратегий (логирование, метрики, retry) можно использовать делегаты:
Тогда:
10–20 стратегий не требуют 10–20 дженериков.
Вы просто ¿подсовываете делегаты.
Это тоже «стратегия + делегирование», просто более легковесная.
Ответ на ваш вопрос
10–20 стратегий — это нормально, если они разделены по доменам и не смешаны в один интерфейс.
Сложный объект, рассматриваемый с разных сторон, не должен иметь одну «монолитную» стратегию, а должен использовать композицию нескольких стратегий.
Подход вида:
— хороший паттерн, но при 10–20 стратегиях лучше:
Разбить на несколько сервисов, или
Использовать делегаты для маленьких стратегий, или
Собрать их через композицию через под-сервисы.
Это сохраняет модульность, тестируемость и читаемость и соответствует принципам чистой архитектуры.
Комментариев нет:
Отправить комментарий