Approccio DDD alle operazioni CRUD di base in un'applicazione complessa incentrata sul dominio

8

La mia azienda sta riscrivendo da zero la nostra applicazione web. È una grande applicazione di livello enterprise con un dominio complesso nel settore finanziario.

Stiamo utilizzando un ORM (Entity framework) per la persistenza.

In sostanza, metà della nostra applicazione si concentra sulla raccolta di dati grezzi da parte dell'utente, la memorizzazione, e quindi l'altra metà dell'applicazione che contiene la maggior parte della nostra logica di dominio reale prende quei dati grezzi per creare la nostra immagine di dominio che differisce notevolmente da quegli input raw originali e li passa in un motore di calcolo, esegue calc, e sputa i risultati, che vengono poi mostrati all'utente.

In un approccio DDD che usa i livelli, sembra che le operazioni CRUD passino attraverso il livello del dominio. ma almeno nel nostro caso, questo non sembra avere senso.

Quando un utente accede alla schermata di modifica per modificare un account di investimento, ad esempio, i campi sullo schermo sono i campi esatti memorizzati nel database, non la rappresentazione del dominio utilizzata in seguito per i calcoli. Quindi, perché dovrei caricare la rappresentazione del dominio dell'account di investimento quando la schermata di modifica richiede la rappresentazione del database (input raw)?

Dopo che l'utente fa clic su "Fatto" nella schermata dell'account di investimento e viene eseguito un POST sul controller, il controller dispone ora di una rappresentazione esatta del database dell'account di investimento che deve essere salvata. Ma per qualche ragione, dovrei caricare la rappresentazione del dominio per apportare modifiche invece di mappare semplicemente il modello del controllore direttamente al modello di database (Entity framework model)?

Quindi in sostanza sto mappando un modello di dati al modello di dominio, solo così può quindi essere mappato sul modello di dati per persistere. Come ha senso?

    
posta wired_in 12.08.2017 - 05:50
fonte

4 risposte

7

Ok immagina di implementare la pagina di creazione dell'account mappando il modulo direttamente su un oggetto EF che viene poi salvato nel db.

Supponiamo inoltre che il database abbia varie restrizioni che impediscono l'inserimento di dati completamente errati. Gli account hanno sempre clienti ecc.

