18

Martin Fowler considera il modello di dominio anemico come anti-pattern.Rich Domain Model e ORM

Anche il rollover del modello di persistenza come modello di dominio sembra gravemente disattivato a causa di Object Relational Impedence Missmatch. Per motivi di persistenza e normalizzazione, tendiamo a suddividere le classi in minuscoli pezzi molto piccoli, i metodi di schiaffo in cima a queste classi sono stupidi. Inoltre, la persistenza raramente cambia, ma la logica di business cambia un po '.

Quindi abbiamo bisogno di un DomainModel che si basa sul modello di persistenza (invece di essere uno e lo stesso). Questo modello di dominio conterrà quindi proprietà e metodi della logica di business.

Ma ora questi modelli di dominio sono ancora dietro il servizio e per poterli esporre al mondo esterno è necessario convertirli in DTO.

Stiamo facendo mappature così manny qui.

  1. Persistenza al Domain Model
  2. Per convertire Domain Model in DTOs per passare insieme tra i servizi

E non finisce qui, dal momento che il DTO può avere bisogno di essere mappati nel ViewModel.

Tutto ciò e il problema della duplicazione della logica di convalida non vanno ancora a buon fine, perché il client richiede la convalida in tempo reale. ViewModel non sa nulla sulla validazione, quindi in una SPA, ad esempio, sei costretto a riscrivere la logica di convalida di nuovo, sul lato client (solitamente in javascript).

Anche i servizi sono per natura senza stato (messaggio o RPC orientato), quindi stiamo eseguendo tutte queste mappature, tra Persistenza, OO e ritorno a Procedural, a quali vantaggi? Come giustificheresti il ​​costo in termini pratici della maggior parte del budget IT?

Ho capito come avere DDD completo, con Radici aggregate, Modelli di dominio ecc. Sarebbe "bello" ma come si può giustificare il costo e l'impatto sulla produttività di sviluppo?

antipattern (o antipattern) è un modello utilizzato nella vita sociale o di lavoro operazioni o ingegneria del software che può essere comunemente usato, ma è inefficace e/o controproducenti nella pratica

E se sì , DDD e Rich Domain Model non rientrano nella definizione di anti-pattern sopra rispetto al modello di dominio "Lean". Scusa, disprezzo la parola caricata, "Anemico".

Mantenendo il modello di dominio, "Lean" si consente effettivamente di essere condiviso senza violare il "principio di dipendenza astratta", "non ripetere te stesso" e il processo di mappatura dei dati che richiede tempo, noioso e soggetto a errori carrier to another, e qualunque sia l'Unit Test che si aggiunge a quello (a meno che non stiate pensando di fare una mappatura senza test unitari e sperare per il meglio).

risposta

7

Sembra che tu stia mescolando molti concetti, incolpando l'approccio del modello di dominio ricco per cose di cui non è direttamente responsabile.

  • Rich modello di dominio è ortogonale ad architettura a strati, soprattutto avendo un ricco modello di dominio non dettare il numero di strati che hai, quali strutture di dati dovrebbero essere scambiati tra questi strati e come devono essere mappati.

  • Il modello di dominio ricco è ortogonale alla convalida e non dice nulla sulla necessità di controllo sul lato client oltre alla convalida del back-end.

