Circa una settimana fa io e il mio amico, socio, nonche' conducente di autovetture quando andiamo assieme ai matrimoni, Fabio, abbiamo iniziato il Refactoring di Oknotizie, internati nella sua stanza a Licata, adottati dai suoi genitori che ci alimentavano ogni qual volta le nostre condizioni psico-fisiche erano motivo di preoccupazione per l'equipe medica che ci segue costantemente durante le fasi di sviluppo. Tutto cio' ovviamente assistiti da forti dosi di caffe' custodito in un termos anti-proiettili preoccupato ad isolare questo importantissimo carburante per programmatori dallo scambio termico con l'ambiente circostante.
Refactoring
che'?
Il Refactoring e'
l'arte di trasformare codice di qualita' non eccelsa (perche' scritto in contesti reali in cui bisogna adattare il progetto al volo per quella nuovissima feature che non puo' aspettare un attimo, in cui le risorse di tempo sono limitate, e in cui i linguaggi utilizzati magari non offrono soluzioni brillanti per risolvere determinati problemi)
in codice di buona qualita',
tramite piccoli passaggi che sistemano una parte alla volta e che sostanzialmente lasciano l'applicazione funzionante.
In realta' dato un software abbastanza vasto, l'unico modo per renderlo di alta qualita' e' quello di eseguire il refactoring periodicamente, perche' scrivere programmi e' un'arte imperfetta, in cui la perfezione mai raggiunta si insegue per approssimazioni successive.
Nel nostro caso il refactoring mirava ad aumentare la qualita' del codice e la sua modularita' interna al fine di rendere l'implementazione di nuove funzionalita' a cui stiamo lavorando piu' semplice. Uno degli obiettivi chiave era quello di raggiungere una separazione completa tra il codice che ha a che fare con il database e il resto del programma. In pratica dalla fine del refactoring oknotizie accede al DB tramite una API ben definita, e non effettua alcuna query diretta.
Un modo migliore di pensare i database
Se vi dico di progettare un database per una rubrica telefonica online
da dove inziate? Probabilmente buttate giu' un paio di tabelle SQL
che modellano in maniera semplice ed efficace il problema. Per esempio potreste pensare ad una tabella
voce con tre campi chiamati
nome,
cognome e
tel. Al fine di avere un identificativo univico per ogni voce e' abbastanza sensato aggiungere un ID unico autoincrementale, e magari creare degli indici per il nome ed il cognome.
In realta' questo non e' un buon modo di progettare il database, o meglio, se siete dei designer davvero esperti potete anche iniziare dalle tabelle, ma solo perche' avete cosi' tanta pratica da pensare inizialmente all'interfaccia e compiere un processo di traduzione simultanea mentre scrivete l'SQL.
Il DB come una blackbox
Provate invece a pensare al database come una
scatola nera, che potrebbe essere implementata in qualunque tecnologia (relazionale o no, SQL o Bdb, o magari tramite il filesystem!). Se il database e' una blackbox e vi chiedono di progettarne uno, tutto diventa piu' chiaro: dovete specificare
quali sono le funzioni di quel database, e non la sua implementazione (la tabella o chi per lei).
In poche parole dovete progettare una API verso il DB. E specificare le sue funzionalita', e qual'e' la complessita' di ogni operazione in termini di tempo e spazio.
Torniamo all'esempio della rubrica telefonica. A questo punto il progetto non sarebbe piu' una tabella SQL abbastanza priva di significato, ma una API:
(output) nomeFunzione (input)
(id) inserisciVoce(nome,cognome,tel)
inserisce una voce nel DB.
Tempo O(1)
Spazio O(1)
() cancellaVoce(id)
cancella una voce, dato il suo ID.
Tempo O(1)
Spazio: N/A
(lista di id) cercaVoceDalNome(nome)
dato il nome o una sua parte, cerca una voce nel DB.
Tempo O(1) se 'nome' esiste nel database
O(N) se 'nome' e' una sottoparte di un nome esistente
Spazio: N/A
E cosi' via. Dopo che avete disegnato l'interfaccia potete finalmente
implementare il vostro DB, qualunque sia la tecnologia che utilizzerete,
e specialmente implementare una API che permetta a tutto il resto del
codice di accedere al database senza curarsi dei dettagli implementativi.
Se tra qualche tempo la vostra applicazione deve diventare un ordine di grandezza piu' complessa, fare qualcosa per cui non era stata progettata, o semplicemente volete migrare ad una tecnologia di database alternativa, ringrazierete voi stessi per aver preso questa strada in tempo.