Analisi Post-Mortem: Lezioni Apprese dal Fallimento del Refactoring

Il nostro problema non è mai stato un singolo bug. È stato un fallimento sistemico del nostro processo di gestione delle dipendenze. L’esperienza ci ha insegnato tre lezioni fondamentali:

  1. pip freeze non è uno strumento di rollback: Abbiamo scoperto sulla nostra pelle che pip freeze crea una “fotografia” dell’ambiente che può essere incoerente e non riproducibile, specialmente in presenza di dipendenze complesse o installate in modo non standard.

  2. Le Dipendenze Implicite sono Bombe a Orologeria: Il caso timesfm ha dimostrato che una dipendenza non tracciata in un file di requisiti rende l’ambiente una “scatola nera” impossibile da replicare, condannando ogni tentativo di rollback o di onboarding.

  3. Un Ambiente Sano è un Prerequisito, non un Dettaglio: Abbiamo perso giorni a debuggare il codice (il sintomo) quando la causa principale era un ambiente di esecuzione instabile.

1. Classificazione dei Nuovi Strumenti e Artefatti

Abbiamo introdotto nuovi strumenti che devono diventare parte integrante del nostro workflow. Li classificherei così:

ArtefattoClassificazioneScopo e Ruolo
requirements.inFonte di Verità LogicaUn file scritto a mano che elenca solo le nostre dipendenze dirette e di alto livello (es. pandas, langchain). È l’unico file di requisiti che modificheremo.
pip-compileRisolutore DeterministicoLo strumento (pip-tools) che legge requirements.in e genera un lockfile completo, risolvendo l’intero albero delle dipendenze in modo coerente e trovando versioni compatibili.
requirements.lockFonte di Verità FisicaUn file generato automaticamente da pip-compile. Contiene ogni singolo pacchetto (diretto e transitivo) con la sua versione esatta e il suo hash. È la “fotografia” perfetta e riproducibile del nostro ambiente.
capture_environment.pyStrumento di ArcheologiaUno script di emergenza da usare su ambienti esistenti e non documentati per tentare di estrarne la configurazione. Non è per lo sviluppo quotidiano, ma per il recupero.

2. Definizione di Nuove Pratiche da Adottare

Dobbiamo introdurre nuove regole ferree nel nostro processo di sviluppo.

Pratica 1: Il Workflow “Lockfile-First”

  • Regola: Nessuno sviluppatore installa più pacchetti con pip install .

  • Processo:

    1. Aggiungere il nome del nuovo pacchetto a requirements.in.

    2. Eseguire pip-compile requirements.in —output-file=requirements.lock per aggiornare il lockfile.

    3. Eseguire pip install -r requirements.lock per sincronizzare l’ambiente.

    4. Committare su Git entrambi i file (requirements.in e requirements.lock).

Pratica 2: Gestione Esplicita delle Dipendenze Speciali

  • Regola: Qualsiasi dipendenza che non proviene da PyPI (es. da Git, locali, URL speciali) DEVE essere documentata e definita in requirements.in con la sua sintassi completa (es. timesfm @ git+…).

Pratica 3: Verifica dell’Ambiente come Prerequisito

  • Regola: Prima di iniziare una sessione di debug complessa, è obbligatorio verificare la salute dell’ambiente.

  • Comando: pip check (per verificare dipendenze installate) e un futuro script verify_environment.py.

3. Modifiche alla Documentazione Attuale

Le nostre guide di onboarding devono riflettere questa nuova realtà.

  • CONTRIBUTING.md:

    • Aggiungerei una nuova sezione principale: “Sezione 5: Gestione delle Dipendenze e dell’Ambiente”.

    • Questa sezione spiegherebbe il ruolo di requirements.in e requirements.lock e imporrebbe il Workflow “Lockfile-First” come unica modalità accettata per aggiungere o aggiornare le dipendenze.

    • Includerebbe una sotto-sezione sulla gestione delle “Dipendenze Speciali” (Git, ecc.).

  • Standard di Documentazione Architetturale:

    • Aggiungerei i file requirements.in e requirements.lock all’elenco degli artefatti architetturali critici del progetto, al pari di ARCHITECTURE-OVERVIEW.md, perché definiscono le fondamenta su cui poggia l’intera applicazione.

4. Cosa Aggiungerei (Le Mie Proposte)

Per capitalizzare appieno questa esperienza, propongo di creare due nuovi artefatti:

Proposta 1: Creare un Nuovo Documento di Policy: DEPENDENCY-MANAGEMENT.md

  • Scopo: Un documento dedicato che formalizza tutto ciò che abbiamo imparato. Sarebbe il “gold standard” per la gestione delle dipendenze.

  • Contenuto:

    • La nostra filosofia sulla riproducibilità.

    • Una descrizione dettagliata del nostro stack di strumenti (pip-tools).

    • Il workflow passo-passo per aggiungere, aggiornare o rimuovere una dipendenza.

    • Una sezione di “Troubleshooting” per errori comuni (ResolutionImpossible, ecc.).

    • La policy per l’introduzione di dipendenze non-PyPI.

Proposta 2: Creare un Nuovo Script di Utility: scripts/verify_environment.py

  • Scopo: Uno script che ogni sviluppatore può lanciare per avere una risposta immediata alla domanda: “Il mio ambiente è sano?“.

  • Funzionalità:

    1. Verifica che la versione di Python sia quella richiesta.

    2. Esegue pip check per trovare dipendenze rotte.

    3. Confronta l’output di pip freeze con il requirements.lock per trovare pacchetti mancanti o extra.

    4. Fornisce un output chiaro: ✅ Ambiente SANO o 🔴 ATTENZIONE: Ambiente non sincronizzato.

Queste aggiunte trasformerebbero la nostra dolorosa esperienza in un sistema robusto che previene attivamente il ripetersi di questo disastro.


Se sei d’accordo, possiamo adottare questo piano come nostra roadmap per la stabilizzazione. Il prossimo passo, a mio avviso, sarebbe creare e formalizzare il requirements.in e il requirements.lock per la nostra base v11.28 funzionante, e poi, finalmente, tornare a risolvere il bug dei grafici, che ora sono quasi certo risieda nel QCPlotlyChartWidget.py.