C++:
Rifattorizzazione

Come fare:

Immaginate di avere una funzione che fa un po’ troppo, come questo metodo ingombrante che inizializza un oggetto ed esegue anche il logging:

#include <iostream>

class Widget {
public:
    void init(bool verbose) {
        // Logica di inizializzazione
        // ...

        // Logging dettagliato
        if (verbose) {
            std::cout << "Widget initialized!" << std::endl;
        }
    }
};

// Uso:
Widget w;
w.init(true);

Output:

Widget initialized!

Refactoring questo in metodi più puliti e focalizzati potrebbe apparire così:

#include <iostream>

class Widget {
public:
    void init() {
        // Solo logica di inizializzazione
        // ...
    }

    void logInitialization() const {
        std::cout << "Widget initialized!" << std::endl;
    }
};

// Uso:
Widget w;
w.init();
w.logInitialization();

Questo cambiamento non ha alterato ciò che fa il programma ma rende la classe Widget più modulare e il suo uso più chiaro.

Approfondimento

Il concetto di refactoring, così come lo conosciamo oggi, ha le sue radici nelle comunità di programmazione Smalltalk degli anni ‘80 ed è stato fortemente popolarizzato dal libro di Martin Fowler “Refactoring: Improving the Design of Existing Code” del 1999. Oggi, il refactoring è una parte fondamentale dello sviluppo software moderno, integrato in varie metodologie di sviluppo come Agile e TDD (Test-Driven Development).

Quando parliamo di alternative al refactoring, ci addentriamo nel territorio della riscrittura o del ridisegno. Il refactoring è strategico e incrementale, mentre una riscrittura può eliminare il codice esistente a favore di una nuova soluzione. Il ridisegno, invece, può comportare cambiamenti più significativi incluso l’alterare la funzionalità, che è un obiettivo non previsto per il puro refactoring.

I dettagli implementativi sul refactoring possono diventare piuttosto granulari. Esistono molti “code smells” che potrebbero spingere a un refactoring, come metodi lunghi, classi grandi o codice duplicato. Esistono strumenti automatizzati che possono assistere nel refactoring, come “Clang-Tidy” per C++, che può individuare problemi ed applicare alcune correzioni.

Inoltre, il refactoring richiede una solida suite di test per garantire che la funzionalità rimanga inalterata. Senza test, si è essenzialmente alla cieca e si rischiano regressioni.

Vedi Anche

Per una comprensione più approfondita del refactoring e per vedere altri esempi, potreste voler consultare:

  • Il testo classico di Martin Fowler “Refactoring: Improving the Design of Existing Code” per idee fondamentali e strategie.
  • La documentazione di Clang-Tidy su https://clang.llvm.org/extra/clang-tidy/ per il supporto al refactoring automatizzato in C++.
  • “Working Effectively with Legacy Code” di Michael Feathers, che fornisce tecniche per il refactoring sicuro nel contesto di basi di codice esistenti meno che perfette.