Pensieri e parole su HCI, home computing, tecnologie desktop e sul Progetto Lobotomy

giovedì 11 novembre 2010

Il Pallino del Database

Ogniqualvolta mi confronto con un qualche programmatore in merito ad una qualsiasi applicazione che deve gestire un po' di dati, pare che la prima (ed unica?) preoccupazione sia lo schema del database. Mi e' gia' capitato con numerosi personaggi, tra cui un SAPpista, un imprenditore ex-sviluppatore di gestionali, diversi developers freelance, insomma con chiunque abbia anche una vaga idea di come scrivere codice: quando si parla di un programma, la prima cosa che vogliono vedere e' il database.
Saro' un eretico, ma a me non pare che questo componente necessiti di tali particolari attenzioni.
Certamente dallo schema del database adottato dipende la scalabilita', la possibilita' di aggiungere funzionalita' complesse in futuro, ed in parte la performance del sistema completo, ma da quando ho adottato una nuova prospettiva nel processo di sviluppo di GASdotto ho smesso di preoccuparmi particolarmente della cosa.
Sostanzialmente, in GASdotto il database e' la rappresentazione "uno a uno" degli oggetti maneggiati dall'applicazione, e tutte le interazioni con questi oggetti sono formalizzate secondo una manciata di regole.
Ad esempio: l'oggetto "Order" e' un ordine aperto presso un fornitore. All'interno della classe sono iscritte le proprieta' che compongono tale elemento. Sul database, c'e' una tabella che si chiama "Orders" (tipicamente le tabelle si chiamano nello stesso modo della classe di riferimento, ma ho dovuto fare una eccezione poiche' "order" e' una parola chiave di SQL) che riporta esattamente quelle stesse proprieta'. Dove l'oggetto ha una stringa, sul database c'e' un varchar. Dove c'e' un numero, corrisponde un intero. Dov'e' c'e' un riferimento ad un oggetto descritto da un'altra tabella, vi si trova la chiave esterna a quella tabella. Nel caso particolare delle relazioni "uno a molti" (ad esempio: i prodotti contemplati all'interno dell'ordine), si utilizza sempre una tabella di appoggio che si chiama "nomedellaclasse_nomedellattributo" e due colonne, una per l'entita' di riferimento (l'ordine) e l'altra per i sottoelementi (i prodotti).
Lo schema non e' per nulla ponderato o meditato: ogni informazione che serve e' memorizzata secondo una forma definita a priori, senza soffermarsi mai sul caso specifico.
Durante l'implementazione del supporto alle "varianti" dei prodotti in GASdotto 2.0 ho constatato come questo approccio sia facilmente adattabile: alla fine dell'opera mi son ritrovato con numerose nuove tabelle, ma per quanto complessa sia la relazione tra prodotto, variante, prodotto ordinato, varianti ordinate, prodotti consegnati eccetera, in breve sono riuscito a cavarne una definizione sempre coerente e non eccessivamente arzigogolata.
Il vantaggio maggiore di tale strategia e' che, essendo tutto maneggiato con poche regole sempre valide, il codice necessario alla serializzazione, deserializzazione, e reperimento e salvataggio delle informazioni e' unico in tutti i casi. Il guscio piazzato intorno al database e' ridotto a poco piu' dei minimi termini, una unica classe ("FromServer". Nome assai poco fantasioso...) provvede alla stragrande maggioranza del lavoro. Cosa non da poco, in termini di mantenibilita'.
Sicuramente lo schema finale non e' il piu' ottimizzato che si possa pensare, e non dubito che si potrebbe fare molto di meglio in termini di performance e risorse occupate, ma in fin dei conti la differenza non si nota. L'istanza nota piu' grossa di GASdotto conta attualmente 600 diversi prodotti da 30 diversi fornitori, il dump completo (e compresso con l'opzione -Ft di pg_dump) di PostgreSQL e' di quasi 1 megabyte, eppure il tutto pare sufficientemente reattivo ai 170 utenti registrati (a parte quando la componente Javascript inizia a macinare tutti quei dati in un colpo solo nel browser, ma e' un altro discorso).
Insomma: personalmente, ho smesso di dare tanto peso a come e' fatto il database di backend delle applicazioni. Quantomeno delle mie. Qualche microsecondo di elaborazione in piu' val bene tutta questa flessibilita' compressa in una cosi' modesta quantita' di codice.

2 commenti:

vivo ha detto...

Perdonami ma un megabyte è veramente poco per una base dati.
Quando i dati diventano tanti, nell'ordine dei Giga o Tera l'ottimizzazione del database (e delle query) influisce per molti ordini di grandezza più che il codice che utilizza/visualizza i dati recuperati.
Inoltre, modificare una base dati di grandi dimensioni è un'operazione che NESSUN amministratore di database serio fa volentieri, ergo meglio la struttura sia corretta da subito.

Roberto -MadBob- Guido ha detto...

Posso essere d'accordo, ma... Io non mi chiamo certo "signor Facebook" o "signor Google", non credo mi trovero' mai a trattare gigabyte o terabyte di dati!
Per la stragrandissima maggioranza dei progetti (open, ma anche commerciali) non val veramente la pena farsi le fisime sull'ottimizzazione al millisecondo, perche' comunque l'ordine delle informazioni da gestire ben difficilmente supera la manciata di megabytes.

In merito alle modifiche da fare: accade molto spesso di farle quando si gestisce un progetto free che cresce rapidamente, come appunto GASdotto. Almeno un paio di volte al mese capita di introdurre una nuova funzionalita' che prevede il fatto di aggiungere o modificare lo schema.
Non per niente sto proprio in questo momento definendo un pezzetto di codice che provvede automaticamente ad aggiornare il database quando cambio le classi PHP aggiungendo o togliendo attributi alle classi elementari ;-)