Dove mettere il comportamento di DTO? Codice pulito struttura oggetto vs dati

0

La domanda simile è stata pubblicata qui link

Non riesco ancora a trovare una risposta, sono confuso!

Ho letto anche il libro "codice pulito". In alcune parti non si deve mescolare la struttura dati / oggetto, se la struttura dei dati è priva di comportamento o un oggetto con un comportamento.

Nella mia applicazione abbiamo oggetti di trasferimento dati che trasportano dati da servizi esterni. Questi DTO hanno solo accessor e mutatori di dati. Quindi li stavo considerando come tipo di struttura dei dati.

Tuttavia Robert Martin sta dicendo nel suo libro che client.isMarried() è migliore di isMarried(client) Ho trovato questo logico come isMarried function usa gli attributi solo dalla classe client .. è più pulito.

In molte aree della mia applicazione abbiamo bisogno di un comportamento su alcuni DTOs. Sono confuso dove mettere questo comportamento. Abbiamo creato classi di Utils con logica aziendale come

ClientUtils { 

   boolean isMarried(Client client) { ...} 
   String getCompleteName(Client client) { ...} 

}

Questo dovrebbe andare al livello di servizio? anche se questi metodi non manipolano qualcos'altro oltre all'oggetto di input Non interagisce con un altro livello (DAL, servizi ..)

    
posta Mohamed Amine Mrad 01.06.2017 - 21:39
fonte

1 risposta

4

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.

    
risposta data 01.06.2017 - 22:30
fonte

Leggi altre domande sui tag