1
votes

We have a aggregate root as follows.

@AggregateRoot
class Document {
    DocumentId id;
}

The problem statement given by the client is "A document can have multiple document as attachments"

So refactoring the model will lead to

//Design One
@AggregateRoot
class Document {
    DocumentId id;

    //Since Document is an aggregate root it is referenced by its id only
    Set<DocumentId> attachments;

    attach(Document doc);
    detach(Document doc);
}

But this model alone won't be sufficient as the client wants to store some meta information about the attachment, like who attached it and when it was attached. This will lead to creation of another class.

class Attachment {
   DocumentId mainDocument;
   DocumentId attachedDocument;
   Date attachedOn;
   UserId attachedBy;

   //no operation
} 

and we could again refactor the Document model as below

//Design Two
@AggregateRoot
class Document {
    DocumentId id;
    Set<Attachment> attachments;

    attach(Document doc);
    detach(Document doc);
}

The different possibilities of modeling that I could think of are given below.

  1. If I go with design one then I could model Attachment class as an aggregate root and use Events to create them whenever a Document is attached. But it doesn't look like an aggregate root.
  2. If I choose design two then Attachment class could be modeled as a value object or an entity.
  3. Or If I use CQRS, I could go with design one and model Attachment as a query model and populate it using Events.

So, which is the right way to model this scenario? Is there any other way to model other what I have mentioned?

1

1 Answers

1
votes

You might find in the long term that passing values, rather than entities, makes your code easier to manage. If attach/detach don't care about the entire document, then just pass in the bits they do care about (aka Interface Segregation Principle).

attach(DocumentId);
detach(DocumentId);

this model alone won't be sufficient as the client wants to store some meta information about the attachment, like who attached it and when it was attached.

Yes, that makes a lot of sense.

which is the right way to model this scenario?

Not enough information provided (the polite way of saying "it depends".)

Aggregate boundaries are usually discovered by looking at behaviors, rather than at structures or relationships. Is the attachment relationship just an immutable value that you can add/remove, or is it an entity with an internal state that changes over time? If you change an attachment, what other information do you need, and so on.