Devo correggere un bug che non si riesce a riprodurre nel nostro ambiente di test, di un software scritto una decina di anni fa in C++.
Utilizza le MFC, i socket ed il multithreading. Ne conosco il funzionamento operativo, solo che non ne avevo mai guardato l'architettura ed il codice.
Ho pensato di inserire alcuni log significativi, in modo da avere qualche informazione in più quando si verifica il bug.
Per inserire i messaggi di log ho ovviamente necessità di modificare il sorgente e quindi c'è il rischio di inserire nuovi bug, tra l'altro per un qualcosa che non aggiunge funzionalità che interessino l'utente.
Il codice non è coperto da test, non rispetta i principi della programmazione object oriented e le classi hanno molte dipendenze tra loro. Questo non vuole essere un giudizio negativo sul lavoro di un altro collega perchè il programma ha girato per dieci anni ed ancora adesso è utilizzato, quando è stato scritto i test automatici neanche si sapeva cosa fossero e le librerie MFC non facilitano la corretta applicazione dei principi dell'object oriented.
A questo punto la domanda sorge spontanea Cosa fare?
Le mie prime azioni di refactoring dovrebbero avere il minimo rischio di inserire bug e il massimo beneficio per le mie modifiche.
Ho iniziato riportando il progetto ad una classe per file, alcuni file contenevano fino ad una decina di classi e questo non mi permetteva di capire con chiarezza le dipendenze; questo perchè la direttiva include del C++ non distingue, ovviamente, quale classe userò, ma solo che ne verrà usata una dichiarata in quel header file.
Poi ho reso, a turno per ogni classe, tutti i metodi privati, ho ricompilato ed esposto come pubblici solo i metodi e le variabili membro effettivamente usati.
Una feature del C++ interessante è quella di poter rendere privati i metodi della classe base. Infatti in C++ posso dichiarare una classe come:
class CClient : protected CAsyncSocket
In questo modo per chi usa CClient posso controllare quali metodi di CAsyncSocket vengono chiamati. L'attività successiva è stata quella di disegnare uno schema UML focalizzato sulle dipendenze tra le classi principali, da cui sono emersi alcuni interventi che potrei effettuare.
Ora sto pensando a come inserire i test. Su codice C++ non ne ho mai scritti, sarà una buona occasione per imparare ad usare CPPUnit.