Visão Geral: Arquitetura de Software Moderna em .NET
Objetivo
Construir sistemas manuteníveis, testáveis e evolutivos, baseados em domínios ricos e isolamento de dependências — conforme Eric Evans, Robert C. Martin, e Martin Fowler.
Estrutura Macro
Inspirada em Clean Architecture e DDD Strategic Design:
┌──────────────────────────────────────────┐
│ Presentation │
│ (API, MVC, Blazor, gRPC, etc.) │
└───────────────▲──────────────────────────┘
│
┌───────────────┴──────────────────────────┐
│ Application Layer │
│ (Use Cases / Application Services) │
└───────────────▲──────────────────────────┘
│
┌───────────────┴──────────────────────────┐
│ Domain Layer │
│ (Entities, Value Objects, Aggregates, │
│ Domain Events, Repositories Interfaces) │
└───────────────▲──────────────────────────┘
│
┌───────────────┴──────────────────────────┐
│ Infrastructure Layer │
│ (ORM, EF Core, Messaging, Persistence, │
│ External Services, IoC, Adapters) │
└──────────────────────────────────────────┘
Camadas e Padrões
Domain Layer (Coração do Sistema)
Evans, Vernon, Millett & Tune, Fowler
O modelo de domínio é o núcleo do software — todas as outras camadas o servem.
Padrões:
- Entity → objeto com identidade (ex:
Order,Customer). - Value Object → sem identidade, definido por seus atributos (ex:
Money,Address). - Aggregate → grupo de entidades e valores com consistência transacional.
- Repository → abstrai persistência.
- Domain Service → lógica que não pertence a uma entidade específica.
- Domain Event → encapsula fatos importantes do domínio.
- Specification Pattern → expressa regras e filtros de domínio.
- Factory → cria objetos complexos de forma controlada.
Boas Práticas (.NET):
- Entidades imutáveis sempre que possível
- Use
recordpara Value Objects (record structé excelente). - Evite dependências de EF Core nesta camada
- Use Event Sourcing e CQRS apenas quando o domínio exigir alta complexidade e rastreabilidade.
Application Layer (Orquestração)
Vernon, Millett, Fowler, Clean Architecture
Aplica o domínio para resolver casos de uso específicos.
Responsabilidades:
- Application Services (orquestram entidades e serviços de domínio)
- Commands e Queries (CQRS)
- Transações e fluxos de trabalho
- Publica Domain Events ou Integration Events
Padrões:
- Command Handler / Query Handler → separação clara de escrita e leitura.
- Mediator Pattern (ex: MediatR)
- DTOs / Input Models
- Unit of Work (via EF Core
DbContext)
Infrastructure Layer
Fowler, Clean Architecture, Implementing DDD
Depende das outras camadas, nunca o contrário.
Padrões:
- Repository Implementation → persistência real (EF Core, Dapper, Mongo, etc.).
- Adapter / Bridge → integrações externas (HTTP, mensageria, etc.).
- Factory / Abstract Factory → criação de serviços ou clientes externos.
- Decorator / Proxy → logging, cache, retry.
- Event Bus / Outbox Pattern → para integração assíncrona.
Práticas .NET:
- Interfaces no domínio, implementações aqui
- Não expor
DbContext - Usar Dependency Injection
- Unit of Work centralizado
Presentation Layer
The Pragmatic Programmer, Clean Code
A camada mais volátil deve ser a mais fina.
Exemplos:
- ASP.NET Core API → Controllers chamam Application Services.
- Blazor / MVC → somente UI.
- gRPC → para comunicações de alta performance.
Práticas:
- Validação de input models
- Transforme View Models em DTOs.
- Evitar lógica de negócio
- Padronizar error handling e logging
Padrões de Arquitetura
| Tipo | Padrões | Origem |
|---|---|---|
| Estrutural | Layered, Hexagonal, Onion | Fowler / Clean Architecture |
| Criação | Factory, Builder, Singleton | GoF |
| Comportamental | Command, Strategy, Observer, Mediator | GoF |
| Tático DDD | Entity, Value Object, Repository, Aggregate, Domain Event | Evans / Vernon |
| Estratégico DDD | Bounded Context, Context Map, ACL, Shared Kernel | Evans / Millett |
| Integração | CQRS, Event Sourcing, Outbox, Saga | Vernon / Millett |
Práticas de Código Limpo
Clean Code + Refactoring + The Clean Coder
- Métodos pequenos, expressivos e sem efeitos colaterais
- Nomeie pelo propósito (Intention-Revealing Names)
- Aplique SRP (Single Responsibility Principle) e OCP (Open-Closed Principle).
- Refatore continuamente — “o código deve contar uma história”.
- Escreva testes primeiro (TDD)
- Alta cobertura de testes de unidade no domínio
- Boy Scout Rule: deixe o código melhor do que encontrou
Guia de Decisão (Resumo)
| Decisão | Diretriz |
|---|---|
| Separar responsabilidades | Use camadas Domain, Application, Infra, Presentation |
| Dependências | Sempre apontam para dentro (Clean Architecture) |
| Domínio complexo | Aplique DDD tático e estratégico |
| Persistência | Repositories + UoW + Mapeamento via EF Core |
| Comunicação entre contextos | Messaging (Event Bus) ou HTTP (REST/gRPC) |
| Validação | No domínio (regras) e na apresentação (input) |
| Arquitetura evolutiva | Refatorar com testes automatizados (Fowler) |
| Cultura e profissionalismo | Responsabilidade, respeito ao tempo e qualidade (The Clean Coder) |
Exemplo de organização de Solução .NET
src/
├── CompanyName.Project.Api → Presentation Layer
├── CompanyName.Project.Application → Application Layer
├── CompanyName.Project.Domain → Domain Layer
├── CompanyName.Project.Infrastructure → Infrastructure Layer
└── CompanyName.Project.Tests → Unit & Integration Tests
Conclusão
"A boa arquitetura maximiza as decisões que você pode adiar." — Robert C. Martin
Essa síntese cria uma base sustentável, onde cada camada tem uma função clara e o domínio permanece protegido, expressivo e evolutivo.