Usando DDD tático para projetar microsserviços

Azure Migrate

O design orientado por domínio (DDD) se opõe à ideia de ter um único modelo unificado para todo o sistema; em vez disso, incentiva a divisão do sistema em contextos limitados, cada um dos quais tem o seu próprio modelo. Durante a fase estratégica do DDD, está a mapear o domínio do negócio e a definir contextos vinculados para os modelos de domínio.

O DDD tático é quando define os modelos de domínio com mais precisão. Os padrões táticos são aplicados num único contexto vinculado. Em uma arquitetura de microsserviços, onde cada contexto limitado é um candidato a microsserviço, estamos particularmente interessados na entidade e nos padrões agregados. A aplicação desses padrões nos ajudará a identificar limites naturais para os serviços em nosso aplicativo (consulte o próximo artigo desta série). Como princípio geral, um microsserviço não deve ser menor do que uma agregação e não deve ser maior do que um contexto vinculado. Primeiro, vamos rever os padrões táticos. Em seguida, vamos aplicá-los ao contexto limitado de envio no aplicativo Drone Delivery.

Visão geral dos padrões táticos

Esta seção fornece um breve resumo dos padrões táticos de DDD, portanto, se você já está familiarizado com DDD, provavelmente pode pular esta seção. Os padrões são descritos com mais detalhes nos capítulos 5 a 6 do livro de Eric Evans, e em Implementing Domain-Driven Design de Vaughn Vernon.

Diagrama de padrões táticos em design orientado por domínio

entidades. uma entidade é um objeto com uma identidade exclusiva que persiste ao longo do tempo. Por exemplo, numa aplicação bancária, os clientes e as contas seriam entidades.

  • Uma entidade tem um identificador exclusivo no sistema, que pode ser usado para pesquisar ou recuperar a entidade. Isso não significa que o identificador esteja sempre exposto diretamente aos usuários. Pode ser um GUID ou uma chave primária em um banco de dados.
  • Uma identidade pode abranger vários contextos limitados e pode durar além do tempo de vida do aplicativo. Por exemplo, números de contas bancárias ou IDs emitidos pelo governo não estão vinculados ao tempo de vida de um aplicativo específico.
  • Os atributos de uma entidade podem mudar ao longo do tempo. Por exemplo, o nome ou endereço de uma pessoa pode mudar, mas ela ainda é a mesma pessoa.
  • Uma entidade pode conter referências a outras entidades.

Objetos de valor. Um objeto value não tem identidade. Ele é definido apenas pelos valores de seus atributos. Os objetos de valor também são imutáveis. Para atualizar um objeto de valor, você sempre cria uma nova instância para substituir a antiga. Os objetos de valor podem ter métodos que encapsulam a lógica de domínio, mas esses métodos não devem ter efeitos colaterais no estado do objeto. Exemplos típicos de objetos de valor incluem cores, datas, horas e valores de moeda.

Agregados. uma agregação define um limite de consistência em redor de uma ou mais entidades. Exatamente uma entidade em um agregado é a raiz. A pesquisa é feita usando o identificador da entidade raiz. Quaisquer outras entidades na agregação são filhas da raiz e são referenciadas seguindo ponteiros da raiz.

A finalidade de uma agregação é modelar invariáveis transacionais. As coisas no mundo real têm redes complexas de relações. Os clientes criam pedidos, os pedidos contêm produtos, os produtos têm fornecedores e assim por diante. Se a aplicação modificar vários objetos relacionados, como garante a consistência? Como mantemos o controlo das invariáveis e as aplicamos?

Os aplicativos tradicionais costumam usar transações de banco de dados para impor consistência. Em um aplicativo distribuído, no entanto, isso muitas vezes não é viável. Uma única transação comercial pode abranger vários armazenamentos de dados, ser de longa duração ou envolver serviços de terceiros. Em última análise, cabe ao aplicativo, não à camada de dados, impor as invariantes necessárias para o domínio. É isso que os agregados servem de modelo.

Nota

Uma agregação pode consistir em uma única entidade, sem entidades filhas. O que o torna um agregado é o limite transacional.

