Il modo migliore per fare riferimento a dati di database statici nel codice?


24

Molte applicazioni includono "dati statici": dati che non cambiano realmente durante la vita dell'applicazione. Ad esempio, potresti avere un elenco di aree di vendita che probabilmente sarà un elenco fisso per il prossimo futuro.

Non è raro trovare questi dati statici in una tabella di database (spesso perché si desidera fare riferimento ad essi nelle chiavi esterne di altre tabelle). Una semplice tabella di esempio avrà un ID da utilizzare come chiave primaria e una Descrizione. Ad esempio, la tabella SalesArea avrà (almeno) una colonna SalesAreaId e una colonna SalesAreaDescription.

Ora, nel codice potresti non voler trattare ogni riga della tabella allo stesso modo. Ad esempio, potresti voler impostare un'area di vendita predefinita su alcune schermate, fornire cifre diverse per alcune aree o limitare ciò che gli utenti possono fare in altre aree.

Qual è il modo migliore per fare riferimento a questi dati statici nel codice? Perché?

  1. Inserisci nel codice le descrizioni nel tuo codice. Usalo per cercare SalesAreaId dal database quando ne hai bisogno.
  2. Inserisci nel codice gli ID nel tuo codice. Usalo per cercare SalesAreaDescription quando ne hai bisogno.
  3. Aggiungi una colonna alla tabella per ogni scopo, ad esempio una colonna "IsDefaultOnProductLaunchScreen" e così via (potrebbero essercene molte).
  4. Qualcos'altro.

Ci sono altre considerazioni speciali che dovrei fare quando ho a che fare con dati di database statici? Ad esempio, dare a queste tabelle un nome speciale?


1
Possibile duplicato: programmers.stackexchange.com/questions/304169/… Credo che le risposte su quello (collegato)
arrivino al nocciolo

Risposte:


14

Che ne dici di caricarli in una cache (di solito implementata come una tabella hash) all'avvio dell'applicazione? Se lo fai, non devi nemmeno interrogare il database (beh, non più di una volta).

Vorrei anche suggerire di evitare qualsiasi codifica. Aggiungi indicatori predefiniti (inizialmente nella tabella DB e anche nella struttura della cache) per le schermate che richiedono impostazioni predefinite. Per eseguire ricerche su non defauilt, prova a memorizzare le chiavi che verranno cercate in un file di configurazione o proprietà, se possibile.


La memorizzazione nella cache è ovviamente utile, ma come si aggiornano questi valori? Presumibilmente un riavvio dell'applicazione o una sorta di strategia di invalidazione della cache?
Steve,

1
@Steve Sì, esattamente. Dipende dall'applicazione. Il riavvio è utile per avviare qualcosa di frequente. Per un'applicazione a esecuzione prolungata, forse ricaricare la cache una volta al giorno durante i periodi lenti. La mia domanda sarebbe: che dire di uno scenario in cui l'applicazione esegue molti periodi di vita molto brevi. Ad esempio, forse uno script PHP o qualcosa di simile.
Tylermac,

Il database eseguirà la propria cache per i dati a cui si accede frequentemente, quindi si implementerà nuovamente qualcosa di già implementato (e probabilmente non altrettanto!)
James Anderson

@JamesAnderson: la memorizzazione nella cache dell'applicazione significa che ci sarà sempre e solo una chiamata al database. Sì, i database avranno le loro cache, ma questi possono essere invalidati / aggiornati da eventi al di fuori del controllo della tua applicazione, e devi comunque avere una connessione al database ed effettuare una query per ottenere quei dati (e spero che sia nel cache di db). Non è poi così difficile implementare una semplice cache in-application.
FrustratedWithFormsDesigner

7

Un'alternativa al DB o alla codifica hardware consiste nell'utilizzare un file di configurazione letto al momento dell'avvio. È quindi possibile archiviare questi dati in una struttura di sola lettura all'interno del codice.

Nel raro (ma non impossibile) caso in cui modifichi questi dati dovrai riavviare l'app. Se ciò non è possibile, è possibile scrivere un gestore di configurazione più complesso che controlla le modifiche nel file di configurazione ogni volta che si accede ai dati, questo è in realtà abbastanza efficiente poiché è necessario solo controllare un timestamp sul file e quindi invalidare tutti i dati se il file è aggiornato.


