DEV Community

Danilo O. Pinheiro, dopme.io
Danilo O. Pinheiro, dopme.io

Posted on

DDD com .NET: Separando Responsabilidades com Bounded Contexts

"A confusão começa quando diferentes áreas de negócio compartilham um mesmo modelo de dados." — Eric Evans

Com o crescimento de aplicações, principalmente em arquiteturas de microserviços, cresce também a complexidade de lidar com múltiplos domínios de negócio. É aí que entra o DDD (Domain-Driven Design) e seu conceito-chave: o Bounded Context.

Neste artigo, vamos explorar como aplicar DDD com Bounded Contexts na prática, utilizando .NET 8, organização de pastas e exemplos reais.


📦 O que é um Bounded Context?

Um Bounded Context é uma fronteira explícita dentro de um domínio, onde um modelo específico é definido e aplicado de forma consistente.

Na prática, isso significa separar funcionalidades como Financeiro, Cadastro, Logística, etc., em contextos independentes — cada um com seu vocabulário, regras de negócio e estrutura de dados.


🧰 Tecnologias Utilizadas

  • .NET 8 (Web API)
  • Clean Architecture
  • DDD tactical patterns (Entity, Aggregate, Repository, Service)
  • MediatR (opcional)
  • MongoDB/PostgreSQL (dependendo do contexto)
  • EventBus (ex: RabbitMQ/Kafka para comunicação entre contextos)

🗂 Estrutura de Projeto com Bounded Contexts

src/
├── CatalogContext/
│   ├── Catalog.Application/
│   ├── Catalog.Domain/
│   ├── Catalog.Infrastructure/
│   └── Catalog.API/
│
├── SalesContext/
│   ├── Sales.Application/
│   ├── Sales.Domain/
│   ├── Sales.Infrastructure/
│   └── Sales.API/
│
└── BuildingBlocks/
    ├── EventBus/
    ├── Core/
    └── Logging/
Enter fullscreen mode Exit fullscreen mode

Cada contexto:

  • É autônomo
  • Possui seu próprio domínio e aplicação
  • Expõe APIs próprias (REST ou gRPC)
  • Se comunica com outros contextos via eventos, nunca diretamente

🧠 Exemplo Prático: Catálogo e Vendas

✅ Catálogo (CatalogContext)

Responsável por: gerenciamento de produtos, preços, estoque

Entidade Product

public class Product
{
    public Guid Id { get; private set; }
    public string Name { get; private set; }
    public decimal Price { get; private set; }

    public Product(string name, decimal price)
    {
        Id = Guid.NewGuid();
        Name = name;
        Price = price;
    }

    public void UpdatePrice(decimal newPrice)
    {
        if (newPrice <= 0)
            throw new DomainException("Preço inválido.");

        Price = newPrice;
    }
}
Enter fullscreen mode Exit fullscreen mode

🛒 Vendas (SalesContext)

Responsável por: criação de pedidos, status de pagamento

Comando CreateOrderCommand

public class CreateOrderCommand : IRequest<Guid>
{
    public Guid ProductId { get; set; }
    public int Quantity { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Handler usando MediatR

public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, Guid>
{
    private readonly IOrderRepository _orderRepo;

    public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        var order = new Order(request.ProductId, request.Quantity);
        await _orderRepo.AddAsync(order);
        return order.Id;
    }
}
Enter fullscreen mode Exit fullscreen mode

🔗 Comunicação entre Contextos

Como SalesContext não tem acesso direto a Product, ele escuta um evento de domínio disparado por CatalogContext:

// Evento no Catalog.Domain
public class ProductPriceChangedEvent : IntegrationEvent
{
    public Guid ProductId { get; set; }
    public decimal NewPrice { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Em SalesContext, um handler consome esse evento e atualiza caches ou triggers de revalidação de pedidos.


🧭 Vantagens dos Bounded Contexts

✅ Redução de acoplamento
✅ Modelagem centrada no negócio
✅ Escalabilidade por domínio
✅ Facilidade para times independentes
✅ Base para adoção de microsserviços


🚨 Cuidados ao Aplicar

⚠️ Evite contextos genéricos (ex: “Core” com tudo misturado)
⚠️ Não compartilhe entidades entre contextos
⚠️ Prefira comunicação eventual/assíncrona


🧩 Quando aplicar Bounded Contexts?

Situação Recomendado?
Módulos com lógicas distintas ✅ Sim
Times atuando em áreas separadas ✅ Sim
Microsserviços ou monólitos modulares ✅ Sim
CRUD simples e pequeno ❌ Overkill

🧪 Próximos passos

Se quiser evoluir esse projeto, você pode:

  • Adicionar EventBus para comunicação (Kafka, RabbitMQ, etc.)
  • Usar OpenTelemetry para rastrear eventos entre contextos
  • Aplicar testes de contrato e integração assíncrona

🤝 Conecte-se Comigo

Se você também está aplicando DDD, arquitetura em camadas ou quer debater cenários reais, vamos trocar ideias:

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.