In altre parole, rendendo il vostro modello di dominio anemico con tutta la logica di business nel settore dei servizi non sarà necessariamente salvare da scrivere un sacco di testo standard DTO codice di mappatura, né sarà rimuovere la necessità di lato client "doppio controllo "(che è, tra l'altro, una best practice comunemente accettata).

Questo non significa che il tuo punto sul costo e il peso di un'architettura a più livelli a pieno titolo non è valido. Potresti trovare interesse in questo post di Mark Seemann discutendo preoccupazioni simili: http://blog.ploeh.dk/2012/02/09/IsLayeringWorthTheMapping.aspx

+0

Penso che l'articolo che hai collegato riassuma il dilemma. Tranne che non credo nell'invio di Domain Model attraverso il filo, sembra il lavoro di un DTO. Non ha senso avere un comportamento sul DTO e esporlo al cliente. Quindi per me l'architettura è solo "fattibile" con un altro strato di astrazione e mappatura oltre ai 3 che ha menzionato. E questo è MOLTO di mappatura! Non è corretto dire che l'altro modo di introdurre la preoccupazione dell'interfaccia utente per il dominio per il riutilizzo. Penso che ci sia un mezzo "felice" tra i 2 estremi del pollar. – Alwyn

+0

"Sposta meno dati in giro e le cose probabilmente diventeranno più semplici" - La sua conclusione alla fine dell'articolo, che suona come Lean Model per me. – Alwyn

+0

"Non ha senso avere un comportamento sul DTO ed esporlo al client" - ora capisco la connessione che stai facendo tra il modello di dominio ricco/anemico e il layering. Sottintendi che gli oggetti del dominio dovrebbero essere rimossi dalla maggior parte della logica di business possibile nel tentativo di inviarli direttamente al livello dell'interfaccia utente senza la necessità di DTO? O è qualcos'altro a cui ti riferisci come "Lean Model"? – guillaume31

2

Prima di tutto non penso che si possa facilmente evitare di duplicare la logica di convalida sul client e sul server. Questo non è limitato al DDD, però. Ci sono alcuni meccanismi per alleviare il dolore, ma sarà sempre necessario uno sforzo.

L'altra parte è tutta questa mappatura :)

Quello che state facendo è effettivamente usando per effettuare letture. Potresti pensare di aver bisogno di leggere la tua entità per modificarla. Questo è vero se si eseguono operazioni basate sull'entità (entità probabilmente più in termini di DB qui - intero record) invece di operazioni basate sull'attività sul proprio oggetto entità. Un esempio stupido potrebbe essere che un cliente telefona al call center per cambiare un indirizzo. L'operatore richiama il record del cliente e modifica l'indirizzo. Questo è basato sull'entità e porta a problemi tipici w.r.t. concorrenza dal momento che 2 azioni possono essere eseguite sullo stesso record (comunque improbabile). Questo è un approccio molto tradizionale al design UX: "Modifica il record".

Contrastare questo con un pulsante sullo schermo che dice: "modificare un indirizzo". Si modifica solo l'indirizzo sul record e anche se questo sembra la stessa cosa, è davvero molto diverso. Le possibilità di 2 operazioni che cambiano lo stesso indirizzo sono piuttosto più sottili di quelle di cambiare lo stesso record. Se è richiesto il controllo della concorrenza richiesto su questa parte.

Ora se uno non legge il dominio, cosa si legge. Da dove provengono i dati. È qui che entra in gioco CQRS (Comando/Query Responsibility Segregation). In passato è stato confuso/combinato con Event Sourcing ma questo non è richiesto. È possibile creare un lato di query semplice per l'applicazione incentrata sulla restituzione dei dati necessari. In C# ho usato uno DataRow se si tratta di una singola istanza, uno DataTable per più istanze e un DTO personalizzato per qualcosa di più complesso. Ci può essere un modo in cui si può anche farla franca con i tipi anonimi (non indagare ancora su questo).

Pertanto:

Domain Model = operazioni/calcolo/scrivere Query Servizi = leggere

ci sono situazioni in cui si può ottenere via con semplicemente caricando un'entità/aggregazione come ad esempio in un'applicazione web dal momento che è a conoscenza (o potrebbe essere a conoscenza) del proprio modello di dominio ma un client intelligente sarebbe un po 'anti-modello.

La giustificazione è piuttosto complicata ma si riduce alla manutenzione. Se il tuo approccio non alleggerisce il tuo onere di manutenzione, è probabile che qualcosa non sia applicato correttamente e necessiti di qualche refactoring.

DDD non riguarda solo l'implementazione tecnica, sebbene faccia un lungo cammino, spingendo verso la giusta modellazione OO. Immagino che le altre idee vengano inserite nel software in ogni caso, quindi il software sembra essere al centro dell'attenzione. Vogliamo tutti vedere dove la gomma incontra la strada.

Come la maggior parte le cose DDD può essere fatto male :)

