Onde a lógica de negócios envolve vários agregados?

5
Ainda sou um iniciante quando se trata de design dirigido por domínio, e estou tentando modelar algo como o sistema de batalha de um RPG como um contexto limitado. Eu estou tentando modelar um contexto limitado em que um Combatente tem uma lista de habilidades, e cada Capacidade tem uma lista de efeitos que seriam aplicados. Por exemplo, um Efeito comum seria causar dano ao Combatente alvo.

Tanto quanto eu posso dizer, as duas raízes agregadas seriam Combatente e Habilidade, com Efeito sendo um objeto de valor.

Agora, não estou certo de onde eu deveria estar colocando minha lógica para a interação entre os Combatentes. Em particular, precisarei de lógica que lide com a execução de uma habilidade levando em consideração a fonte Combatente e o Combatente alvo. Da mesma forma, precisarei de lógica semelhante para os efeitos individuais de uma habilidade. Como a ação e os efeitos estão sendo causados por uma instância de um Combatente e estão tendo como alvo uma segunda instância do Combatente, não creio que a lógica deva ser feita dentro do próprio agregado do Combatente.

O problema é que eu simplesmente não sei onde a lógica deve ir. Inicialmente, pensei que um serviço de domínio seria o ponto certo, mas depois de pesquisá-los, acho que posso estar errado. Alguém tem alguma idéia de onde eu deveria estar colocando essa lógica?

    
por LayfieldK 04.02.2018 / 17:16
fonte

1 resposta

5

A lógica de negócios que coordena os processos envolvendo vários agregados deve permanecer em um gerenciador de Saga / Process . Isso não significa que toda a lógica deva permanecer lá. Não. Apenas a lógica de coordenação. A implementação real depende da linguagem de programação e da arquitetura, mas eu poderia dar a você e exemplo.

Por exemplo, suponhamos que um combatente inflija dano (fogo) a outro combatente. O processo de disparo é tratado por um Saga . Mas todo combatente deve ter dois métodos de comando: inflectDamageTo e getDamagedBy . A Saga carrega a shooter agregada, chama shooter.fireAt(shootedId, effect) e persiste as alterações. Em seguida, ele carrega o shooted agregado, chama shooted.getDamagedBy(shooterId, effect) e persiste as alterações.

Antes e depois de cada passo, a Saga poderia continuar seu progresso. Isso pode ser tão simples quanto um Enum . Você faz isso para ter informações suficientes para recuperar em caso de algo dar errado e a Saga for parada com força (ou seja, o processo é interrompido, o servidor é reiniciado, etc.).

Tenha em mente que neste processo você tem duas transações, não apenas uma (ou nenhuma, dependendo do tipo de persistência). Além disso, observe que cada agregado recebe apenas o ID do outro e não uma referência completa.

P.S. Existem alguns domínios em que o desempenho é mais importante do que a capacidade de manutenção do código ou a consistência dos dados; Baseio minha resposta no fato de que você analisou seus requisitos de negócios e ainda deseja usar a abordagem DDD.

    
por 04.02.2018 / 18:14
fonte