Domain-Driven Design em C#: como não se afogar na complexidade

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Domain-Driven Design em C#: como não se afogar na complexidade

\n\n

Quando seu projeto C# supera o estágio de "aplicação CRUD simples", chega o momento da verdade. A lógica de negócio começa a se embaralhar, os métodos dos serviços crescem para centenas de linhas, e a palavra "refatoração" causa tremores nervosos. Familiar? Bem-vindo ao mundo onde, sem Domain-Driven Design (DDD), você corre o risco de transformar o código em um pântano.

\n\n

DDD não é sobre "mais um framework". É uma filosofia que coloca o domínio de negócio no centro do universo. Hoje vamos analisar como aplicar Domain-Driven Design em projetos C# para que o código se torne não apenas funcional, mas compreensível e flexível. Sem enrolação — apenas exemplos reais e dicas práticas.

\n\n

Por que o DDD salva projetos C#?

\n\n

Imagine que você está escrevendo um sistema para gerenciar pedidos em uma loja online. Se você simplesmente colocar toda a lógica nos controladores ASP.NET, depois de seis meses não conseguirá explicar por que o método CreateOrder() chama CalculateShipping(), que, por sua vez, acessa o banco de dados para taxas de câmbio. O DDD oferece uma separação clara: existe uma camada de domínio, onde vive a lógica de negócio, e uma infraestrutura, que cuida dos detalhes técnicos.

\n\n

A ideia central do DDD é a Ubiquitous Language (linguagem ubíqua). Você e os especialistas de negócio falam a mesma língua. No código, isso se expressa em termos como: "Order", "LineItem", "DiscountPolicy", e não "OrderDto", "OrderService" e "Helper". Quanto mais próximo o código estiver da linguagem do negócio, mais fácil será mantê-lo.

\n\n

Design estratégico e tático

\n\n

O DDD se divide em duas partes: a estratégica (como dividir o sistema em módulos) e a tática (como escrever o código dentro do módulo). Em C#, o design tático nos fornece quatro blocos de construção poderosos:

\n\n
    \n
  • Entity — objeto com um identificador único (por exemplo, OrderId).
  • \n
  • Value Object — objeto que é definido por seus atributos (por exemplo, Money ou Address).
  • \n
  • Aggregate Root — entidade raiz que gerencia um grupo de objetos.
  • \n
  • Repository — abstração de acesso a dados.
  • \n
\n\n

Vamos ver como isso se parece no código.

\n\n

Exemplo: projetando um pedido (Order)

\n\n

Vamos começar com algo simples: temos um pedido que consiste em itens. O pedido pode estar no status "Novo", "Pago" ou "Cancelado".

\n\n

1. Value Object: Money

\n\n

Dinheiro é um Value Object clássico. Dois objetos Money são iguais se tiverem o mesmo valor e moeda. Eles são imutáveis.

\n\n
public sealed record Money(decimal Amount, string Currency)\n{\n    public static Money operator +(Money left, Money right)\n    {\n        if (left.Currency != right.Currency)\n            throw new InvalidOperationException("Currency mismatch");\n        return new Money(left.Amount + right.Amount, left.Currency);\n    }\n}\n
\n\n

Observe o record — em C# 9+ esta é a maneira ideal de criar um Value Object. Ele fornece automaticamente Equals, GetHashCode e imutabilidade.

\n\n

2. Entity: Order e LineItem

\n\n

As entidades têm um identificador. Vamos criar uma classe base para Entity:

\n\n
public abstract class Entity<TId>\n{\n    public TId Id { get; protected set; }\n\n    protected Entity(TId id) => Id = id;\n\n    public override bool Equals(object? obj) =>\n        obj is Entity<TId> other && Id!.Equals(other.Id);\n\n    public override int GetHashCode() => Id!.GetHashCode();\n}\n
\n\n

Agora o próprio Order e LineItem:

\n\n
public class Order : Entity<Guid>\n{\n    private readonly List<LineItem> _items = new();\n    public IReadOnlyList<LineItem> Items => _items.AsReadOnly();\n    public OrderStatus Status { get; private set; }\n    public Money Total { get; privat                

Blogs

Book Recommendations