I DTO non fanno parte del modello di dominio e non hanno alcun comportamento. Le DTO rappresentano le strutture di dati che vengono trasferite attraverso il limite del sistema, ad es. dati che sono serializzati per essere inviati attraverso una rete. Le DTO sono anche ideali per rappresentare i dati in entrata che potrebbero essere incoerenti, prima che vengano convalidati e tradotti nel tuo modello di dominio.
All'interno del modello di dominio, gli oggetti che rappresentano i concetti all'interno del dominio problematico in genere contengono la logica aziendale associata. La parte interessante non è il comportamento che interroga lo stato del modello, ma i metodi che modificano il modello, oltre ai semplici setter. Ciò può portare ad una mappatura molto elegante del dominio problematico nel tuo codice, in quanto il modello in pratica si gestisce da solo.
A volte non vogliamo farlo e mantenere la maggior parte dei comportamenti fuori dal modello immediato. Questo è chiamato un modello di dominio anemico ed è più procedurale rispetto alla tecnica di progettazione orientata agli oggetti. Come tale, è considerato un anti-modello da alcuni. Tuttavia, questo funziona molto bene se c'è molta logica aziendale che non appartiene chiaramente a un singolo oggetto del modello di dominio. Invece, possiamo strutturare la logica di business in base al caso d'uso. Ogni caso d'uso manipola quindi il modello di dominio. Lo svantaggio è che diventa più difficile mantenere il modello coerente.
Questi due approcci non sono esclusivi, ma sono una scala mobile. A un'estremità, tutto il comportamento è direttamente nel modello, all'altra il modello di dominio è costituito da record stupidi. Nel mezzo, il modello di dominio contiene operazioni generiche che assicurano la coerenza, ma la logica specializzata vive all'esterno nei servizi che orchestrano le modifiche al modello.
Nel tuo caso, un accessor isMarried()
non ha nulla a che fare con un DTO. Un DTO può semplicemente esporre i suoi dati. All'interno del tuo modello di dominio, sembra che un tale metodo appartenga chiaramente a qualche tipo di classe Person. Se stai introducendo le classi Util che prendono il nome da un'altra classe, è un chiaro segnale di avviso che il tuo progetto potrebbe essere disattivato: in molti casi quel comportamento dovrebbe essere parte della classe originale, altrimenti dovrebbe essere modellato separatamente in quanto non fa parte della classe dominio problema modellato.
Tuttavia, penso che un isMarried()
accessor sia un esempio debole di questo perché è fondamentalmente solo un getter, e un getter è fondamentalmente solo sintassi di fantasia per un campo. Come esempio diverso, consideriamo un'applicazione web che consente agli studenti di iscriversi alle lezioni. Se questo è direttamente parte del modello di dominio, vedremmo chiamate di metodi come student.enrolIn(lecture)
o lecture.enrol(student)
nel nostro codice. Ma a volte l'iscrizione non è semplice e ha regole aziendali complesse, ad es. come vengono assegnati posti limitati agli studenti che applicano. Se l'iscrizione è un intero processo a sé stante, potremmo voler modellare quel processo come un oggetto separato: lectureEnrolmentProcess.run(lecture, student)
. Tornando al tuo comportamento isMarried()
: poiché questo comportamento probabilmente non è un processo complesso con le sue preoccupazioni, non dovrebbe essere tenuto separato.
Quindi penso che ci dovrebbe essere un chiaro pregiudizio per mettere la maggior parte dei comportamenti direttamente nel modello, ma non dovremmo aver paura di estrarre qualsiasi comportamento che abbia una preoccupazione completamente diversa rispetto al concetto che viene modellato.