La memorizzazione di tipi nel database è anti-pattern?

3

Un piccolo background su da dove viene questa domanda. Nella mia attuale applicazione .NET sto lavorando su alcune funzionalità relative all'archiviazione di un certo tipo di entità aziendale chiamata "Progetto". A seconda della situazione, ciò che deve essere archiviato e le azioni esatte relative all'archiviazione possono variare notevolmente. La mia idea di base è creare un'entità chiamata ArchiveSchedule che in pratica memorizza i dati che dicono che questo tipo di progetto dovrebbe essere archiviato dopo questo lasso di tempo.

Desidero incapsulare le mie query per la selezione di tutti gli oggetti da archiviare e i comandi per l'archiviazione effettiva nei propri oggetti che ereditano da alcune interfacce comuni. Ci saranno più query di archiviazione (selezionare elementi basati su varie proprietà, o se sono stati archiviati prima e successivamente ripristinati, ecc.) E più comandi di archiviazione (cioè comandi che inviano dati a interfacce diverse, alcuni che eseguono eliminazioni, ecc. ). Quello che sto considerando di fare è includere su ArchiveSchedule, riferimenti al tipo .NET effettivo corrispondente alla query e al comando che voglio usare per questo programma. Quindi, quando voglio eseguire effettivamente query e comandi, utilizzo reflection per creare l'oggetto ed eseguire il comando o la query.

Questa strategia di base per archiviare le informazioni sul tipo nel database e quindi utilizzare il reflection per creare gli oggetti e iniettare le dipendenze è antipattern? O c'è un modo migliore per farlo?

Nota: so che ci sono alcuni problemi con la semplice memorizzazione del nome del tipo o dello spazio dei nomi, perché potrebbero cambiare durante il refactoring, ma credo che questi potrebbero essere mitigati abbastanza facilmente usando un GuidAttribute nella definizione della classe e archiviando invece il guid, quindi Sono curioso di sapere se ci sono altri problemi fondamentali oltre a questo.

    
posta AndrewSwerlick 12.04.2013 - 16:49
fonte

4 risposte

4

Sì, generalmente. Stai quindi vincolando il nome del tipo a dati esterni, limitando le tue capacità di refactoring e facendo in modo che le persone cambino le cose in due posti quando fanno una nuova classe. Inoltre, sei (o almeno qualcuno è ...) sarà un mondo di dolore in ~ 10 anni quando C # diventa obsoleto. Le nuove implementazioni potrebbero non avere lo stesso nome di classe, per non parlare di idiomi per l'istanziazione.

Tenderei a non includere questo nel database, e anche se lo facessi, memorizzando qualche forma agnostica di implementazione del comando. Potrebbe essere più un lavoro, ma nel complesso è un po 'più flessibile e robusto.

    
risposta data 12.04.2013 - 17:42
fonte
1

Stai pensando troppo al tuo problema. La maggior parte del supporto di O / RM si chiama Mappatura della gerarchia degli oggetti . Utilizzando il Pattern di strategia , puoi incapsulare la logica per archiviare il tuo Progetto in una gerarchia di ProjectArchiver. Fornisci un ID per l'Archiver e collegalo al database.

La classe base dovrebbe avere una funzione di Archive () virtuale, implementata da tutte le classi figlie.

Quando l'oggetto viene recuperato dal database, creerà un'istanza della sottoclasse appropriata con la corretta implementazione di Archive. E tutto ciò che devi fare è chiamarlo.

    
risposta data 12.04.2013 - 20:15
fonte
0

Un sistema di riflessione come questo può essere davvero fragile e non sempre è chiaro perché fallisce quando fallisce.

Ovviamente fallisce quando il nome del tipo non è corretto ma non ci sono indicazioni sul perché o come non sia corretto. Ad esempio, potresti semplicemente non avere il riferimento all'assembly appropriato e poi fallirà. Si può dedurre quello basato sul fatto di avere un nome di tipo corretto (funziona da qualche altra parte quando si digita Type.GetType (typename)), ma questo è un po 'di testing e spunta da fare rispetto ad altre classi di bug. Per trovare il Guid, dovrai cercare gli assembly appropriati che attenuano solo parzialmente l'area di superficie per i problemi.

Anche il tuo problema non è specifico del database, ma ogni volta che attribuisci informazioni sul tipo a un'origine persistente. Un problema è il modo in cui gestirai il cambiamento delle proprietà (rimozione o aggiunta) e altre modifiche del genere.

Un altro potenziale problema è rappresentato dalle prestazioni, la riflessione è relativamente lenta ma non è probabile che importi a meno che non la utilizzi in un modo che probabilmente non dovresti essere.

Nel complesso, non penso che chiamerei questo tipo di cosa un antipattern. Esistono DB progettati per l'orientazione degli oggetti che sarebbero ideali qui, ma in questo caso dovresti avere due DB da mantenere se il resto della tua applicazione si adatta meglio in un contesto relazionale. Può davvero risparmiare tempo di sviluppo e ridurre gli errori se usato correttamente, ma può anche costare molto tempo di sviluppo e aumentare gli errori se questo codice verrà modificato molto o se le persone che lo utilizzano non lo capiranno veramente. Si tratta di utilizzare correttamente gli strumenti.

    
risposta data 12.04.2013 - 17:39
fonte
0

Questo sembra un possibile candidato per un database di documenti come Raven o MongoDB piuttosto che un database relazionale.

Con i database di documenti che non sono bloccati in uno schema, puoi memorizzare qualsiasi elemento di qualsiasi struttura che possa adattarsi maggiormente ai tuoi dati in quanto non sai esattamente esattamente cosa vuoi archiviare.

    
risposta data 12.04.2013 - 17:32
fonte

Leggi altre domande sui tag