Pattern / metodologia per rappresentare record di database di grandi dimensioni come oggetti

2

Un po 'di informazioni di base: abbiamo una vecchia applicazione di database scritta in Access che consente agli utenti di monitorare il loro carico di lavoro, e il codice è ...' procedurale 'potrebbe essere troppo gentile. La stragrande maggioranza del codice è cablata per formare eventi, c'è un lotto di duplicazione e un'astrazione minima o nulla. Se ha bisogno di recuperare i dati dal database, lo farà proprio lì e poi, anche se questo significa all'incirca lo stesso bit di codice ripetuto 6 volte per 6 pulsanti simili (e 6 richieste di database praticamente identiche). Non è carino.

Voglio ricostruire l'applicazione in VB.NET, ma sto colpendo un po 'l'intoppo del design quando si tratta di scrivere classi per rappresentare i record del database come oggetti - Non ho una grande esperienza in OO programmazione (ho scritto poche piccole app, letto molti libri e materiale, normale lurker di SE), quindi questa è la mia prima applicazione di database OO.

Il problema è che un determinato "lavoro" per un utente ha un lotto di campi nel database. Circa 30 circa - ID, Titolo, Richiedente, Data richiesta, Data obiettivo, Priorità, Tipo, Approvazione ... e così via. Primo passaggio: Whack tutto in una grande classe Job sporca:

Public Class Job
    Private mID As String
    Private mTitle As String
    Private mRequestorName As String
    Private mRequestorEmail As String
    ...

    Public Property ID() As String
        Get
            Return mID
        End Get
        Set(value As String)
            Me.mID = value
        End Set
    End Property
    ...
End Class

Yikes. Sono sicuro che puoi vedere la mia esitazione nell'avere una classe così enorme seduta davanti e al centro dell'applicazione. Tutte queste proprietà sembrano violare l'incapsulamento anche - i membri privati potrebbero anche essere pubblici, ma al contrario devo essere in grado di modificare i campi e poi scrivere di nuovo nel database.

Secondo passaggio: ci sono alcune cose che potrebbero essere estratte e collocate altrove: ad esempio, tutti quei membri di Requestor___ potrebbero sedere in una classe Requestor

Public Class Job
    Private mID As String
    Private mTitle As String
    Private mRequestor As Requestor
    ...
End Class

Public Class Requestor
    Private mName As String
    Private mEmail As String
    ...
End Class

Quindi ora ne ho una mezza dozzina. Classi più piccole? Si sente bene Ma sembra che tutto ciò che ho realizzato sia essenzialmente la normalizzazione del database, che non sembra debba vivere nell'applicazione. E l'unica vera modifica alla struttura è che richiede più passaggi per accedere agli elementi dei dati.

E ho ancora tutte quelle proprietà (che mi costringono a usare la notazione ungherese sui miei membri privati, di cui non sono un fan, ma VB.NET non è sensibile al maiuscolo / minuscolo, quindi non posso usare il stessi nomi), che non sono ancora a posto con me.

Esiste uno schema o una metodologia standard per lo spostamento di elementi di dati di grandi dimensioni da e verso un database? La mia migliore idea corrente è quella sopra con i metodi commit() e read() nella classe Job - le modifiche vengono apportate agli oggetti e successivamente vengono eseguite sul database.

    
posta Kai 23.09.2013 - 11:58
fonte

3 risposte

2

La risposta alla tua domanda è che probabilmente, per la maggior parte del tempo, non è necessario.

In realtà, stai costruendo il tuo modello in modo tale da mappare banalmente il design del database relazionale esistente. Questo è un cattivo approccio per sé , inoltre, se quel disegno relazionale è viziato e / o denormalizzato. La persistenza è il supporto, non il kernel.

Concentrati invece su problemi concreti che la tua applicazione dovrebbe risolvere e costruisci un modello esplicitamente progettato per soddisfare tali requisiti. Questo modello rifletterà il dominio concettuale della tua applicazione, molto più del tuo modello di dati.

La mia esperienza con i record di database di grandi dimensioni è che, la maggior parte delle volte, è necessario solo un sottoinsieme di colonne per eseguire determinate operazioni.

    
risposta data 26.09.2013 - 01:05
fonte
0

