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:

  1. 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.
  2. 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.

powered by IMHO