# DoncMobile API -- Guia de Arquitetura **Versao:** v3.2.0 -- 2025 **Stack:** .NET 8, C#, Dapper **Arquitetura:** Controller -> Service -> Repository **Idioma do codigo:** Portugues (BR) ## 01 -- Arquitetura em camadas O codigo e dividido em tres camadas com responsabilidades claras e bem separadas. Cada camada conhece apenas a camada imediatamente abaixo dela. O Controller nao sabe que existe SQL. O Service nao sabe que existe Dapper. O Repository nao sabe que existe HTTP. - **Controller** -- Recebe a requisicao HTTP, chama o servico, devolve o response. Nada mais. (HTTP only) - **Service** -- Contem toda a logica de negocio: validacoes, calculos, orquestracao de chamadas. (Regras de negocio) - **Repository** -- Executa SQL e mapeia o resultado para tipos de dominio. Zero logica de negocio. (SQL + mapeamento) - **Infrastructure** -- Fabrica de conexoes, clientes HTTP nomeados, configuracoes de infraestrutura. (Infra tecnica) ## 02 -- Estrutura de pastas ``` DoncMobile.API/ ├── Controllers/ -- apenas HTTP, sem SQL, sem logica ├── Services/ │ ├── Interfaces/ -- IServicoSincronizacao.cs │ └── ServicoSincronizacao.cs ├── Repositories/ │ ├── Interfaces/ -- IRepositorioSincronizacao.cs (sem Dapper na interface) │ └── Dapper/ -- implementacao concreta com Dapper │ └── RepositorioSincronizacao.cs ├── Infrastructure/ -- IFabricaConexao, FabricaConexaoSqlServer ├── Middleware/ -- TratadorGlobalExcecoes ├── Exceptions/ -- ExcecaoSincronizacao e demais ├── Constants/ -- ConstantesSincronizacao (sem magic numbers no codigo) └── Models/ ├── DTOs/ -- request e response (nao altere campos -- app consome) └── QueryResults/ -- tipos internos de mapeamento do Dapper ``` > **ALERTA:** Pastas em ingles, codigo em portugues. As pastas seguem convencao tecnica do .NET pois viram namespaces. O codigo dentro delas e 100% em portugues. ## 03 -- Criando um endpoint novo **Passo 1:** Defina o DTO de request e response em Models/DTOs/. Nomes em portugues. **Passo 2:** Crie a interface do repositorio em Repositories/Interfaces/. Zero mencao a Dapper, SqlConnection ou dynamic. **Passo 3:** Implemente o repositorio com Dapper em Repositories/Dapper/. Cada metodo abre e fecha sua propria conexao. **Passo 4:** Crie o servico com a logica de negocio em Services/. Toda regra, validacao e calculo fica aqui. Use ExcecaoSincronizacao para erros de dominio. **Passo 5:** Crie o endpoint no controller. O controller deve ter no maximo ~10 linhas por action. Sem try/catch, sem SQL, sem logica. **Passo 6:** Registre no Program.cs com comentario mostrando como trocar implementacao. ## 04 -- O que fazer e o que nao fazer **Proibido:** - new SqlConnection() no controller ou service - new HttpClient() em qualquer lugar -- use IHttpClientFactory - dynamic fora do Repository - SQL fora do Repository - try/catch no controller sem motivo especifico - Logica de negocio no controller - Logica de negocio no repository - IConfiguration injetado no controller - Expor ex.Message na resposta HTTP - Magic numbers no codigo (use Constants) - Codigo comentado com // -- use git - Interpolacao $"" nos logs - Emojis nas mensagens de log - Nomes em ingles no codigo novo **Correto:** - Controller injeta apenas o Service e ILogger - Service injeta Repository, IHttpClientFactory e ILogger - Repository injeta apenas IFabricaConexao e ILogger - Cada metodo do Repository abre sua propria conexao - CancellationToken propagado ate o Dapper - Tipos fortemente tipados em todos os retornos - ExcecaoSincronizacao para erros de dominio - Constantes nomeadas para todos os valores fixos - Logs com template {NomeParametro} - partial class quando arquivo ficar grande - Um arquivo de interface + um de implementacao por entidade - Metodos com no maximo 40 linhas - Comentarios explicando o porquê, nunca o o que - Todo codigo em portugues ## 05 -- Tratamento de excecoes O TratadorGlobalExcecoes intercepta toda excecao nao tratada e devolve um response padronizado. | Situacao | O que fazer no codigo | Status HTTP | CodigoErro | |----------|-----------------------|-------------|------------| | Regra de negocio violada | Lancar ExcecaoSincronizacao no Service | 422 | Definido por voce | | Timeout no banco | Nao precisa fazer nada | 504 | TIMEOUT_BANCO | | Banco indisponivel | Nao precisa fazer nada | 503 | BANCO_INDISPONIVEL | | Servico externo falhou | Adicionar HttpRequestException no middleware | 502 | SERVICO_EXTERNO_ERRO | | Cliente cancelou requisicao | Nao precisa fazer nada | 499 | REQUISICAO_CANCELADA | | Erro inesperado | Nao precisa fazer nada | 500 | ERRO_INTERNO | **Quando try/catch ainda e valido:** (1) quando voce precisa executar uma acao antes de relancar a excecao; (2) quando a excecao faz parte do fluxo normal e voce quer converte-la para ExcecaoSincronizacao. Sempre termine com throw. ## 06 -- Convencoes de nomenclatura | Elemento | Convencao | Exemplo | |----------|-----------|---------| | Classes | PascalCase em portugues | ServicoSincronizacao | | Interfaces | I + PascalCase em portugues | IRepositorioAutenticacao | | Metodos publicos | PascalCase + verbo de acao claro | BuscarRotas(), MontarResposta() | | Variaveis locais | camelCase em portugues | diasRetroativos, pedidosIds | | Parametros | camelCase em portugues | tokenCancelamento, requisicao | | Campos privados | _camelCase em portugues | _repositorio, _fabrica | | Constantes | PascalCase em classe estatica | StatusPedido.Aceito | | Booleanos | Prefixo descritivo | ehValido, possuiDataInicio | | Colecoes | Nome no plural | pedidosIds, tiposProblema | | Dicionarios | Descreve o mapeamento | statusPorPedido, clientesPorId | ## 07 -- Convencao de idioma Todo o codigo de dominio e escrito em portugues. Sem excecoes. A unica excecao sao palavras que fazem parte da linguagem C# e do framework .NET -- string, Task, List, Controller, async, await, ILogger. | ERRADO | CORRETO | |--------|---------| | GetRoutes() | BuscarRotas() | | var result | var resultado | | bool isValid | bool ehValido | | int count | int quantidade | | var config | var configuracao | | BuildResponse() | MontarResposta() | | // Get data from db | // Busca dados do banco | | List\ items | List\ itens | > **ALERTA:** Nao "corrija" portugues para ingles. Se voce encontrar codigo existente escrito em portugues e alterar para ingles, isso e uma violacao. ## 08 -- Logs estruturados Usamos structured logging com templates nomeados. O nome do parametro entre {} e indexado por ferramentas como Seq e Application Insights. **Errado:** - Interpolacao perde o valor indexado: `$"Iniciado para Profissional {profissionalId}"` - Emojis quebram filtros e alertas - Dados sensiveis: nunca logue senha, token ou CPF - ex.Message no log de Info **Correto:** - Template nomeado indexavel: `"Iniciado. ProfissionalId={ProfissionalId}"` - Mensagem em portugues, sem emoji, sem interpolacao - `LogError(ex, "Mensagem. Param={P}", valor)` -- excecao como primeiro argumento - Nivel correto: Debug = detalhe, Info = fluxo, Warning = inesperado nao critico, Error = falha ## 09 -- Checklist antes do PR 1. dotnet build sem erros e sem warnings novos 2. Controller tem menos de 80 linhas -- sem SQL, sem try/catch, sem IConfiguration 3. Repository nao tem logica de negocio -- apenas SQL e mapeamento para tipos fortemente tipados 4. Interface do Repository nao menciona SqlConnection, IDbConnection nem dynamic 5. CancellationToken propagado ate o Dapper em todas as queries 6. Nenhum new HttpClient() -- IHttpClientFactory registrado e utilizado 7. Servicos registrados no Program.cs com comentario mostrando como trocar implementacao 8. Rotas HTTP e campos JSON identicos ao contrato anterior -- zero breaking changes 9. Todo codigo novo em portugues -- classes, metodos, variaveis, comentarios 10. Sem codigo comentado com // -- delete ou commite 11. Logs com template estruturado {NomeParametro} -- sem interpolacao $"" e sem emojis 12. Nenhum metodo com mais de 40 linhas 13. Magic numbers substituidos por constantes