Se ti stai prendendo il tempo di riscrivere il codice in un'altra lingua, prenditi il tempo necessario per ripulire il database. Mentre i tuoi passi di normalizzazione possono sembrare che non hanno ottenuto molto, posso assicurarti che passi del genere porteranno enormi dividendi. Se si dispone di uno schema di database mal progettato, sarà necessario supportare tale progettazione scadente nel codice sorgente.

Se non riesci a riprogettare il database, probabilmente vale ancora la pena progettare correttamente il livello di persistenza nel codice sorgente e quindi avere un livello leggero nel codice che possa interagire con il database mal progettato.

    
risposta data 25.09.2013 - 05:19
fonte
0

Il riferimento alla disadattamento impedenza relazionale all'oggetto è una lettura interessante . Tuttavia, quando lo guardiamo con più attenzione, fondamentalmente si lamenta perché un piolo quadrato non si adatta a un buco rotondo.

Questo è ciò che risolve un ottimo prodotto ORM. Sfortunatamente, avendo fatto parte di due distinti progetti e sviluppi dell'ORM, posso dire che molti ORM portano le loro sfide.

Anche se la domanda è vecchia di un anno, i principi menzionati qui vengono appresi nel corso degli anni e sono ancora validi e potrebbero essere utili a qualcuno.

  1. Utilizza il principale di DRY
  2. Carica sempre il record completo (o solo i campi chiave, dell'indice che stai utilizzando per la ricerca). Ci possono essere eccezioni in caso di segnalazione, ma per applicazioni OLTP generali, farlo come principio perché cambierete la logica spesso e non dovreste tornare indietro e modificare gli oggetti del vostro record di base (come suggerito nei prossimi due principi). La penalità di velocità si applica raramente e il vantaggio di codifica è molto più alto.
  3. Accetta il fatto che un database ha lo scopo di darti serie di righe (tuple) e usarle così come sono invece di combattere la struttura.
  4. Assicurati che il primissimo livello di oggetti che si occupano del database sia "record aware" (vale a dire principio precedente). Ciò significa che ogni oggetto gestisce un solo tipo di record, di solito da una tabella o da una vista.
  5. È possibile aggiungere facoltativamente un livello di oggetti che sono a conoscenza di più tabelle, ovvero a conoscenza delle relazioni tra le tabelle. Questo rende le cose più facili. Ma poi devi usare solo quel nuovo livello, e non andare direttamente al livello inferiore per coerenza, altrimenti avrai un sacco di Odore di codice link
  6. Ora scrivi la tua logica aziendale, in oggetti separati da quelli che gestiscono il database. Tranne mettere tutto il controllo del vincolo del tipo di convalida nel primo strato. Ciò significa mantenere la convalida dei dati separata dalle regole aziendali o dalla funzionalità aziendale.
  7. Mai "non implementare" la convalida nel database stesso, in altre parole, mai ignorare / saltare sulla convalida, ma inserire tutto ciò che il motore di database consentirà. Ciò significa che sono fondamentali come l'implementazione di semplici convalide come "CHECK constraints" a complessi trigger DML cross table. In altre parole, non lasciare mai la spazzatura nel database (vedo una tonnellata di sistemi ben intenzionati dagli sviluppatori con questo difetto). Hmm .. L'ho detto abbastanza strong .. Immagino di no ... quindi ... quello che sto DICENDO :-) è "Non fare affidamento sugli oggetti dell'interfaccia utente per l'integrità dei dati che possono essere fatti dal motore del database ". E se DEVI consentire dati non convalidati da qualche parte nel tuo processo aziendale perché "operatore / utente" potrebbe non averlo al primo utilizzo, ad es. un paziente non è consapevole di darti tutte le informazioni in uno scenario ER, quindi assicurati che sia in atto un processo che richiede regolarmente a qualcuno di andare a compilare i dati mancanti.
  8. I record con campi BLOB o altri campi grandi dovrebbero essere gestiti dall'oggetto principale significato per il record, ma solo recuperare il blob per riferimento chiave, se necessario. Questa implementazione dovrebbe essere nascosta e gli altri oggetti che utilizzano l'oggetto "record" non dovrebbero preoccuparsi di quando e come il BLOB viene recuperato o salvato nel database.

Questo elenco è ingannevolmente piccolo, ma renderà la vita più facile per lo sviluppatore e per il DBA che deve convivere con il design, in qualsiasi progetto in cui sia necessario il mapping relazionale da oggetto.

    
risposta data 19.10.2014 - 09:40
fonte