1
Buona idea per alcuni tipi di dati statici, ma non così buona se si desidera applicare relazioni FK come descritto nella domanda.
Kramii Ripristina Monica

La domanda non ha detto che questo era un requisito, solo uno scenario. Se non è necessario, l'approccio del file di configurazione funziona bene.
Steve,

Hai ragione, non ero abbastanza chiaro. Ma sono contento ... perché ho imparato qualcosa dalla tua risposta. Non ho mai incontrato questo approccio prima.
Kramii Ripristina Monica

3

Se i dati si riferiscono a dati esistenti nel tuo DB, è probabilmente altrettanto efficace aggiungerli al DB quanto aggiungerli al codice. In caso contrario, di solito sono tentato di "prendere quel proiettile una volta" e inserirlo nel codice fino alla prima modifica.

Spesso ciò che riteniamo statico risulta non esserlo, e quando ciò accade, non si deve attendere il rilascio di un codice per passare una modifica. Non appena ciò accade una volta, inserirlo nel database e scrivere una pagina dell'amministratore per eseguire ulteriori aggiornamenti.

Per fare un esempio, se nel DB sono già presenti Aree di vendita, aggiungere una descrizione lì, non creare una tabella hash per mettere in relazione i dati del database con elenchi codificati. Ma se non costruisci una tabella hash delle aree di vendita con tutti i mezzi, ma sii pronto, la prima volta che qualcuno modifica una descrizione o aggiunge una nuova area di vendita, spostala nel DB.


"Spesso ciò che riteniamo statico risulta non essere" - così vero.
Kramii Ripristina Monica

3

Perché non solo codificare tutto? Il problema principale che ho sempre avuto è il riferimento ai valori statici dal DB nel codice dell'applicazione. Una cosa è se stai semplicemente creando un elenco a discesa o qualcosa fuori dai valori statici, ma cosa succede se una logica dell'applicazione dipende dai valori dal DB?

In una semplice app al momento ho un elenco di stati di modifica per contenuti: bozza, pubblicato, archiviato.

Gli elementi di contenuto devono essere trattati in modo diverso a seconda dello stato in cui si trovano. Se dovessi conservare questi dati di stato nel DB, con i valori 1, 2, 3, rispettivamente, come farei per verificare se qualcosa è in Bozza stato?

if (content.State == 1)
o
if (content.State == "Draft")?

Ho appena codificato i valori!
Stessa cosa se usi una tabella cache / hash: devi ancora usare un valore scritto nel tuo codice come chiave per cercare i tuoi dati.

Quali sono gli svantaggi dell'approccio hard-coding?


Lo svantaggio è come ha detto pdr, "Spesso ciò che pensiamo sia statico risulta non esserlo".
Tylermac,

2
Ma se in realtà fai riferimento ai valori dei dati statici nel codice, non puoi modificarlo nel database senza interrompere l'app. Sicuramente dipende da cosa vengono utilizzati i dati: come ho già detto, se sta semplicemente popolando un elemento dell'interfaccia utente in modo che un utente possa selezionare un valore e riportarlo direttamente nel DB come parte di un record in un'altra tabella , quindi i dati statici nel DB possono cambiare indipendentemente dal codice dell'app. Sono abbastanza sicuro che questa sia la situazione di @pdr: l'app che gestisce l'insieme di dati statici come un singolo elemento.
Dave,

2

Simile a ciò che ha detto FrustratedWithFormsDesigner, questo viene in genere eseguito con una cache, in quanto significa che devi sempre caricare i dati statici una sola volta, ma segue il modello OAOO, il che significa che non stiamo definendo i dati in due punti (database e in il tuo codice).

So che NHibernate ORM offre questa funzionalità attraverso una cache di 2 ° livello . Puoi dire che memorizza nella cache i dati da una determinata tabella e dire che è di sola lettura. Verrà caricato la prima volta che è necessario e dopo non accederà più al database, anche se si accede ai dati da più sessioni.


+1 per una volta e una sola volta. Ma per quanto riguarda il trattamento di file diverse in modo diverso?
Kramii Ripristina Monica

