Validazione e persistenza dei dati in un modello di dominio

5

Il mio (primo e attuale) posto di lavoro (un negozio .NET) soffre di una sovrabbondanza di modelli di dominio anemico , nella misura in cui non so davvero come la convalida e la persistenza dei dati debbano essere gestite in un modello di dominio appropriato.

Persistenza dei dati

Un'opzione sarebbe quella di dare al modello di dominio un modo per fare la stessa persistenza. Ad esempio, potresti iniettare un IFooRepository tramite un'iniezione del costruttore e farlo risolvere da un contenitore IoC per assicurarti non creare una dipendenza da esso (à la architettura cipolla ). Ma non sono sicuro che il codice che utilizza il modello di dominio debba essere responsabile della chiamata di metodi per salvare i dati, ecc. O se debba essere eseguito implicitamente dietro le quinte su un thread in background. Forse questo rompe quella purezza del modello di dominio ed è più simile al modello record attivo .

L'altra opzione che vedo è non legare il modello di dominio alla persistenza dei dati e invece avere un livello di servizio responsabile di questo aspetto.

Quali sono le migliori pratiche per la persistenza dei dati nel modello del modello di dominio?

Validation

Un altro problema che non so come risolvere con un modello di dominio appropriato è come indicare all'interfaccia utente perché lo stato del modello corrente non è valido senza l'accoppiamento (o almeno il catering) del UI. Ad esempio, supponiamo di avere un modulo che un utente compila con vari campi. Vogliamo convalidare quell'input e, se qualcosa non va, indicare un errore su quel campo specifico con un messaggio.

