понедельник, 13 июля 2026 г.

Strategy, Strategies, Pattern, Comet, StrategyPattern, TemplateMethodPattern

Strategy, Strategies, Pattern, Comet, StrategyPattern, TemplateMethodPattern

https://www.perplexity.ai/search/db6e2fc1-20a3-411a-823f-379f4d79ea73

Много стратегий — это нормально, если они независимы

Пример: ваш сложный объект рассматривается с разных сторон:

·         Поведение (behavior)

·         Расписание (scheduler)

·         Метрики (metrics)

·         Тунинг (tuner)

·         Авторизация (auth)

·         Логирование (logging)

·         Кэширование (cache)

·         Retry-политика (retry)

·         Сериализация (serializer)

·         Сжатие (compressor)

·         и т.д.

Если у вас будет:

public class BackgroundService<
    TBehavior, TScheduler, TMetrics, TTuner,
    TAuth, TLogging, TCache, TRetry, TSer, TCompress>
    : BackgroundService
    where TBehavior : IBehaviorStrategy
    where TScheduler : ISchedulerStrategy
    where TMetrics : IMetricsStrategy
    where TTuner : ITunerStrategy
    where TAuth : IAuthStrategy
    where TLogging : ILoggingStrategy
    where TCache : ICacheStrategy
    where TRetry : IRetryStrategy
    where TSer : ISerializerStrategy
    where TCompress : ICompressorStrategy
{ ... }

он станет неудобным:

·         Много типов параметров.

·         Конструктор с 10+ аргументами.

·         Сложность чтения и поддержки.

Поэтому при 10–20 стратегиях лучше не делать один класс с 10+ дженериками, а:

1.       Разбить на несколько компонентов (например, ProcessingService, SchedulingService, LoggingService).

2.      Или использовать композицию через интерфейс — собирать сложный сервис из нескольких небольших сервисов, каждый со своей стратегией.

Но принцип «не смешивать стратегии» остается: каждый аспект — отдельный интерфейс и отдельный набор стратегий.

Не смешивать отдельные стратегии — это правильно

Вы спросили:

Если у меня есть сложный объект, который рассматривается с разных сторон,
то мы все равно не должны смешивать наши отдельные стратегии.

Да, не должны смешивать, и это правильно.

Почему:

1.       Разная ответственность

o    Scheduler отвечает за расписание, а Bridge не должен знать, как оно работает.

o    Metrics отвечает за сбор метрик, а Behavior не должен за них заботиться.

2.      Разная динамика изменений

o    Те, кто меняет логику поведения, не должны дергать код метрик.

o    Те, кто меняет способ кэширования, не должны менять код scheduler.

3.      Принцип единой ответственности (SRP)
Каждый интерфейс стратегии — одна ответственность.
Смешивание нарушает SRP и усложняет тестирование.

4.      Чистая архитектура
В чистой архитекттуре интерфейсы (включая стратегии) должны быть маленькими и специализированными, а зависимости направлены от инфраструктуры к бизнес-логике.
[41]

Как практично организовать 10–20 стратегий

Вариант 1: Несколько небольших сервисов

Не один класс с 20 дженериками, а несколько:

public class ProcessingService<TBehavior, TAuth, TRetry>
    : IHostedService
    where TBehavior : IBehaviorStrategy
    where TAuth : IAuthStrategy
    where TRetry : IRetryStrategy
{ ... }

public class SchedulingService<TScheduler>
    : IHostedService
    where TScheduler : ISchedulerStrategy
{ ... }

public class LoggingService<TLogging>
    : IHostedService
    where TLogging : ILoggingStrategy
{ ... }

public class MetricsService<TMetrics>
    : IHostedService
    where TMetrics : IMetricsStrategy
{ ... }

Тогда:

·         Каждый сервис имеет мало стратегий (2–4).

·         Конструкторы небольшие.

·         Логика разделена по доменам.

В DI вы регистрируйте их независимо:

services.AddHostedService<ProcessingService<MyBehavior, JwtAuth, DefaultRetry>>();
services.AddHostedService<SchedulingService<IntervalScheduler>>();
services.AddHostedService<LoggingService<FileLogger>>();

Вариант 2: Композитный сервис с «под-сервисами»

Если нужен один «главный» сервис, пусть он собирает другие:

public class MasterBackgroundService : BackgroundService
{
    private readonly ProcessingService _processingService;
    private readonly SchedulingService _schedulingService;
    private readonly MetricsPoller _metricsPoller;

