Mas, e se um dos eventos fizer com que um sistema externo que não esteja sob seu controle "envie um item" para o cliente se você apenas reproduzir os eventos, o item será enviado duas vezes.
Para escolher um exemplo específico, vamos considerar como uma abordagem "pelo menos uma vez" aos efeitos colaterais pode funcionar.
State currentState = State.InitialState
for(Event e : events) {
currentState = currentState.apply(e)
}
for(SideEffect s : currentState.querySideEffects()) {
performSideEffect(s)
Portanto, o modelo de domínio rastreia o que precisa ser feito; mas deixa o real fazendo para o aplicativo
No contexto da execução de um comando, a ideia básica parece a mesma. Os efeitos colaterais reais ocorrem fora da transação que atualiza o modelo.
Portanto, os testes de unidade para o seu modelo podem parecer algo como
{
// Given
State currentState = State.InitialState
// When
Events events = List.of(OrderPlaced)
// Then
List.of(SendEmail) === currentState.applyAll(events).querySideEffects()
}
{
// Given
State currentState = State.InitialState
// When
Events events = List.of(OrderPlaced, EmailSent)
// Then
List.EMPTY === currentState.applyAll(events).querySideEffects()
}
Os principais pontos aqui sendo
- A atualização do modelo é livre de efeitos colaterais; os efeitos colaterais reais ocorrem fora da transação que atualiza o modelo.
- Um evento que descreve o resultado do efeito colateral precisa voltar.