3.3 KiB
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). Это создавало проблемы:
- Shared не был platform-neutral. Любой платформенный проект (Discord, Slack, WebSocket) тащил Telegram-зависимость.
- Дублирование логики.
GmRelay.Webиспользовал тот же рендерер через прямую зависимость отShared, но Web — это не Telegram-клиент. - Невозможно написать unit-тесты без Telegram-объектов. Smoke-тесты создавали InlineKeyboardMarkup даже для проверки чисто доменной логики.
Decision
Разделить рендеринг на две стадии:
- View Builder (platform-neutral) — собирает view model из доменных DTO.
- 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 за чистоту абстракции.
Related
- 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).