DEV Community

Domain-Driven Design com .NET

Domain-Driven Design (DDD) é uma abordagem arquitetural que coloca o foco no núcleo do negócio. Ela propõe modelar o software com base em regras de negócio reais, usando uma linguagem comum entre devs e especialistas. Em sistemas .NET, essa abordagem é perfeitamente compatível com padrões como Clean Architecture, CQRS, e o uso de ferramentas modernas como Entity Framework, MediatR e ASP.NET Core.


🧠 Princípios-Chave do DDD

Conceito Definição
Domínio Área central do problema que o sistema resolve
Modelo de Domínio Representação do conhecimento do domínio em código
Entidade Objeto com identidade única (ex: Cliente, Pedido)
Value Object Objeto imutável sem identidade, definido por seus valores (ex: CPF)
Aggregate Conjunto de entidades e VOs com regras de consistência
Root Aggregate Entidade raiz que gerencia o agregado
Repository Interface para persistência de agregados
Bounded Context Fronteira lógica onde o modelo é consistente
Linguagem Ubíqua Vocabulário comum entre devs e especialistas

🏗️ Estrutura de Projeto Sugerida

src/
├── Domain/
├── Application/
├── Infrastructure/
└── WebAPI/
Enter fullscreen mode Exit fullscreen mode

🔧 Exemplo Prático: Sistema de Pedidos

Entidade Pedido

public class Pedido
{
    public Guid Id { get; private set; }
    public DateTime CriadoEm { get; private set; }
    private readonly List<ItemPedido> _itens;
    public IReadOnlyCollection<ItemPedido> Itens => _itens;

    public Pedido()
    {
        Id = Guid.NewGuid();
        CriadoEm = DateTime.UtcNow;
        _itens = new List<ItemPedido>();
    }

    public void AdicionarItem(string produto, decimal preco, int quantidade)
    {
        if (string.IsNullOrWhiteSpace(produto)) throw new DomainException("Produto inválido.");
        _itens.Add(new ItemPedido(produto, preco, quantidade));
    }

    public decimal ObterTotal() => _itens.Sum(i => i.Total());
}
Enter fullscreen mode Exit fullscreen mode

Value Object: ItemPedido

public class ItemPedido
{
    public string Produto { get; }
    public decimal PrecoUnitario { get; }
    public int Quantidade { get; }

    public ItemPedido(string produto, decimal preco, int quantidade)
    {
        Produto = produto;
        PrecoUnitario = preco;
        Quantidade = quantidade;
    }

    public decimal Total() => PrecoUnitario * Quantidade;
}
Enter fullscreen mode Exit fullscreen mode

🔌 Repositório + EF Core

public interface IPedidoRepository
{
    Task<Pedido> ObterPorIdAsync(Guid id);
    Task AdicionarAsync(Pedido pedido);
}
Enter fullscreen mode Exit fullscreen mode
public class PedidoRepository : IPedidoRepository
{
    private readonly DbContext _context;

    public PedidoRepository(DbContext context) => _context = context;

    public async Task<Pedido> ObterPorIdAsync(Guid id) =>
        await _context.Set<Pedido>().FindAsync(id);

    public async Task AdicionarAsync(Pedido pedido)
    {
        await _context.Set<Pedido>().AddAsync(pedido);
        await _context.SaveChangesAsync();
    }
}
Enter fullscreen mode Exit fullscreen mode

🚀 Aplicando CQRS com MediatR

Comando

public record CriarPedidoCommand(List<ItemDTO> Itens) : IRequest<Guid>;
Enter fullscreen mode Exit fullscreen mode

Handler

public class CriarPedidoHandler : IRequestHandler<CriarPedidoCommand, Guid>
{
    private readonly IPedidoRepository _pedidoRepository;

    public CriarPedidoHandler(IPedidoRepository repo) => _pedidoRepository = repo;

    public async Task<Guid> Handle(CriarPedidoCommand request, CancellationToken cancellationToken)
    {
        var pedido = new Pedido();
        foreach (var item in request.Itens)
            pedido.AdicionarItem(item.Produto, item.Preco, item.Quantidade);

        await _pedidoRepository.AdicionarAsync(pedido);
        return pedido.Id;
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ Boas Práticas

  • Modele a linguagem do negócio antes de começar a codar.
  • Use DDD somente onde há complexidade de domínio.
  • Mantenha regras dentro das entidades, evitando serviços anêmicos.
  • Evite acoplamentos entre Bounded Contexts diretamente.
  • Utilize testes unitários focando no comportamento do domínio.

📦 Ferramentas Úteis no Ecossistema .NET + DDD

Ferramenta Finalidade
Entity Framework Core ORM e persistência
MediatR Implementação de CQRS
AutoMapper Conversão entre modelos e DTOs
FluentValidation Validação de entrada
Serilog Logging estruturado
Swashbuckle/Swagger Documentação automática da API

📘 Conclusão

DDD é uma abordagem que dá estrutura e clareza ao desenvolvimento de sistemas complexos. Em vez de focar apenas em tecnologia, ele prioriza o negócio, as regras e a linguagem da empresa. No ecossistema .NET, temos suporte maduro para aplicar os padrões recomendados e escalar sistemas com qualidade e robustez.


🤝 Conecte-se Comigo

Top comments (0)