# ADR-001 — Modular Monolith com MediatR (CQRS Leve) **Status:** Aprovado **Data:** 2026-05-29 **Autores:** Equipe Donc --- ## Contexto A solução Donc possui 4 implementações independentes de criação de OS, lógica de parceiro duplicada em 3 projetos, e `Go4YouEntities` (EF6) como ponto único de falha referenciado por 6 projetos. Qualquer mudança em uma entidade core pode quebrar toda a solution simultaneamente. O plano de modernização (`visao-geral.md`) define uma progressão em 6 etapas, da situação atual até Clean Architecture completa. A Etapa 4 exige definir o padrão de código que as novas funcionalidades devem seguir antes que a refatoração comece. **Problema:** Novas funcionalidades ainda estão sendo criadas no modelo antigo (lógica duplicada em controllers, acesso direto ao banco, sem validação centralizada). Precisamos de um padrão imediatamente aplicável que: 1. Seja adotável hoje, sem precisar criar novos projetos .csproj 2. Seja compatível com a Clean Architecture alvo 3. Permita à IA criar e modificar features de forma isolada e segura 4. Não exija reescrita de tudo de uma vez --- ## Decisão Adotar **Modular Monolith com MediatR (CQRS Leve)** como padrão para todas as funcionalidades novas. **O que isso significa na prática:** - Cada funcionalidade nova é um **Command** (escrita) ou **Query** (leitura) com seu **Handler** isolado - Validação declarativa com **FluentValidation** no Validator do Command - Controllers são **cascas finas**: recebem request, chamam `_mediator.Send()`, retornam response - Nenhum handler acessa banco diretamente: usa repositório por **interface** - O tenant (`ContratoSaasId`) é resolvido uma vez por requisição via **`IContextoTenant`** — nunca propagado como parâmetro manual entre classes - Módulos comunicam-se apenas por **interfaces públicas** ou **eventos de domínio** (`INotification`), nunca por acesso direto a tabelas do outro **Módulos definidos:** | Módulo | Bounded Context | |--------|----------------| | `OrdemServico` | Criação, ciclo de vida, checklist, produtos, filas | | `Profissional` | Profissionais, parceiros, cobertura geográfica | | `Agendamento` | Janelas, reservas, reagendamento | | `Roteirizacao` | Distribuição, rotas, DoncRouter | | `Financeiro` | Fechamento, comissões, relatórios | | `Integracoes` | ERPs externos, webhooks, fila de importação | | `Notificacao` | Push, e-mail, webhooks de saída | | `Tenancy` | ContratoSaas, isolamento, usuários | --- ## Alternativas Consideradas ### A: Continuar no modelo atual (controller com lógica) - **Vantagem:** sem custo de mudança imediato - **Problema:** cada bug novo cria 3-4 correções paralelas; a IA não sabe onde colocar código novo; impossível testar unitariamente ### B: Clean Architecture completa imediata (Donc.Domain + Donc.Application + Donc.Infrastructure) - **Vantagem:** arquitetura ideal desde o início - **Problema:** exige criar projetos, reorganizar solution, configurar DI de zero — 2-3 meses antes da primeira funcionalidade entrar no novo formato; `Go4YouEntities` precisa ser substituído antes ### C: Modular Monolith com MediatR (escolhida) - **Vantagem:** adotável hoje dentro dos projetos existentes; compatível com Clean Architecture alvo; cada feature é isolada e testável; a IA sabe exatamente onde criar coisas novas - **Desvantagem:** não elimina o `Go4YouEntities` no curto prazo — os handlers ainda podem usar EF6 durante a transição --- ## Consequências **Positivas:** - Novas features entram em arquivos isolados — zero risco de quebrar outras features - A IA cria um Command+Handler+Validator sem precisar entender todo o controller - Testes unitários triviais: 1 handler = 1 teste - Preparação natural para a Etapa 4 (Donc.Application já terá a estrutura de Commands/Queries) - O mesmo padrão funciona em ApiV2 (.NET 4.8 com MediatR 9.x) e DoncMobile.API (.NET 8+) **Negativas / Riscos:** - `Go4YouEntities` continua sendo o único DbContext até a Etapa 6 — o risco de ponto único de falha persiste durante a transição - `StatusCalculadoId` (hardcoded em múltiplos projetos) precisa ser centralizado antes de migrar o módulo OS completo - Time precisa aprender o padrão Command/Handler — curva de ~1 sprint **Regras inegociáveis:** 1. Toda funcionalidade nova segue este padrão — sem exceção 2. Nenhum handler recebe `ContratoSaasId` como parâmetro — sempre via `IContextoTenant` 3. Nenhum módulo acessa tabela de outro módulo diretamente 4. Nomes sempre em português (ver `CLAUDE.md` — Convenções de Código) --- ## Referências - [modulos.md](modulos.md) — Bounded contexts e contratos públicos de cada módulo - [nova-funcionalidade.md](nova-funcionalidade.md) — Guia prático com exemplos de código - [visao-geral.md](visao-geral.md) — Plano de modernização completo (Etapas 1-6) - [../../CLAUDE.md](../../CLAUDE.md) — Convenções de código obrigatórias