Ho avuto alcune domande sugli oggetti valore in DDD.
Ho avuto una classe ReportDefinition
(fondamentalmente uno schema per un report specifico che gli utenti possono creare) con le seguenti proprietà (in Java):
UUID id;
UUID ownerId;
UUID organizationId;
ReportDefinitionName name;
ReportTitle reportTitle;
ReportDescription reportDescription;
Instant createdAt;
Instant lastModifiedAt;
Come puoi vedere, lì tutto è un oggetto valore. Finora, tutti gli oggetti valore nei sistemi sono stati wrapper attorno a una singola primitiva (le stringhe per la maggior parte). Ad esempio, per ottenere il titolo del report come stringa, farei reportDefinition.reportTitle().title()
.
Ieri ho dovuto aggiungere un'altra proprietà, ReferenceType
. Sono giunto alla conclusione che reportTitle
, reportDescription
e referenceType
dovrebbero probabilmente essere raggruppati insieme con un altro oggetto valore, ReportDetails
. Riesco a vedere la necessità di referenceType
di essere ancora un oggetto valore, ma non sono sicuro se dovrei cambiare title
e description
in stringhe semplici all'interno di ReportDetails
?
Al momento, ReportTitle
e ReportDescription
eseguono alcune semplici convalide (cioè il titolo del report deve essere compreso tra 1 e 60 caratteri, ecc.), ma questo è tutto. Se li avessi creati, potrei comunque eseguire i controlli di convalida di base entro ReportDetails
.
Un'altra domanda che si pone è se questo potrebbe portare alla violazione della legge di Demeter. vale a dire che il livello dell'applicazione dovrà chiamare reportDefinition.reportDetails.title().title()
che sta iniziando a diventare un po 'pazzo.
E infine, dato che gli oggetti value dovrebbero essere immutabili, suppongo che se volessi aggiornare i dettagli del report, potrei aver bisogno di metodi come ReportDetails updateTitle(title)
che restituisca una nuova istanza di ReportDefinition
. Mi stavo chiedendo chi dovrebbe effettivamente chiamare quel metodo? vale a dire dovrebbe essere un metodo protetto in ReportDetails
e chiamato tramite un metodo void updateTitle()
su ReportDefinition
? Oppure va bene per il livello applicazione chiamare reportDetails.updateTitle()
e quindi passare il risultato a un metodo updateReportDetails()
su ReportDefinition
?
Parte del motivo per cui aveva senso dividerli in un oggetto separato era perché un Report
avrà bisogno delle informazioni in ReportDetails
quando viene creato (mentre il resto delle informazioni in ReportDefinition
è irrilevante e si occupa di altre preoccupazioni).
L'immutabilità è un artefatto di seguire DDD e non vuole che i consumatori della classe modifichino ReportDetails
semplicemente per avere un riferimento ad esso. Un caso aziendale è che ReportDetails
può essere modificato solo quando ReportDefinition
è in uno stato di bozza (non mostrato sopra) mentre le altre informazioni in ReportDefinition
possono sempre essere modificate.