Zastanawiałem się czy poniższy kod to dobra praktyka czy też nie. Niemniej, w obecnym projekcie się sprawdza. Na razie. Pomyślałem więc, że skoro się “na razie” sprawdza to warto się nią podzielić. I o to ona!
1
2
3
4
5
6
7
public interface LogSomethingEvent extends Event {
MainId mainId();
String fullMessage();
}
Oczywiście kod został zobfuskowany, ale główna idea pozostaje niezmenna. Stworzyliśmy w zespole interfejs, który jest takim znacznikiem eventowym zdefiniowanym przez moduł go obsługujący (jego publiczne API). Wygląda więc na komendę, a to już budzi niepokój czy to faktycznie jest “prawidłowe” rozwiązanie. Jednak dzięki niemu wystarczy, że inny, konkretny event zaimplementuje powyższy interfejs i log w naszym audycie gotowy!
1
2
3
4
5
6
7
8
9
10
11
public record TaskReviewedEvent(
MainId mainId,
String taskName
) implements DomainEvent, LogSomethingEvent {
@Override
public String fullMessage() {
return "\"" + taskName + "\" has been reviewed";
}
}
1
2
3
4
5
6
7
8
9
@EventListener
@Transactional
public void handle(LogSomethingEvent event) {
MainId mainId = event.mainId();
Log log = logFactory.create(mainId, event.fullMessage());
logRepository.save(log);
}
I to tyle. Handler dla eventu jest naprawdę stabilny. Od dłuższego czasu nie ulega żadnym zmianom. A znacznik jest zaimplementowany już przez kilkanaście klas.
Jedyne co budzi nasz niepokój to dane, które trzeba przekazać do eventu, aby wygenerować odpowiedni log. W powyższym przypadku jest to taskName
. Z punktu widzenia domeny jest on kompletnie nie potrzebną informacją - oczywiście poza tworzeniem historii audytowej. Jednak nie jest to aż taki duży narzut powodujący straszne problemy. Da się z tym żyć.
Daj znać co o sądzisz o powyższym rozwiązaniu. Czy warto odchodzić od dobrych praktyk (event to nie komenda) i być pragmatycznym? Czy też nie? Być może widzisz w powyższym rozwiązaniu jakieś logiczne dziury, nad którymi trzeba się zastanowić.