Files
GmRelayBot/docs/adr/002-platform-neutral-batch-rendering.md

3.3 KiB

ADR 002: Platform-Neutral Batch Rendering

Status

Accepted — implemented in v1.10.0 (PR #42).

Context

SessionBatchRenderer жил в GmRelay.Shared и напрямую зависел от Telegram.Bot (InlineKeyboardMarkup, ParseMode.Html). Это создавало проблемы:

  1. Shared не был platform-neutral. Любой платформенный проект (Discord, Slack, WebSocket) тащил Telegram-зависимость.
  2. Дублирование логики. GmRelay.Web использовал тот же рендерер через прямую зависимость от Shared, но Web — это не Telegram-клиент.
  3. Невозможно написать unit-тесты без Telegram-объектов. Smoke-тесты создавали InlineKeyboardMarkup даже для проверки чисто доменной логики.

Decision

Разделить рендеринг на две стадии:

  1. View Builder (platform-neutral) — собирает view model из доменных DTO.
  2. Platform Renderer (platform-specific) — превращает view model в платформенное представление.
Domain DTOs
    │
    ▼
SessionBatchViewBuilder (Shared)
    │
    ▼
SessionBatchViewModel (platform-neutral)
    │
    ├──► TelegramSessionBatchRenderer ──► HTML + InlineKeyboardMarkup
    │
    └──► DiscordSessionBatchRenderer ──► (issue #26)

Изменённые компоненты

Компонент Было Стало
SessionBatchRenderer GmRelay.Shared.Rendering Удалён
SessionBatchViewBuilder GmRelay.Shared.Rendering
SessionBatchViewModel GmRelay.Shared.Rendering
TelegramSessionBatchRenderer GmRelay.Bot + GmRelay.Web
DiscordSessionBatchRenderer GmRelay.Shared.Rendering (stub)
BatchMessageEditor GmRelay.Shared.Rendering GmRelay.Bot + GmRelay.Web

Consequences

Positive

  • GmRelay.Shared больше не зависит от Telegram.Bot. Чистый platform-agnostic проект.
  • Можно добавить DiscordSessionBatchRenderer без изменений в Shared.
  • Unit-тесты ViewBuilder не создают InlineKeyboardMarkup.
  • Логика подсчёта игроков, сортировки сессий и генерации действий — в одном месте (ViewBuilder).

Negative

  • Временное дублирование. TelegramSessionBatchRenderer и BatchMessageEditor скопированы в Bot и Web. Планируется вынести в GmRelay.Shared.Telegram при появлении третьего Telegram-потребителя.
  • Дополнительная стадия. Теперь два вызова вместо одного: Build + Render. Этоtrade-off за чистоту абстракции.
  • Issue #22 — этот рефакторинг.
  • Issue #26 — Discord Bot MVP (потребитель новой архитектуры).
  • ADR 001 — vertical slice, native AOT, Aspire (docs/adr/0001-use-vertical-slice-native-aot-and-aspire.md).