DDD Entity and EntityType reference

I'm learning DDD and here is a problem I faced. I have two Aggregates (simplified):

class NoteType : AggregateRoot {
  int noteTypeId
  string name
  string fields[]
  ... code omitted ...
}

class Note : AggregateRoot {
  int noteId
  int noteTypeId
  map<str, str> fieldValues

  setFieldValue(fieldName, fieldValue) {
    // I want to check that fieldName is present in Notes.fields
    // and later fieldValues[field.name] = fieldValue
  }
  ... code omitted ...
}

I've heard that aggregates should reference to each other by ID's only. It this case I can't access NoteType.fields. I found several ways to do so, but not sure which one is better:

  1. Pass NoteType instance into the Note model via constructor (do not reference by ID)
  2. Use repository in setFieldValue to load NoteType
  3. Use service which will do the check (this may cause all the Note logic to be implemented in this service, since Note highly dependent on NoteType)

What do you suggest?

Upvotes: 0

Views: 60

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57307

What do you suggest?

Pass the information that the aggregate needs to the aggregate when it needs it.

  setFieldValue(fieldName, fieldValue, noteType) {
    // Now you have the data that you need to verify the noteType.fields
  }

Sometimes, if you can't tell from outside the aggregate what information you need, then you instead pass the capability to look up that information

  setFieldValue(fieldName, fieldValue, notes) {
    // Use the provided capability to get what you need
    noteType = notes.get(this.noteTypeId)

    // the do the useful work
    this.setFieldValue(fieldName, fieldValue, noteType)
  }

Of course, if the only thing you need is the fields, then you might prefer to work only with that property:

setFieldValue(fieldName, fieldValue, fields)

Design is what we do, when we want to get more of what we want than we'd get by just doing it. -- Ruth Malan

In Domain Driven Design, a common "what we want" is to have the "business logic", meaning our implementation of the policies of information change that are important to our business, separated from the "plumbing" that describes how to read and store that information.

Upvotes: 1

Related Questions