• O que são Subdomínios no Domain-Driven Design?

    O que são Subdomínios no Domain-Driven Design?

    Quando lidamos com sistemas complexos, um dos maiores desafios é compreender o negócio de forma organizada. O Domain-Driven Design (DDD) propõe que, antes mesmo de pensar em código, precisamos entender profundamente o domínio — ou seja, o problema central que o software deseja resolver. Dentro desse domínio, existem partes menores e especializadas: os subdomínios.

    Vaughn Vernon, em Domain-Driven Design Destilado, reforça que identificar subdomínios é um dos passos fundamentais para criar sistemas coerentes, expressivos e mais fáceis de evoluir.


    Por que subdomínios existem?

    Um negócio de verdade não é monolítico. Ele é composto por diversas capacidades, processos e responsabilidades distintas. Os subdomínios representam exatamente isso: segmentos do negócio que possuem objetivos e regras próprias.

    Dividir o domínio em subdomínios ajuda a enxergar melhor as partes importantes, reduz confusões conceituais e prepara o terreno para decisões arquiteturais melhores — como os Bounded Contexts.


    Três tipos de subdomínios

    Vaughn Vernon destaca três categorias que ajudam a entender o papel de cada parte do negócio:

    1. Subdomínio Core (Core Domain)

    É o coração do negócio, aquilo que realmente diferencia a empresa no mercado.
    É onde você investe mais esforço de modelagem, especialistas do negócio e design cuidadoso.

    Exemplo:
    Em uma plataforma de investimentos, o “motor de cálculo de risco e rentabilidade” pode ser o core domain. É a inteligência que torna a plataforma melhor que a concorrência.


    2. Subdomínios de Suporte (Supporting Subdomains)

    São importantes para que o core funcione bem, mas não representam diferencial competitivo.
    Têm regras próprias, mas servem principalmente para dar sustentação ao core.

    Exemplo:
    Ainda na plataforma de investimentos, áreas como “gestão de clientes” ou “atualização cadastral” são essenciais, porém não definem inovação. São processos que precisam estar corretos, mas não precisam de modelagem profunda como o core.


    3. Subdomínios Genéricos (Generic Subdomains)

    São capacidades que quase todo negócio precisa e não valem o esforço de reinventar.
    Normalmente são resolvidos com bibliotecas, frameworks ou serviços já existentes.

    Exemplo:
    Autenticação, envio de notificações por e-mail, controle de acesso.
    Faz sentido usar soluções consolidadas em vez de construir tudo do zero.


    Como identificar subdomínios na prática?

    A análise começa conversando com especialistas do negócio, entendendo processos reais e observando onde estão as diferenças de linguagem, objetivos e regras. Subdomínios costumam aparecer quando:

    • uma parte do negócio tem linguagem própria (“risco”, “perfil”, “vector de exposição” são típicos do domínio financeiro)
    • o processo tem etapas e decisões específicas
    • a responsabilidade daquela área é clara e independente das demais

    O segredo é olhar para o negócio como um mapa: cada região desse mapa é um subdomínio com fronteiras conceituais claras.


    Exemplos de subdomínios em diferentes áreas

    E-commerce

    • Core: estratégia de precificação, recomendação de produtos
    • Suporte: catálogo, inventário, pagamentos
    • Genérico: autenticação, geração de boletos, envio de e-mails

    Aplicativo de entrega

    • Core: sistema de roteamento inteligente e previsão de entrega
    • Suporte: cadastro de restaurantes, avaliações
    • Genérico: login, monitoramento de logs

    Banco digital

    • Core: motor de aprovação de crédito, análise de risco
    • Suporte: abertura de conta, operações de cartões
    • Genérico: envio de SMS, verificação de identidade via terceiros

    Esses exemplos mostram que o “core” nunca é o sistema inteiro, mas sim aquele pedaço onde a empresa se diferencia.


    Subdomínio não é Bounded Context

    É comum confundir os dois, mas eles têm papéis diferentes:

    • Subdomínio → existe no negócio
    • Bounded Context → existe na modelagem do software

    Ou seja, primeiro entendemos o negócio por meio de subdomínios; depois, ao transformar isso em software, criamos bounded contexts para representar esses conceitos dentro de limites claros.


    Conclusão

    Subdomínios são a primeira grande divisão lógica dentro do domínio de um negócio. Eles ajudam a enxergar prioridades, planejar melhor o design e decidir onde vale investir mais esforço. Seguindo o raciocínio de Vaughn Vernon, reconhecer o que é core, o que é suporte e o que é genérico permite que a equipe concentre energia naquilo que realmente importa e simplifique o que pode ser reaproveitado.

    Dominar esse conceito é abrir caminho para aplicar o restante do DDD com muito mais clareza e propósito — especialmente quando chega o momento de definir bounded contexts e arquiteturas alinhadas ao domínio.

  • Arquiteturas que Potencializam o Uso de Domain-Driven Design

    Arquiteturas que Potencializam o Uso de Domain-Driven Design

    Domain-Driven Design (DDD) é uma abordagem que coloca o domínio — as regras, conceitos e processos essenciais do negócio — no centro das decisões de software. Embora seus princípios possam ser aplicados em diversos estilos arquiteturais, algumas arquiteturas dialogam de forma especialmente natural com o DDD, pois favorecem isolamento de responsabilidades, clareza de limites e evolução contínua. A seguir, exploramos essas arquiteturas, como elas fortalecem o DDD e quais livros ajudam a aprofundar cada tema.

    Event-Driven Architecture (EDA)

    Em muitos domínios, eventos representam mudanças relevantes: um pedido é criado, um pagamento é aprovado, um contrato expira. A Event-Driven Architecture transforma esses acontecimentos em mensagens explícitas, permitindo que diferentes Bounded Contexts se comuniquem sem acoplamento direto.

    Essa abordagem combina de maneira orgânica com Domain Events do DDD, favorecendo autonomia e escalabilidade dentro de sistemas distribuídos.

    Livro recomendado: Implementing Domain-Driven Design, de Vaughn Vernon — que integra eventos ao design tático e estratégico do DDD.

    Command Query Responsibility Segregation (CQRS)

    CQRS separa a responsabilidade de escrita (comandos) da responsabilidade de leitura (consultas). Essa divisão reduz conflitos entre regras de negócio e necessidades de consulta, tornando o modelo de domínio mais limpo e focado.

    Em DDD, CQRS permite que o modelo de domínio represente comportamentos e invariantes com clareza, enquanto os modelos de leitura são moldados para atender demandas específicas de visualização ou desempenho.

    Livro recomendado: Não há um livro único e oficial sobre CQRS, mas os materiais e workshops de Greg Young — criador do padrão — são as melhores referências.

    Actor Model e Arquiteturas Reativas

    Em arquiteturas reativas baseadas no Actor Model, cada componente isola seu estado e se comunica exclusivamente por mensagens. Essa abordagem reduz riscos de concorrência e facilita modelagem de comportamentos distribuídos.

    No contexto de DDD, atores podem representar entidades ou agregados, e o fluxo de mensagens se alinha naturalmente a políticas do domínio. Essa combinação é especialmente útil em sistemas que lidam com grandes volumes de eventos simultâneos.

    Livro recomendado: Reactive Messaging Patterns with the Actor Model, de Vaughn Vernon.

    REST-Based Architecture

    REST continua sendo um dos estilos mais populares para expor capacidades de sistemas modernos. Ele estrutura recursos em torno de representações simples e previsíveis, facilitando integração entre diversos contextos.

    Quando usado dentro de limites bem definidos, REST funciona como uma porta estável de comunicação para um Bounded Context, sem comprometer a expressividade interna do modelo de domínio.

    Livro recomendado: RESTful Web Services, de Leonard Richardson e Sam Ruby.

    Service-Oriented Architecture (SOA)

    SOA introduziu a ideia de serviços autônomos, orientados a capacidades específicas do negócio. Esses princípios ecoam diretamente a noção de Bounded Contexts no DDD.

    Embora SOA costume ser aplicado em ambientes corporativos amplos, sua insistência em contratos, interoperabilidade e limites bem definidos reforça práticas essenciais do DDD.

    Livro recomendado: SOA Principles of Service Design, de Thomas Erl.

    Microservices Architecture

    A arquitetura de microservices ganhou força por dividir sistemas em serviços pequenos e independentes. Porém, sem entendimento claro de limites, microservices facilmente se tornam fragmentação acidental.

    No DDD, esses serviços devem nascer de Bounded Contexts. Quando existe um alinhamento entre limites do domínio e limites do serviço, microservices oferecem autonomia real, escalabilidade e evolução descentralizada.

    Livro recomendado: Building Microservices, de Sam Newman — uma visão prática, combinável com o DDD. Para padrões avançados, Microservices Patterns, de Chris Richardson.

    Hexagonal Architecture (Ports and Adapters)

    A Arquitetura Hexagonal, ou Ports and Adapters, separa o núcleo de domínio das dependências externas. O domínio fica protegido de detalhes técnicos, bancos, frameworks ou protocolos de comunicação.

    Esse isolamento permite que o modelo de domínio evolua livremente, reforçando a centralidade do negócio e tornando o software mais testável e adaptável. Essa arquitetura é especialmente eficaz quando combinada com os padrões táticos do DDD.

    Livro recomendado: Implementing Domain-Driven Design, de Vaughn Vernon. Para referência conceitual original, os textos de Alistair Cockburn sobre Ports and Adapters.


    Conclusão

    Cada arquitetura apresentada reforça, à sua maneira, os princípios do Domain-Driven Design. Event-Driven Architecture evidencia acontecimentos importantes do negócio; CQRS organiza responsabilidades de forma clara; o Actor Model fortalece sistemas concorrentes e orientados a mensagens; REST facilita integração entre contextos; SOA e microservices dão forma explícita aos limites contextuais; e a Arquitetura Hexagonal protege o domínio das pressões externas.

    Quando combinadas com discernimento, essas abordagens ampliam a capacidade de um sistema representar o negócio com precisão, evoluir com segurança e permanecer compreensível com o tempo. É justamente nessa interseção entre arquitetura e domínio que o DDD atinge seu potencial máximo.

  • Bounded Context (Contexto Delimitado): Conceito, Aplicação e Recomendações Práticas

    Quando um sistema cresce, seus conceitos começam a se repetir em diferentes áreas da aplicação. Muitas vezes, a mesma palavra passa a significar coisas distintas dependendo de onde é usada. Essa sobreposição de significados cria modelos confusos, entidades infladas e código difícil de manter.
    O Bounded Context surgiu justamente para evitar esse tipo de problema.

    A imagem evidencia a ideia central do bounded context: cada parte do domínio tem suas próprias regras, comportamentos e linguagem interna. Nada está misturado ou confuso; os mundos coexistem lado a lado, independentes e ao mesmo tempo integráveis pelos pontos certos.

    Bounded Context?

    Um Bounded Context (Contexto Delimitado) é uma fronteira clara onde um conjunto de conceitos, regras e modelos tem um significado único e consistente.

    Dentro dessa fronteira:

    • as palavras são usadas com precisão;
    • o modelo é criado apenas para resolver as necessidades daquele contexto;
    • não há obrigação de carregar significados de outros lugares do sistema.

    Fora desse limite, os mesmos termos podem ter definições diferentes, e isso é desejável.
    Cada contexto descreve apenas a parte do domínio que realmente lhe pertence.


    Por que usar Bounded Contexts

    A separação do domínio em bounded contexts ajuda a:

    • reduzir ambiguidades no significado dos conceitos;
    • evitar modelos inflados e genéricos;
    • diminuir dependências indevidas entre áreas do sistema;
    • permitir que cada parte evolua com clareza e foco.

    Essa abordagem torna o software mais compreensível e mais fácil de manter ao longo do tempo.


    Vamos a um exemplo simples

    Imagine uma plataforma de ensino.

    Contexto de catálogo

    O objetivo é exibir cursos ao usuário.

    O modelo Curso pode conter:

    • título
    • descrição
    • carga horária
    • categoria

    Esse contexto se preocupa apenas com apresentação.

    Contexto de matrículas

    Aqui, Curso representa outra realidade:

    • quantidade de vagas
    • período de matrícula
    • regras de elegibilidade
    • status da turma

    O foco é controlar quem pode se matricular e quando.

    É a mesma palavra (Curso), mas com significados diferentes. Cada contexto preserva seu próprio uso do conceito, sem interferências desnecessárias.


    Agora segue um exemplo de quando não existe Bounded Context

    Sem dividir por contextos, é comum surgir uma única entidade chamada Curso contendo todos os campos de todas as áreas:

    • título, descrição e carga horária
    • vagas e períodos
    • preços
    • regras administrativas
    • métricas internas
    • requisitos e calendários
    • status de matrícula

    Esse acúmulo cria:

    • complexidade desnecessária;
    • propriedades que só fazem sentido para parte do sistema;
    • validações confusas;
    • impacto imprevisível quando a entidade é alterada.

    Bounded Context evita justamente essa mistura de significados.


    Dúvidas comuns

    Uma aplicação deve ter quantos Bounded Contexts?

    Não existe uma regra fixa. O domínio é quem define as fronteiras.

    Quando há apenas um contexto

    Projetos pequenos, MVPs e domínios simples podem começar com um único contexto.
    Separar cedo demais traz complexidade artificial.

    Quando há vários contextos

    Em sistemas reais, é comum existir mais de um.
    Isso ocorre quando:

    • diferentes áreas do sistema usam o mesmo termo com significados distintos;
    • regras de negócio são muito específicas para cada área;
    • modelos ficariam grandes demais se unidos.

    É natural, e até esperado, que um software maduro tenha múltiplos bounded contexts.


    Os bounded contexts precisam ser aplicações separadas?

    Não necessariamente. Existem duas formas de organizá-los:

    1. Vários bounded contexts na mesma aplicação

    Funciona bem quando:

    • o sistema ainda não exige escalabilidade independente;
    • a equipe é pequena;
    • os contextos ainda evoluem juntos.

    Nesse caso, a separação é lógica: pastas, módulos, camadas.

    2. Cada bounded context como um serviço independente

    Acontece quando:

    • os contextos são grandes;
    • equipes trabalham separadas;
    • há necessidade de autonomia e deploy independente.

    Isso geralmente aparece em arquiteturas de microsserviços, mas só é recomendado quando existe independência real entre contextos.


    E o repositório Git? Monorepo ou Multirepo?

    A escolha depende do nível de independência dos bounded contexts.

    Monorepo (um único repositório)

    Recomendado quando:

    • os contextos estão na mesma aplicação;
    • mudanças frequentemente envolvem mais de um contexto;
    • equipes são pequenas.

    Facilita refatoração e manutenção.

    Multirepo (um repositório por contexto)

    Faz sentido quando:

    • cada contexto é um serviço separado;
    • equipes diferentes mantêm contextos distintos;
    • ciclos de deploy são independentes.

    Traz autonomia, mas aumenta a necessidade de contratos estáveis e comunicação clara entre serviços.


    Recomendações práticas

    • Deixe o domínio apontar onde os contextos começam e terminam.
    • Só separe quando existir diferença real de significado ou regras.
    • Não transforme cada contexto em um serviço isolado sem necessidade.
    • Prefira monorepo para projetos pequenos ou médios.
    • Use multirepo apenas quando autonomia e deploy independente forem requisitos do domínio.

    Conclusão

    O Bounded Context é uma ferramenta essencial para manter sistemas compreensíveis conforme crescem. Ele funciona como um mapa que impede que conceitos se misturem, garantindo que cada parte do domínio tenha seu próprio significado, suas próprias regras e seu próprio ritmo de evolução. Essa clareza reduz atrito entre equipes, diminui ambiguidades e preserva a saúde do modelo ao longo do tempo.

    Nem todo software precisa começar com vários bounded contexts. Em sistemas pequenos ou em fases iniciais, um único contexto costuma ser suficiente e até desejável. A divisão se torna realmente importante quando o domínio cresce a ponto de a mesma palavra significar coisas diferentes, quando regras de negócio se tornam complexas em áreas distintas, ou quando o modelo passa a ficar pesado demais para representar tudo de uma só vez.

    Quando bem aplicados, os bounded contexts ajudam o software a refletir de forma mais fiel a realidade do negócio, evitando acoplamentos desnecessários e permitindo que cada parte evolua no seu próprio ritmo. Essa prática não é apenas uma escolha arquitetural: é uma maneira de manter o domínio saudável, o código sustentável e a comunicação entre equipes mais clara — três pilares fundamentais em qualquer produto que pretende sobreviver ao tempo e à complexidade inevitável de sistemas vivos.