8319edda38
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.6 KiB
3.6 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 ──► Discord embeds + buttons
Изменённые компоненты
| Компонент | Было | Стало |
|---|---|---|
SessionBatchRenderer |
GmRelay.Shared.Rendering |
Удалён |
SessionBatchViewBuilder |
— | GmRelay.Shared.Rendering |
SessionBatchViewModel |
— | GmRelay.Shared.Rendering |
TelegramSessionBatchRenderer |
— | GmRelay.Bot + GmRelay.Web |
DiscordSessionBatchRenderer |
— | GmRelay.DiscordBot.Rendering |
BatchMessageEditor |
GmRelay.Shared.Rendering |
GmRelay.Bot + GmRelay.Web |
Consequences
Positive
GmRelay.Sharedбольше не зависит отTelegram.Bot. Чистый platform-agnostic проект.- Discord renderer lives in
GmRelay.DiscordBot, so NetCord stays out ofShared. - 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 (потребитель новой архитектуры).
- Issue #30 — Discord reschedule voting использует
IPlatformMessenger. - Issue #31 — scheduler notifications и reschedule deadline updates через
IPlatformMessenger. - Issue #32 — compose wiring для Discord bot (healthcheck :8082).
- Issue #33 — регрессионные тесты platform rendering (Telegram + Discord).
- ADR 001 — vertical slice, native AOT, Aspire (
docs/adr/0001-use-vertical-slice-native-aot-and-aspire.md).