I had a few questions around value objects in DDD.
I had a class
ReportDefinition (basically a schema for a specific report that users can create) with the following properties (in Java):
UUID id; UUID ownerId; UUID organizationId; ReportDefinitionName name; ReportTitle reportTitle; ReportDescription reportDescription; Instant createdAt; Instant lastModifiedAt;
As you can see, there everything is a value object. So far, all the value objects in the systems have been wrappers around a single primitive (Strings for the most part). i.e. to get the report title as a string, I would do
Yesterday I needed to add another property,
ReferenceType. I came to the realization that
reportDescription and the
referenceType should probably be grouped together another value object,
ReportDetails. I can see the need for
referenceType to still be a value object, but not sure if I should change
description to simple strings within the
At the moment,
ReportDescription do some simple validations (i.e. report title must be between 1 and 60 characters, etc), but that's about it. If I made them strings, I could still do the basic validation checks within
Another question that arises is whether this might lead to violation of the law of demeter. i.e. it's like that the application layer will need to call
reportDefinition.reportDetails.title().title() which is starting to get a bit crazy.
And finally, given that value objects should be immutable, I'm guessing if I wanted to update the report details, I might need methods like
ReportDetails updateTitle(title) that returns a new instance of
ReportDefinition. I was wondering who should actually call that method? i.e. should it be a protected method within
ReportDetails and called via a
void updateTitle() method on the
ReportDefinition? Or is it fine for the application layer to call
reportDetails.updateTitle() and then pass the result to an
updateReportDetails() method on
Part of the reason why it made sense to split them out into a seperate object was because a
Report will need the information in
ReportDetails when being created (whereas the rest of the information in
ReportDefinition is irrelevant and deals with other concerns).
The immutability is an artefact of following DDD and not wanting consumers of the class to modify
ReportDetails simply on account of having a reference to it. A business case is that
ReportDetails can only be change when
ReportDefinition is in a draft state (not shown above) whereas the other information in
ReportDefinition can always be changed.