Search code examples
domain-driven-design

DDD: References to other layers from domain model


I have a backend for an app that sends push notifications to various users under certain conditions. So far there is an aggregate root PushNotification and an interface PushNotificationSender, whose concrete implementation is defined via dependency injection.

The PushNotificationSender belongs to the Infrastructure Layer or? I also think that the decision when and to whom to send a push notification should be in the Domain Layer.

But how do I send a push notification? As I understood it, the domain layer should not have any dependency on the infrastructure layer. Without this dependency I can't call the PushNotificationSender and therefore I can't send a push notification. How could this be solved?

There is also a feature request that a PushNotification can be sent on a certain date. This additionally brings the Infrastructure Layer into play, because I have to store this ScheduledPushNotification in the database with a Due date until the Due date is reached. My current approach is an Application Layer Service with a method schedulePushNotificationForDate(pushNotification, date), in which ScheduledPushNotificationRepository is injected by DI. Now I have again the problem that the decision which push notification should be sent when to which user is a business rule and should be accordingly in the Domain Layer. But this rule should not access the application layer. How could this case be solved?

Edit - A bit more context

The system is kind of a fitness training app with a frontend on mobile devices and one monolithic backend.

There are the following two use cases:

  1. After a user finishes a workout, all users that follow him should receive a push notification
  2. A user can set a reminder for a workout. This reminder will send a push notification.

As discussed in some comments here, I'm not convinced that sending these push notifications should be only the responsibility of something in the infrastructure layer. I understand that normally it should be like this, but in this case the requirement clearly states that a push notification should be send. So in my opinion this is a business requirement and therefore belongs in the domain layer.


Solution

  • I also think that the decision when and to whom to send a push notification should be in the Domain Layer.

    You are right about that. Additionally, sending notification usually happens asynchronously in a separate transaction. You may consider publishing a domain event asynchronously with the notification details (e.g. whom the notification is intended to) the notification sender needs. A domain service can listen to those notification domain events and call the PushNotificationSender (which you rightly pointed out is an infrastructure layer concern) with parameters extracted from the domain event. Having notification in a separate transaction has an additional benefit of imposing retry operations whose success is unceration and would block the main business transaction unnecessarily.

    There is also a feature request that a PushNotification can be sent on a certain date.

    If I got you right, you mean sending some notifications on a certain date instead of immediately. In that case, the domain service can do the persisting with scheduled date for you instead of your current application service. Moreover, the domain service may put the notification date if it is uniform over all users or the domain event may carry the date with it if it varies from user to user.