In DDD, come faccio a mantenere un polimorfismo contenente aggregato

6

Da qualche tempo sto sviluppando applicazioni secondo i principi della DDD, e, come molti, spesso mi imbatto in problemi quando si tratta di mantenere un aggregato.

Uno dei principali vantaggi del DDD è che mi consente di utilizzare tutta la potenza del design OO nel mio dominio - in quanto tale, voglio usare il polimorfismo e conformarmi al principio open-closed. Cioè Posso estendere la mia logica aggiungendo nuovi sottotipi senza richiedere modifiche ai supertipi.

Il problema si presenta quando si persiste. In qualche modo ho bisogno di appiattire questo dominio per una rappresentazione persistente, e successivamente di ripristinarlo. Come ottengo ciò, senza sporcare l'implementazione di Repository con instanceof (o equivalente nella lingua preferita) in tutto il luogo. Questo è generalmente considerato una cattiva forma, oltre a violare l'OCP, almeno nel repository stesso. Quando aggiungo un nuovo sottotipo, sono costretto ad aggiungere un caso nel repository.

C'è un modo elegante per gestirlo?

    
posta Joeri Hendrickx 06.12.2016 - 14:42
fonte

4 risposte

1

Uno dei modi è usare la riflessione. Durante l'avvio dell'applicazione, il repository ispezionerà la struttura delle entità del dominio e determinerà automaticamente il modello relazionale e la mappatura delle entità a questo modello relazionale. Questo è fondamentalmente ciò che possono fare gli ORM più moderni. Lo svantaggio di questo approccio è che è estremamente complicato da implementare per i casi non banali e una piccola modifica nel modello di dominio potrebbe portare a modelli relazionali drasticamente differenti, il che complica le migrazioni tra le versioni.

Oltre a questo, no, non c'è modo. Se il tuo repository dipende dal tuo modello di dominio, significa che il repository deve cambiare quando cambia il modello di dominio. Questa è la definizione di dipendenza. E l'OCP può funzionare davvero solo se le cose non dipendono l'una dall'altra.

Ma c'è un modo per rendere il cambiamento più facile e più sicuro. Perché l'utilizzo di instanceof è un problema? Non c'è niente di sbagliato nell'usarlo. Solo che se aggiungi un nuovo sottotipo, non sai dove devi estendere il codice per supportare questo nuovo sottotipo. Ma c'è una soluzione per questo: un Pattern visitatori . Con il visitatore, quando aggiungi una nuova sottoclasse, aggiungi anche un nuovo metodo all'interfaccia. Ciò significa che ogni classe che implementa questa interfaccia diventerà non compilabile e immediatamente saprai dove ovunque devi estendere il codice per supportare la nuova classe. Sì, renderà più difficile l'aggiunta di nuovi sottotipi, ma renderà le modifiche più sicure.

    
risposta data 06.12.2016 - 17:09
fonte
2

Mark Seeman fornisce la risposta semplice al tuo punto dolente immediato: ai confini, le applicazioni sono non orientato agli oggetti .

Potresti anche leggere il saggio di Greg Young The Generic Repository .

One of the main advantages of DDD is that it allows me to use the full power of OO design in my domain -- as such I want to use polymorphism and conform to the open-closed principle.

Potrebbe essere necessario lasciarlo andare - non c'è molta arte precedente che incoraggi l'uso dell'ereditarietà nella costruzione del modello di dominio.

La composizione, piuttosto che l'ereditarietà, è il modello di riutilizzo più comunemente discusso.

Il mio suggerimento: se pensi davvero che hai bisogno di ereditarietà, fai un passo indietro e sfida il tuo modello di dominio; può darsi che il linguaggio onnipresente stia cercando di mostrarti che ci sono concetti isolati che la tua attuale prospettiva si confonde.

    
risposta data 06.12.2016 - 16:00
fonte
1

Se la riflessione non è una parola sporca per te, potrebbe essere il percorso più semplice. Memorizza i nomi completi delle classi (o serializzazioni complete) nel database e utilizza il sistema di riflessione della tua lingua per creare un'istanza in base al nome o deserializza "direttamente" se stai memorizzando le serializzazioni complete.

In molte lingue, sono solo alcune righe di codice in più nei repository (o nella classe base) e in pratica hai finito.

Tutte le altre soluzioni (Chains of Responsibility, Factories, ecc.) richiedono di registrare o mantenere un elenco di sottoclassi esplicitamente da qualche parte nel codice o nella configurazione. E, va bene per molte applicazioni. Se vuoi evitare riflessioni, essere esplicito o ottenere una certa configurabilità, devi solo decidere dove fai e non vuoi mantenere quegli elenchi.

    
risposta data 06.12.2016 - 16:27
fonte
0

Preferisco usare un database NoSQL orientato ad Aggregate, come MongoDB, per mantenere gli aggregati. In questo modo è possibile mantenere la struttura del modello e non è necessario eseguire alcuna mappatura e il tipo concreto dell'oggetto viene anche incluso come metadati.

    
risposta data 30.12.2016 - 22:20
fonte

Leggi altre domande sui tag