Publicar eventos para notificar sobre alterações num domínio mantém domínios diferentes desacoplados entre si, mas se realmente houver um fluxo lógico de eventos isso se torna implícito, e difícil de acompanhar. Uma solução melhor é usar um gerenciador de processos (Process Manager) para acompanhar o processo por inteiro, afirmou Bernd Rücker em sua apresentação sobre processos de longa duração e Domain-Driven Design (DDD) deste ano na conferência DDD eXchange.
Rücker, com mais de 10 anos de experiência trabalhando com processos de longa duração, e co-fundador de Camunda, observa que, da perspectiva do consumidor, o processo de compra numa loja online é bastante simples: realizar pedido, pagar, receber o que pediu. Implementar isso usando a perspectiva DDD pode resultar em quatro recursos de negócio e correspondendo a contextos limitados: loja, pagamento, inventário e frete. Esses contextos podem então disparar eventos de domínio correspondentes ao processo de compra: pedido realizado, pagamento recebido, mercadorias separadas e mercadorias enviadas.
Para completar o processo de compra os contextos precisam colaborar e responder aos eventos disparados. Quando um evento de pedido realizado é disparado, o contexto de pagamento, subscrevendo a esses eventos, irá então coletar o dinheiro para o pedido antes de disparar um evento de que o pagamento foi realizado. Um problema com isso, entretanto, é que o contexto de pagamento precisa estar ciente do evento de pedido realizado, e de todos os outros eventos que um pagamento deve disparar. Na prática, significa que sempre que um novo cliente solicita pagamento, o contexto de pagamento deve ser envolvido.
Rücker observa que o problema com o fluxo de eventos é que, embora induza a um baixo nível de acoplamento, não há noção de um processo. Torna mais difícil de ver o fluxo lógico como um todo, se referindo a Martin Fowler. Outra desvantagem é que uma nova regra de negócio que cause uma mudança no fluxo de evento (por exemplo, que clientes VIP podem ter opções diferenciadas de pedidos), devem exigir uma mudança em diversos contextos.
Uma solução melhor, para Rücker, é acompanhar o processo global em um local e usar um gerenciador de processos, com as principais responsabilidades sendo:
- Fazer transformação evento-para-comando. O evento pedido realizado é algo que já aconteceu, e implica algo que realmente queremos que aconteça, um comando, que neste exemplo poderia ser um comando de recuperar pagamento;
- Implementar o fluxo como um cidadão de primeira classe da lógica de domínio. O fluxo geral, bem como a lógica em cada passo individual, são parte da lógica de domínio nos contextos envolvidos;
- Gerenciar o estado para fluxos de longa duração
A partir de uma visão de implementação, o maior desafio para Rücker é o gerenciamento do estado. Maneiras de implementá-lo incluem:
- Modelo de atores (Actor model), usando por exemplo Akka, em que um ator pode ter estado local. Um ator implementa o process manager e é responsável pelo fluxo geral. Isso também é descrito por Vaughn Vernon em seu livro Reactive Messaging Patterns with the Actor Model;
- Mantendo o estado do fluxo do processo numa entidade. É a implementação mais comum na experiência de Rücker;
- Lista de circulação (Routing slip), onde todas as etapas obrigatórias são enviadas com a mensagem. Isso impede a necessidade de armazenamento central de estado de processo;
- Uma máquina de estado em que cada etapa é definida. Rücker observa que uma vantagem que temos usando uma máquina de estado é a visibilidade do estado de um processo.
Em sua experiência trabalhando com clientes implementando processos de longa duração, Rücker viu alguns erros comuns, que incluem não usar mecanismos de fluxo de trabalho ou um caseiro, e usando conjuntos sem código escrito. Em vez disso, recomenda usar uma biblioteca de um framework open source leve, cujo Camunda é um dos muitos, que pode ser incorporado em seu código. Também é recomendado implementar somente os casos mais comuns, excluindo os casos mais excepcionais. Cuidar de talvez 99% de todos os casos e deixar o resto para intervenção humana é uma recomendação feita, também, por Greg Young.
Rücker publicou um exemplo no GitHub que implementa um sistema simples de pedidos usando as ideias de sua apresentação.
A DDD eXchange Conference do próximo ano, em Londres, está agendada para 26-27 de abril de 2018.