4

tl; dr Il modello di dominio non è ben definita, è probabilmente progettato con un approccio centrato sul db in mente.

Lo scopo principale di DDD è quello di modellare in codice i concetti e i processi aziendali. Dubito davvero che i concetti e i processi aziendali siano solo delle proprietà. Ma se sono davvero sì, il modello di dominio può essere lo stesso del modello di persistenza, in modo da non dover eseguire alcuna mappatura.

Il modello di persistenza modella come viene memorizzato lo stato dell'oggetto . Se non si è nel dominio dei database, il modello di dominio e persistenza non può avere lo stesso scopo.Uno dei più grandi errori che vedo con DDD è pensare al modello di dominio come se fosse ancora guidato da dati. In DDD non hai un database concreto. Hai repository. Non ci sono relazioni uno-a-molti, molti-a-molti ecc. Non ci sono tabelle e nessuna riga. Ci sono solo oggetti che cercano di rappresentare il Dominio il più accurato possibile.

In parole povere, il dominio si preoccupa della modellazione del comportamento aziendale mentre a Persistenza si preoccupa di memorizzare lo stato dell'oggetto. Vedo qui due responsabilità diverse.

Informazioni sulla convalida, sono disponibili 2 tipi: convalida dei dati di input formato e quindi convalida di altre regole aziendali in base a ciò che si modifica in uno stato dell'oggetto.

Circa la duplicazione, penso che tu ti stia riferendo al formato di input ma come @EbenRoux ha detto che ci sono meccanismi che possono aiutare con quello. In asp.net mvc la maggior parte di quelle regole di validazione include anche la versione js.

Lascia che ti dica un piccolo segreto con i servizi. Mentre la loro interfaccia può essere definita nel dominio, la loro implementazione può essere inserita nel livello di persistenza, consentendo loro di lavorare direttamente con lo spazio di archiviazione. E poiché il resto dell'app utilizza il servizio nella sua forma astratta (l'interfaccia), solo il contenitore DI conoscerà il segreto sporco.

DDD non significa essere cool, si tratta di progettare un'applicazione in base al dominio. Scommetto che pochi sviluppano un'applicazione per il solo scopo di essere un'interfaccia utente per il db. La maggioranza mira a fornire un servizio con il proprio software, per costruire un prodotto virtuale che risolva un problema. È logico che il design dell'app sia guidato sul problema che si desidera risolvere e non sugli strumenti tecnici che si sono appena verificati.

Come suona, vuoi una casa di mattoni ma il costruttore dice: "Scusa ma la mia sega funziona solo con il legno". Bene, non utilizzare una sega, utilizzare un altro strumento che può aiutare a tagliare un mattone. Gli strumenti devono essere adattati al problema, non viceversa.

+0

Quindi il dominio nel DDD è statico o stateless? Il dominio dovrebbe esporre le sue proprietà? In caso contrario, quale sarebbe il parametro e i tipi di ritorno dei metodi di dominio ?, DTO? Se espone le sue proprietà come è meglio del Modello Anemico? – Alwyn

+0

Il dominio riguarda principalmente il comportamento.Ovviamente, un oggetto dominio può avere proprietà ma non ha solo proprietà. E quelle proprietà non sono solo primitive. Come si salva IFormattedContent direttamente in una colonna? Sto iniziando a pensare che il tuo attuale dominio sia solo una raccolta di codice procedurale guidato dai dati che usa solo termini DDD. – MikeSW

+0

@Alwyn parte del dominio è stateful - è proprio il punto delle Entità avere uno stato così come un'identità in modo da poter tenere traccia delle modifiche in quello stato. Gli oggetti valore d'altra parte non sono stateful (congelati nello stato, se lo si desidera). I servizi di dominio dovrebbero essere chiaramente senza stato. – guillaume31