vendredi 9 avril 2021

DDD - Who has the responsbility of aggregate “deletion”?

Suppose we have a system that contains only three aggregates Employee, Organization and QueueNode. Each has it's own behaviors and boundary so they cannot be merged into one aggregate.

So now I have the requirement

Authorized employees should be able to delete queues, keeping a log of when and who did it.

What would be your solution to tackle this problem ? I will discuss my findings in the following.

Option 1 Using a domain service

class EmployeeDeleteQueueNodeService{
    private QueueNodeRepository nodeRepo; // This will be injected in the constructor

    void execute(Employee employee, QueueNode node){
        node.raiseEvent(new QueueNodeDeleted(employee, node));
        this.nodeRepo.delete(node);
    }
}

And then inject this service to the application service carrying out the use case of deleting the QueueNode.

Option 2 Injecting the QueueNodeRepository to a method of the Employee aggregate.

class Employee{
    /// Constructor, unrelated business methods

    void deleteQueueNode(QueueNode node, QueueNodeRepository nodeRepository){
        node.raiseEvent(new QueueNodeDeleted(this, node));
        nodeRepository.delete(node);
    }
}

This creates more verbose code which is always better. My only concern about this is that I'm passing the repository to the Employee method which seems to have some debate about, personally I like that approach.

Option 3 Same as the above but execute the deletion after the event fires

class Employee{
    /// Constructor, unrelated business methods

    void deleteQueueNode(QueueNode node, QueueNodeRepository nodeRepository){
        node.raiseEvent(new QueueNodeDeleted(this, node));
    }
}

// Somewhere else in the Application layer
class QueueNodeDeletionListener {
    private QueueNodeRepository nodeRepo; // This will be injected in the constructor

    void notify(QueueNodeDeleted event){
         this.nodeRepo.delete(event.getQueueNode());
    }
}

I think the "strict" DDD approach would recommend this especially with an event sourcing architecture (which I'm not using). However to me it feels wrong for the method inside the Employee to only raise an event on another aggregate (may be totally wrong, this is just my gut feeling).

If this is the correct solution, where should the event listener live ? should it be registered in the application layer and notified after the first use case is carried out or should both the event publishing and deletion be carried out in one transaction (a Domain layer listener) ? Let me know what you think.

Also I've read from multiple sources that usually the concept of "Delete" is not much present in the business model, however in my specific case I'm confident it is.

Aucun commentaire:

Enregistrer un commentaire