1
@Kramii - Puoi usare qualcosa come le classi di enumerazione . Se i metadati si riferissero solo al tuo programma, metterei la logica di business ( IsDefaultOn...) in una proprietà sull'entità. Fallo restituire vero per l'entità unica. Ciò ti permetterebbe di trovare quell'entità, data l'intera collezione. In alternativa, è possibile utilizzare una classe controller che fornirà all'entità appropriata una chiamata di metodo.
Scott Whitlock,

2

Questa è l'ottimizzazione prematura nel suo peggio.

In primo luogo, qualsiasi DBMS moderno recupererà i dati da piccole tabelle alla velocità della luce e tutti hanno algoritmi di memorizzazione nella cache che vanno dal buono al superbo (più si paga per il DBMS, migliore è la cache!). Quindi stai ottimizzando qualcosa che consuma risorse minime.

In secondo luogo, hai pochissima esperienza con le applicazioni del mondo reale se immagini che qualcosa come "un'area di vendita" siano dati statici. Questi possono cambiare con ogni cambio di Direttore Marketing o CEO. Quindi stai andando in un mondo di dolore due anni dopo.

Ci sono solo due modi per andare qui: -

Archiviarlo in un database e accedere ai dati con sql "normale".

Archiviarlo in un file di configurazione XML di fantasia (eventualmente accessibile tramite REST o SOAP) che può essere facilmente modificato ogni volta che si verifica un "cambio strategico di politica".


1

Dipende da cosa stai facendo con i dati. Se è un elenco di qualcosa, generalmente lo inserirò in un array. Se l'elenco deve crescere in un'altra versione, è facile semplicemente aggiungere al database e modificare il codice per gestire i dati aggiuntivi nell'array (che potrebbe non essere nemmeno necessario a seconda del codice, ad esempio elencando i dati con un per loop usando il limite superiore dell'array). Se si tratta di un elenco di impostazioni, in genere codificherò quelle in quanto di solito non ce ne sono molte ed è più facile e veloce rispetto all'utilizzo di un'istruzione SQL. Se si tratta di un'impostazione che l'utente può modificare e voglio salvare la selezione per i successivi lanci, creerò una tabella da utilizzare come registro e trascinerò le singole voci nelle variabili secondo necessità.


1

So che questa risposta è stata accettata, ma volevo condividere come l'abbiamo fatto nel mio ultimo negozio di sviluppo web, dove abbiamo cercato di ridurre il più possibile l'I / O del database.

Abbiamo utilizzato i file di inclusione lato server per il maggior numero possibile di strutture di dati di tipo ricerca. Principalmente questo era per la navigazione del sito (per includere la subnavigazione) ma l'abbiamo anche usato per il maggior numero possibile di menu a discesa e caselle di controllo (Stati, Paesi, Categorie).

Inizialmente, abbiamo estratto tutti questi dati dal database. Dal momento che abbiamo fornito al cliente un widget di amministrazione, questi potrebbero cambiare questi dati a piacimento e non ci siamo mai impantanati con piccole modifiche al nichel-centesimo. Il più delle volte questi dati non sono quasi mai cambiati ma, occasionalmente, sarebbero cambiati.

Siamo sempre stati alla ricerca di tempi di caricamento più rapidi. Quindi abbiamo deciso di implementare quanti più file di testo lato server statico possibile. Lo abbiamo fatto a lato del widget di amministrazione. Ogni volta che veniva aggiornata una tabella del database, rigeneravamo il corrispondente file di testo statico. Questo ci ha dato un ambiente molto flessibile e veloce.


0

La mia soluzione a questo, che potrebbe non funzionare in tutte le situazioni, è quella di associare i dati del database statico a un hard-coded enum. Poiché il problema deriva dall'avere dati dinamici (database) associati alla logica statica (codice), rendere esplicito (e sciolto) questo legame avendo una tabella di database che si associa al enum. Ex:

LooseDBCodeBinding (database table)
   ID : Int32 (key)
   Name : String
   HardCodedTypeID : Int32

// in code:
public enum LooseDBCodeBinding
{
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3 // etc...
}

Quindi scrivere un'interfaccia utente che ti consenta di visualizzare facilmente l'elenco dei LooseDBCodeBindingrecord e di mapparli su LooseDBCodeBinding enumvalori (incluso il supporto di associazioni "non funzionanti"). È quindi possibile programmare intorno a enum, e progettare il database attorno alla chiave della tabella, ed è solo questa tabella che ha conoscenza di entrambi i contesti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.