Tutto sembra funzionare bene. Ma poi l'azienda stabilisce una nuova regola.

  • Gli account creati il giovedì ricevono un tasso di interesse bonus del 2%. (supponiamo che il tasso di interesse sia uno dei campi dell'account)

Ora devi mettere questa logica da qualche parte e non hai un oggetto dominio per inserirla.

DDD presuppone che avrai sempre questo tipo di regole e probabilmente lo farai. La creazione di un account deve avere vari controlli, un registro di controllo, ecc. Non sarà solo "scrivere una riga sul db"

Pianifica il tuo dominio presumendo che non vi siano persistenza o controller MVC con logica aggiuntiva. Assicurati di acquisire tutti dei requisiti e sono tutti nel modello di dominio.

    
risposta data 12.08.2017 - 07:43
fonte
4

How does that make sense?

Risposta breve: non .

Risposta più lunga: i modelli pesanti per lo sviluppo di un modello di dominio non si applicano a quelle parti della soluzione che sono solo un database.

Udi Dahan ha avuto un'osservazione interessante che può aiutare a chiarire questo

Dahan considers that a service has to have both some sort of functionality and some data. If it does not have data, then it is just a function. If all that it does is performing CRUD operations on data, then it is database.

Il punto del modello di dominio, dopo tutto, è quello di garantire che tutti gli aggiornamenti dei dati mantengano invariata l'attuale business. O, per dirla in altro modo, il modello di dominio è responsabile di garantire che il database che agisce come sistema di registrazione sia corretto.

Quando hai a che fare con un sistema CRUD, di solito non sei il sistema di registrazione per i dati. mondo reale è il libro dei record e il tuo database è solo una rappresentazione locale del mondo reale.

Ad esempio, la maggior parte delle informazioni che appaiono in un profilo utente, come un indirizzo email o un numero di identificazione rilasciato dal governo, hanno una fonte di verità che vive al di fuori della tua attività: è quella di qualcun altro amministratore della posta che assegna e revoca gli indirizzi email, non la tua app. È il governo che assegna gli SSN, non la tua app.

Quindi normalmente non eseguirai alcuna convalida del dominio sui dati che ti arrivano dal mondo esterno; potrebbe essere necessario verificare che i dati siano ben formati e correttamente disinfettati ; ma non i tuoi dati: il tuo modello di dominio non ottiene il veto.

In a DDD approach using layers, it seems like CRUD operations go through the domain layer. but at least in our case, this doesn't seem to make sense.

Esatto per il caso dove il database è il libro del record .

Ouarzy lo mise in questo modo .

Working on lots of legacy code though, I observe common mistakes to identify what is inside the domain, and what is outside.

An application can be considered CRUD only if there is no business logic around the data model. Even in this (rare) case, your data model is not your domain model. It just means that, as no business logics is involved, we don’t need any abstraction to manage it, and thus we have no domain model.

Utilizziamo il modello di dominio per gestire i dati che appartengono al dominio; i dati dall'esterno del dominio sono già gestiti da qualche altra parte - stiamo solo mettendo in cache una copia.

Greg Young utilizza sistemi di magazzino come illustrazione principale delle soluzioni in cui il libro dei record è da qualche altra parte (es .: il pavimento del magazzino). L'implementazione che descrive è molto simile alla tua: un database logico per catturare i messaggi ricevuti dal magazzino e quindi un database logico separato che memorizza le conclusioni tratte dall'analisi di quei messaggi.

So maybe we have two bounded contexts here? Each with a different model for an investment account

Forse. Sarei riluttante a taggarlo come un contesto limitato, perché non è chiaro quale altro bagaglio lo accompagni. Potrebbe essere che tu abbia due contesti, potrebbe essere un contesto con sottili differenze nella lingua ubiquitaria che non hai ancora raccolto.

Possibile prova del nove: quanti esperti di domini hai bisogno di due esperti di dominio per coprire questo spettro, o solo uno che parli dei componenti in modi diversi. Fondamentalmente, potresti essere in grado di indovinare quanti contesti limitati hai funzionando all'indietro con la legge di Conway.

Se consideri che i contesti limitati siano allineati con i servizi, potrebbe essere più semplice: dovresti essere in grado di distribuire queste due parti di funzionalità in modo indipendente? Sì suggerisce due contesti limitati; ma se hanno bisogno di essere sincronizzati, forse è solo uno.

    
risposta data 12.08.2017 - 15:47
fonte
1

Nel tuo dominio non dovresti sapere che il database esiste anche.

Il tuo dominio riguarda le regole aziendali. Le cose che devono sopravvivere quando la società che ha creato il tuo database ha cessato l'attività. Cioè, se vuoi che la tua azienda sopravviva. È davvero bello quando a quelle regole non interessa che tu abbia cambiato la modalità di persistenza dei dati.

I dettagli del database esistono e devono essere gestiti. Dovrebbero vivere da qualche altra parte. Mettili attraverso un confine. Controlla attentamente come comunichi attraverso quel confine o non sia un limite.

Uncle Bob ha questo da dire su cosa mettere i tuoi dati in:

Typically the data that crosses the boundaries is simple data structures. You can use basic structs or simple Data Transfer objects if you like. Or the data can simply be arguments in function calls. Or you can pack it into a hashmap, or construct it into an object.

The important thing is that isolated, simple, data structures are passed across the boundaries. We don’t want to cheat and pass Entities or Database rows. We don’t want the data structures to have any kind of dependency that violates The Dependency Rule.

[…] when we pass data across a boundary, it is always in the form that is most convenient for the inner circle.

Clean Architecture

Spiega anche come i tuoi strati esterni dovrebbero essere plugin per i tuoi livelli interni in modo che i livelli interni non sappiano nemmeno che esistono strati esterni.

Segui qualcosa del genere e avrai un bel posto per ignorare il database in cui puoi preoccuparti delle regole di convalida dell'input, regole che l'input deve essere mantenuto in qualche modo, regole per eseguire i calcoli, regole per inviare quei risultati a qualsiasi output. In realtà è più facile leggere questo tipo di codice.

È così o decidi che il tuo dominio è in realtà solo per manipolare il database. In tal caso la lingua del tuo dominio è SQL. Se così va bene, non aspettarti che la tua implementazione delle regole aziendali sopravviva a un cambiamento di persistenza. Finirai per doverli riscrivere completamente.

    
risposta data 12.08.2017 - 06:30
fonte
1

Applicazione della teoria del DDD:

Ci sono due contesti limitati in quel dominio:

  • I calcoli del conto di investimento. Il modello matematico dell'account di investimento è un elemento, forse un aggregato.
  • Core Finance. L'account di investimento del cliente è una delle Entità.

Ogni Contesto Limitato può avere una diversa progettazione architettonica.

Esempio:

L'account di investimento del cliente è un'entità (forse un aggregato, dipende dal dominio) e la persistenza dei dati viene effettuata tramite il repository dell'entità (RDB o altro tipo di DB come un database OO).

Non esiste un approccio DDD alle operazioni CRUD. Per avere un campo DB legato ai dati di un oggetto si rompono i principi di progettazione.

    
risposta data 12.11.2018 - 04:39
fonte