Come gestiremo la convalida con quel livello di granularità senza aggiungere una significativa complessità al modello di dominio, o facendo hack-ish cose con tipicità (come lanciare un'eccezione di validazione con il nome della proprietà e un messaggio)?

    
posta Jeff Bridgman 27.09.2013 - 18:53
fonte

2 risposte

4

Potrei sbagliarmi nella mia comprensione, ma credo che tu stia cercando di ridisegnare il tuo modello di dominio in modo che non sia pieno di anemia . Un paio di libri davvero eccezionali sull'argomento sono:

  • Martin Fowler - Modelli di architettura delle applicazioni aziendali
  • Eric Evans: design basato sul dominio: affrontare la complessità nel cuore del software
  • Vaughn Vernon: implementazione del Domain Driven Design

Hanno molti contenuti che rispondono ad alcune domande sul tuo obiettivo. Uno dei quali è:

A rich Domain Model can look different from the database design, with inheritance, strategies, and other Gang of Four patterns, and complex webs of small interconnected objects. A rich Domain model is better for more complex logic, but is harder to map to the database.

A simple Domain Model can use Active Record, whereas a rich Domain Model requires a Data Mapper. Since the behavior of the business subject to alot of change, it's important to be able to modify, build, and test this layer easily.

Questo è un estratto di Fowler. Entrerà nei dettagli sul modello anche come modelli anemici e gonfiati. La portata della domanda mi sembra abbastanza grande; quindi non sono sicuro di poter approfondire. Quei libri dovrebbero indicarti la giusta direzione; ti consentirà inoltre di valutare il tuo progetto corrente e la sua implementazione per renderlo rapidamente più rapido.

Da una comprensione relativamente di base:

Dovresti essere in grado di astrarre il tuo modello, che consentirà una breve sovrapposizione di UI e Accesso ai dati nel tuo modello di dominio . Altrimenti, il modello dovrebbe consentire un'implementazione chiara, pulita e concisa che aiuterà a separare la responsabilità.

Scusa se non potrei esserti di più aiuto.

    
risposta data 27.09.2013 - 19:18
fonte
4

La domanda sorge da cosa sta usando la tua UI per ottenere i dati e come invia i dati da mantenere. Ho paura, dal momento che hai menzionato che non hai un livello di servizio e soffri nel trovare il posto giusto per la convalida, che l'interfaccia utente funzioni direttamente con le tue classi di dominio. Questa potrebbe essere la strada da percorrere, tuttavia non sembra un'applicazione molto complessa e puoi eseguire operazioni di persistenza e query direttamente nel codice dell'interfaccia utente. Puoi controllare i post di Ayende Rahien e molti altri che parlano di come eliminare i repository. In scenari relativamente semplici, ORM è in grado di fornire un isolamento sufficiente del modello di dominio dalla persistenza stessa. Inoltre è discutibile se i moderni ORM possano essere visti come DAL. Guarda NHibernate, può fare molto di più che mappare semplici tabelle a classi semplici. E se guardi i tuoi repository potresti trovare una serie di metodi chiamati GetByThis e GetByThat, che generano una semplice query all'ORM (se ne usi uno ovviamente) e giochi solo a uno stupido ruolo di astrazione non necessaria per dare un'impressione che tu fai DDD.

Riguardo al tuo commento su "non creare" dipendenze iniettando repository - invertirai il controllo ma avrai dipendenza non appena usi l'istanza della classe repository nel tuo oggetto dominio. Non importa come ci arrivi. Quindi questa è la scelta peggiore di tutti.

Alla tua domanda di convalida ti consiglierei di esaminare da vicino la convalida in quanto tale e decidere quale convalida è specifica del dominio e quale è più specifica l'immissione di dati. La convalida della voce di dati come i campi obbligatori non deve essere controllata dal modello di dominio. È un lavoro semplice e lo strato dell'interfaccia utente è perfettamente in grado di farlo. Inoltre, la maggior parte delle interfacce utente moderne è in grado di eseguire questa convalida molto facilmente. Tuttavia, devi trovare un modo per informare la tua interfaccia utente delle regole di immissione dei dati (tornerò di seguito). Il modello di dominio deve eseguire una convalida più orientata al business, come se esistesse già un cliente con tale nome. Ma tu, ancora una volta, non puoi farlo all'interno della tua classe di dominio poiché non sei in grado di interrogare i dati esistenti da lì perché non è responsabilità dell'oggetto dominio prendersi cura di qualcosa al di fuori del proprio aggregato.

Quindi, se vuoi andare per affrontare il viaggio DDD ti consiglierei di guardare al principio CQRS. Spesso è legato al sourcing di eventi, ma puoi semplicemente saltarlo. Concentrati su questo scenario, quando usi RDBMS con o senza ORM o NoSQL per la persistenza:

  • Crea modelli di input e visualizza modelli che possono essere utilizzati esclusivamente dall'interfaccia utente.
  • Decora i tuoi modelli di input con attributi di dati per la convalida sul lato client.
  • Invia comandi dall'interfaccia utente al tuo back-end per eseguire la convalida e la persistenza dell'attività.
  • Invia query al tuo back-end dall'interfaccia utente per visualizzare i dati. I dati restituiti devono essere inseriti nei modelli di visualizzazione.
  • Utilizza gli eventi di dominio per comunicare tra diversi contesti limitati

Non richiede necessariamente che la logica di back-end sia inserita in un application server (sebbene sia molto desiderabile abilitare l'uso di più UI con lo stesso back-end). Puoi utilizzare gli eventi in memoria per inviare comandi e query.

Ma ancora una volta, guarda cosa hai veramente bisogno, non cercare di sovvertire le astrazioni solo perché il libro dice così. Ricorda che molto spesso le astrazioni vengono messe in atto solo perché qualcuno ha sentito che questa è una buona cosa. I repository sono un classico esempio, quando la gente dice che rende ignorante la persistenza del proprio sistema e può cambiare il suo ORM ma in realtà nessuno lo fa. Quando viene modificato ORM significa riprogettazione quasi completa e gli archivi vengono scartati altrettanto bene insieme a tutti gli altri codici.

    
risposta data 10.10.2013 - 23:00
fonte