    public MasterBackgroundService(
        ProcessingService processingService,
        SchedulingService schedulingService,
        MetricsPoller metricsPoller)
    {
        _processingService = processingService;
        _schedulingService = schedulingService;
        _metricsPoller = metricsPoller;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        //
запускаем под-сервисы
        await Task.WhenAll(
            _processingService.StartAsync(stoppingToken),
            _schedulingService.StartAsync(stoppingToken),
            _metricsPoller.StartAsync(stoppingToken));
    }
}

Здесь:

·         Универсальный BackgroundService не перегружен 20 дженериками.

·         Каждый под-сервис — отдельная стратегия своей области.

Вариант 3: Функциональные стратегии (делегаты)

Для маленьких стратегий (логирование, метрики, retry) можно использовать делегаты:

public class ProcessingService
{
    private readonly Func<Task> _behavior;
    private readonly Action<string> _log;
    private readonly Action<string, double> _metric;

    public ProcessingService(
        Func<Task> behavior,
        Action<string> log,
        Action<string, double> metric)
    {
        _behavior = behavior;
        _log = log;
        _metric = metric;
    }
}

Тогда:

·         10–20 стратегий не требуют 10–20 дженериков.

·         Вы просто ¿подсовываете делегаты.

Это тоже «стратегия + делегирование», просто более легковесная.

Ответ на ваш вопрос

·         10–20 стратегий — это нормально, если они разделены по доменам и не смешаны в один интерфейс.

·         Сложный объект, рассматриваемый с разных сторон, не должен иметь одну «монолитную» стратегию, а должен использовать композицию нескольких стратегий.

·         Подход вида:

BackgroundService<TBehavior, TScheduler, TMetrics, TTuner>

— хороший паттерн, но при 10–20 стратегиях лучше:

o    Разбить на несколько сервисов, или

o    Использовать делегаты для маленьких стратегий, или

o    Собрать их через композицию через под-сервисы.

Это сохраняет модульность, тестируемость и читаемость и соответствует принципам чистой архитектуры.[41]

четверг, 8 января 2026 г.

Unicode, Emodzi, Giga

Unicode, Emodzi

https://giga.chat/link/gcsGVWGvHw

Вот таблица с самыми распространёнными эмодзи и их эквивалентными кодами Юникода для использования в C#, JavaScript и других языках программирования. Эти коды можно применять для вывода специальных символов и пиктограмм.

ЭмодзиНазваниеЮникод-код
😊улыбающийся смайликU+1F604
🤩лицо с широко открытыми глазамиU+1F929
🚀ракетаU+1F680
📈восходящий графикU+1F4C8
📊диаграммаU+1F4CA
🔥огоньU+1F525
💰монетыU+1F4B0
🏆трофейU+1F3C6
🎖️лента наградU+1F3C5
🦾рукопожатиеU+1F91D
🍰пирожноеU+1F370
🍕пиццаU+1F355
🌶️перец чилиU+1F336
🧘‍♂️мужчина йогаU+1F9D8
🙃смущённый смайликU+1F605
🇷🇺флаг РоссииU+1F1F7,U+1F1FA
🫣синий кругU+1F7E6
🟥красный квадратU+1F7E5
🟦зелёный треугольникU+1F7EA
🛑стопU+1F6D1
🔔колокольчикU+1F514
🌀воронкаU+1F5DC
🖼️фотографияU+1F5BC
📸камераU+1F4F7
📱мобильный телефонU+1F4F1
👻призракU+1F47B
🕵️детективU+1F575
🐳китU+1F433
🐟рыбаU+1F41F
🚗автомобильU+1F697
🚐поездU+1F683
🚓полицейская машинаU+1F693
🚔автобусU+1F68C
🏃‍♂️бегущий мужчинаU+1F3C3
💃танцующая женщинаU+1F483
🎲игральные костиU+1F3B2
🎮контроллер игрыU+1F3AE
🍿попкорнU+1F37F
🌎ЗемляU+1F30D
🌜️ЛунаU+1F314
🌽кукурузаU+1F33D
🍕пиццаU+1F355
🍌бананU+1F34C
🍎яблокоU+1F34E
🍋лимонU+1F34B
🍊апельсинU+1F34A
🍐тыкваU+1F347
🍍ананасU+1F34D
🍎красное яблокоU+1F34E
🍑персикU+1F351
🍒зеленое яблокоU+1F34F
🍓клубникаU+1F353
🍔бургерU+1F354
🍕пиццаU+1F355
🍦мороженоеU+1F366
🍧пудингU+1F36E
🍩пончикиU+1F369
🍳спагеттиU+1F35D
🍫шоколадU+1F370
🍭леденцыU+1F36D
🍷бокал винаU+1F377
🍹стакан сокаU+1F37E
🍸коктейльU+1F379
🍵чайU+1F375
🍾бутылка шампанскогоU+1F37E