Sono un po' di giorni che penso a questo post, ma fino ad
ora non ero riuscito a trovare i 30 minuti consecutivi necessari per poterlo
redarre. L'intento è quello di presentare un caso reale in cui il Refactoring mi
è stato di aiuto nella realizzazione di una delle ultime features di IMHO, per
l'appunto il sistema di upload dei file verso l'ftp.
Quando ho iniziato il lavoro, le uniche cose che realmente avevo chiare in
testa erano i seguenti presupposti:
- L'unico modo veramente valido per implementare la
feature era di usare il protocollo FTP. Svariate ricerche in rete mi avevano
confermato che l'eterogeneità dei motori di blogging lasciava poco spazio a
soluzioni più sfiziose.
- In secondo luogo era necessario comunque lasciare aperta la possibilità,
in futuro di creare soluzioni ad-hoc per ogni motore di blogging.
Armato di pazienza e di queste labili certezze, il primo passo è stato quello
di cercare una libreria per l'FTP. Di certo una cosa da escludere subito era la
realizzazione ex-novo di tale libreria, non perchè impossibile, ma perchè la sua
implementazione avrebbe fatto lievitare inutilmente i tempi di realizzazione. La
libreria trovata come sapete è la' edtFTPnet, che alcuni test comparativi mi
hanno confermato essere la più affidabile.
A questo punto avrei potuto mettermi davanti ad un foglio di carta e
disegnare la soluzione del problema così come sarebbe dovuta nascere, tuttavia
dato il tempo scarso, e la mia ormai grande fiducia nel refactoring, ho invece
aperto Visual Studio e cercato il punto migliore per innestare il nuovo codice.
Alla fine la scelta è caduta sull'aggiunta di un bel metodo virtuale alla classe
base degli adapter con i parametri che sembravano più adeguati e nel farne
l'override in un solo engine, cosciente del fatto che il codice che avrei
scritto al limite andava copiato in tutti gli altri engine.
Questa era una soluzione evidentemente temporanea, non
sia mai che io cada nella trappola mortale del cut&paste, ma che
mi permetteva innanzitutto di approfondire la problematica facendo funzionare il
sistema velocemente. Inoltre, evidenziava una bella questione, ovvero come fare in modo, dovendo fornire a tutti gli
engine il medesimo protocollo, di astrarre l'implementazione del protocollo dall'engine
stesso.
Ma tutto ciò era materia per i posteri. Innanzitutto occorreva scrivere il
metodo che trasferiva i file. E già questa questione apriva altri problemi. Al
termine del lavoro, quando l'engine di .TEXT già pubblicava i post mi sono reso
conto che lo faceva in modo logicamente errato. Infatti l'engine apriva e
chiudeva la connessione ad ogni file inviato. Con un protocollo come l'FTP
questo era un problema dannatamente grave, perchè l'handshake iniziale causava
un overhead eccessivo. Ovviamente pensandoci bene avrei anche potuto trovarmi in
futuro con protocolli diversi (si pensi ad esempio ad un webservice) che non
richiedessero una apertura e chiusura della connessione. A questo punto i metodi
da uno sono divenuti tre. Due responsabile di aprire e chiudere la connessione,
e il terzo che trasferiva i file uno per uno. Un protocollo non connesso,
semplicemente poteva lasciare vuoti i metodi Open() e Close().
Risolto questo problema era giunto il momento di estendere il funzionamento
agli altri engine. Escluso a priori il cut&paste, in buona ottica oop non
rimaneva che separare le responsabilità e creare una classe che si occupasse del
trasferimento. E così è stato ed è nata la classe FtpPublisher. A questo punto
tutti gli engine trasferivano immagini per mezzo dell'FTP. Il problema a prima
vista era risolto. Ma ancora il requisito di cui al punto 2 non era del tutto
soddisfatto. E' vero che è sempre possibile riscrivere un metodo, ma è anche
vero che è di gran lunga meglio se non lo si fa. Inoltre, era evidente una
duplicazione delle funzionalità. GLi engine così come il publisher ftp aveevano
entrambi i metodi Open(), Close() e SendFile().
Quindi l'idea è stata quella di estrapolare completamente la logica di
trasferimento dall'engine e semplicemente di consentire ad esso di fornire
l'istanza di publisher da utilizzare per la pubblicazione. Perciò ho creato la
classe astratta Publisher, e ho migrato i metodi Open(), Close() e SendFile()
verso il publisher, in particolare l'ftp. A questo punto non rimaneva altro che
fare in modo che l'engine creasse l'istanza di publisher e perciò ho creato una
proprietà che lo restituisse a chi lo chiedeva. Tutto ciò adeguando poco a poco
anche la logica che usava il publisher.
La soluzione era veramente buona. Ma ancora gli mancava qualcosa. Anche i
questo caso, sostituire il publisher costringeva a ricompilare. E' stata la
reflection alla fine che mi è corsa in aiuto. Modificare la proprietà degli
engine per fare in modo che leggessero la classe publisher da file di
configurazione è stato un gioco da ragazzi. E a questo punto ero veramente
soddisfatto.
Ecco, a conclusione di questo post, vorrei rilevare come, partendo con poche
certezze e armati della affilate spade dell'object-orientation e del refactoring
si possa ottenere una soluzione ben congegnata, risparmiando di spremere le
meningi su problemi che per ovvie ragioni all'inizio sfuggono. Ovviamente questo
è il mio modo di procedere, suppongo che altri avrebbero ottenuto soluzioni
differenti, ma ritengo che il succo del discorso sia davvero importante: non
conta che riusciate a smontare il problema pezzo per pezzo da subito, è molto
più probabile che, comportandovi come le onde del mare sulla roccia,
riusciate più facilmente ad eroderlo mano a mano che esso presenta le sue parti
più friabili.