Serviços de domínio e aplicação. na terminologia DDD, um serviço é um objeto que implementa alguma lógica sem manter nenhum estado. Evans distingue entre serviços de domínio, que encapsulam a lógica de domínio, e serviços de aplicativos, que fornecem funcionalidade técnica, como autenticação de usuário ou envio de uma mensagem SMS. Os serviços de domínio são geralmente utilizados para modelar o comportamento que abrange múltiplas entidades.

Nota

O termo serviço é sobrecarregado no desenvolvimento de software. A definição aqui não está diretamente relacionada aos microsserviços.

Eventos de domínio. os eventos de domínio podem ser utilizados para notificar outras partes do sistema quando algo acontece. Como o nome sugere, os eventos de domínio devem significar algo dentro do domínio. Por exemplo, "um registo foi inserido numa tabela" não é um evento de domínio. "Uma entrega foi cancelada" é um evento de domínio. Os eventos de domínio são especialmente relevantes numa arquitetura de microsserviços. Uma vez que os microsserviços são distribuídos e não partilham arquivos de dados, os eventos de domínio fornecem uma maneira de os microsserviços se coordenarem entre si. O artigo Comunicação interserviços discute as mensagens assíncronas com mais detalhes.

Existem alguns outros padrões DDD não listados aqui, incluindo fábricas, repositórios e módulos. Esses podem ser padrões úteis para quando você está implementando um microsserviço, mas são menos relevantes ao projetar os limites entre microsserviços.

Entrega por drone: Aplicando os padrões

Começamos com os cenários que o contexto limitado de Envio deve lidar.

  • Um cliente pode solicitar um drone para recolher mercadorias de uma empresa que esteja registada no serviço de entrega por drones.
  • O remetente gera uma etiqueta (código de barras ou RFID) para colocar na embalagem.
  • Um drone irá recolher e entregar um pacote do local de origem para o local de destino.
  • Quando um cliente agenda uma entrega, o sistema fornece um ETA com base em informações de rota, condições meteorológicas e dados históricos.
  • Quando o drone está em voo, um usuário pode rastrear a localização atual e a ETA mais recente.
  • Até que um drone recolha a encomenda, o cliente pode cancelar uma entrega.
  • O cliente é notificado quando a entrega é concluída.
  • O remetente pode solicitar a confirmação de entrega ao cliente, sob a forma de assinatura ou impressão digital.
  • Os usuários podem procurar o histórico de uma entrega concluída.

A partir desses cenários, a equipe de desenvolvimento identificou as seguintes entidades.

  • Entrega
  • Pacote
  • Drone
  • Account
  • Confirmação
  • Notificação
  • Etiqueta

Os quatro primeiros, Entrega, Pacote, Drone e Conta, são todos agregados que representam limites de consistência transacional. Confirmações e Notificações são entidades secundárias de Entregas e Etiquetas são entidades secundárias de Pacotes.

Os objetos de valor neste design incluem Location, ETA, PackageWeight e PackageSize.

Para ilustrar, aqui está um diagrama UML do agregado Delivery. Observe que ele contém referências a outros agregados, incluindo Conta, Pacote e Drone.

Diagrama UML do agregado Delivery

Existem dois eventos de domínio:

  • Quando um drone está em trânsito, a entidade Drone envia eventos EstadoDoDrone que descrevem a localização e o estado do drone (em trânsito, pousado).

  • A entidade Entrega envia eventos AcompanhamentoDaEntrega sempre que a fase de uma entrega é alterada. Estes incluem EntregaCriada, EntregaReagendada, EntregaEmTrânsito e EntregaConcluída.

Observe que estes eventos descrevem coisas que são significativas no modelo de domínio. Descrevem algo sobre o domínio e não estão vinculados a uma construção de linguagem de programação específica.

A equipa de desenvolvimento identificou mais uma área de funcionalidade, que não se enquadra perfeitamente em nenhuma das entidades descritas até agora. Algumas partes do sistema devem coordenar todos os passos envolvidos no agendamento ou atualização de uma entrega. Portanto, a equipe de desenvolvimento adicionou dois serviços de domínio ao design: um Agendador que coordena as etapas e um Supervisor que monitora o status de cada etapa, a fim de detetar se alguma etapa falhou ou expirou. Esta é uma variação do padrão Scheduler Agent Supervisor.

Diagrama do modelo de domínio revisto

Próximos passos

O próximo passo é definir os limites para cada microsserviço.