Let's assume I was building a collaborative document editing platform ala Google Docs.
Collaborators
work together on a Document
. A Collaborator
must be a user of the platform.
There's a Comment
subdomain that allows Collaborators
to communicate within a Document
.
When a Comment
is created, all Collaborators
should be notified according to their account notification preferences (email, SMS or both).
The notification preferences is stored in a seperate Users
domain.
How can I notify the users whilst maintaining clean separation of my domains?
The options I see:
Raise a
CommentPosted
domain event from within theComment
domain and listen to the event within aComment
application service, which makes a call to theUser
domain for the users and then invokes theEmailService
to send an email. The issue here is now theComment
application service knows about and is coupled on theUser
domain.Have the
User
service listen to theCommentPosted
event. With event-carried state transfer theUser
service should have enough knowledge to formulate and send the email. Still, not sure that it's a good idea for theUser
service to know aboutCommentPosted
event (then again, isn't that part of the idea behind an event-sourced system?).Still raise
CommentPosted
from within theComment
domain but this time have the handler fire off aSendEmailCommand
message. Have an infrastructure email service (most likely a microservice) listen to theSendEmailCommand
. The email service can then make a request to theUser
service to get the email (and probably have it's own cache ofUserId
toEmail
anyway).This seems to be the most generic approach but it does mean the Email infrastructure service now needs some understanding of domain constructs (namely, the
UserId
). Again, I'm not entirely sure that this is a bad thing.At the moment, the Email service is basically just a dumb
port
to an external email service with one method:Email.sendEmail(Email email)
. In this case, it'll might need to change toEmail.sendEmail(User userId, Email email)
.
-
4The events are the interface between your services. In dep. inversion terms, events are the abstraction. The services aren't coupled to each other, but to the event format/protocol, so design that carefully. Also, it's worth knowing that not all of the system has to use event sourcing. BTW, this seems like really a single domain with multiple services, so if you are in control of all of it, there's no need for internal anti-corruption layers. Consider too that notification preferences don't have to be stored in the User service, you could store them with the service that actually needs them.Filip Milovanović– Filip Milovanović2019年11月28日 12:27:08 +00:00Commented Nov 28, 2019 at 12:27
-
I guess the design of events is part of my confusion. If the User service actually cared about the event it wouldn't be an issue, but in this case the only function of the event is to query the User for it's email and notification preference to enable the sending of the email. If anything it almost feels like a command in disguise.NRaf– NRaf2019年11月28日 18:28:27 +00:00Commented Nov 28, 2019 at 18:28
-
The example I gave is simplified in the sense that more than one service cares about the notification preferences. Goes back to having the email or notification store or cache that info, but again, it feels weird to have to add a custom event handler in that service for each email that needs to be sent. In that scenario a Command seems to make more sense.NRaf– NRaf2019年11月28日 18:30:25 +00:00Commented Nov 28, 2019 at 18:30