Perché il software di qualità richiede tempo
Perché i migliori progetti software richiedono anni, non mesi. La pazienza in ingegneria, dall'open source alle startup.

Flask ha impiegato otto anni per arrivare alla versione 1.0. SQLite è in sviluppo attivo dal 2000 e riceve ancora miglioramenti significativi. Il kernel Linux ha più di tre decenni e si può sostenere che stia diventando migliore con l'età. Nel frattempo, da una startup finanziata da VC ci si aspetta che mostri trazione entro 18 mesi, o che spieghi perché no.
C'è un distacco crescente tra quanto tempo serve davvero per costruire un buon software e quanto ci aspettiamo che ne serva. La pressione per rilasciare in fretta non è di per sé sbagliata, ma crea una cultura in cui la pazienza viene vista come mancanza di ambizione, e in cui i progetti che durano vengono liquidati come «lenti» proprio negli anni in cui stanno silenziosamente facendo le cose per bene.
Il mito del successo improvviso
Quasi ogni «successo improvviso» nel software ha una lunga storia alle spalle. React è stato usato internamente da Facebook per oltre un anno prima di essere reso open source. Rust ha passato sette anni in sviluppo prima di arrivare alla 1.0. PostgreSQL nasce come progetto di ricerca nel 1986 e non diventa il database di riferimento per la produzione fino agli anni 2010: quasi trent'anni di miglioramenti silenziosi e costanti.
Ciò che sembra un'emersione improvvisa è di solito il risultato di miglioramenti che si accumulano fino a superare una soglia di visibilità. Il software stava migliorando per tutto il tempo. Semplicemente, la gente non ci faceva caso finché non è diventato abbastanza buono da non poter essere ignorato.
Armin Ronacher, il creatore di Flask, ne ha scritto apertamente. Flask è nato come scherzo del Primo d'aprile nel 2010. È diventato un progetto serio quasi per caso. Anni di lavoro incrementale (correggere casi limite, migliorare la documentazione, ripensare le API) lo hanno trasformato in uno dei framework web Python più popolari. Nessuno di quegli anni è stato sprecato. Ognuno ha reso le fondamenta più solide.
Perché il software ha una componente di tempo incomprimibile
Alcuni problemi non si risolvono più in fretta aggiungendo persone o lavorando di più. Fred Brooks lo ha identificato nel 1975 con The Mythical Man-Month, e l'idea centrale non è cambiata: alcuni aspetti dello sviluppo software sono sequenziali, non parallelizzabili.
- Comprendere il dominio del problema. Non puoi capire davvero uno spazio problematico finché non ci hai lavorato per un po'. La prima versione di qualsiasi software incorpora le tue ipotesi iniziali. La seconda incorpora ciò che hai imparato dalla prima. Una vera comprensione richiede iterazioni, e le iterazioni richiedono tempo.
- Design e stabilità delle API. Le buone API nascono dall'uso. Non puoi progettare un'API perfetta nel vuoto: hai bisogno di utenti reali che incontrino casi limite reali. Le librerie che si affrettano verso la 1.0 spesso si pentono per anni delle decisioni di design prese all'inizio.
- Casi limite e robustezza. Il primo 80% di una funzionalità richiede il 20% del tempo. I casi limite rimanenti, la gestione degli errori e le stranezze delle piattaforme richiedono l'altro 80%. Questo rapporto non è pigrizia: è la natura fondamentale del rendere affidabile il software.
- Community ed ecosistema. Uno strumento non è davvero utile finché non ha documentazione, tutorial, plugin e una community che risponde alle domande. Questo ecosistema non si può fabbricare; cresce in modo organico nel tempo.
I danni della fretta artificiale
«Muoviti in fretta e rompi tutto» era un motto ragionevole per un social network che cercava il product-market fit. È una pessima filosofia per l'infrastruttura, gli strumenti per sviluppatori, i database o qualsiasi cosa da cui dipendono i sistemi altrui. Quando hai fretta con il software di base, i danni si accumulano.
Ho visto diversi progetti open source promettenti collassare perché cercavano di crescere più in fretta di quanto le loro fondamenta potessero reggere. Lo schema è prevedibile: un progetto diventa popolare, i maintainer sentono la pressione di rilasciare funzionalità in fretta, la qualità cala, i contributor si esauriscono e gli utenti migrano verso qualcosa di più stabile. L'ironia è che rallentare li avrebbe portati più lontano.
I progetti che durano non sono quelli che hanno rilasciato più in fretta. Sono quelli che hanno preso decisioni giuste abbastanza presto da non dover riscrivere tutto in seguito.
Il debito tecnico non riguarda solo il codice disordinato. Riguarda le decisioni prese sotto pressione dei tempi, che limitano le possibilità future. Ogni scorciatoia presa per andare più veloci è una tassa su ogni modifica futura. Alcune scorciatoie valgono la pena, ma dovresti prenderle deliberatamente, non perché qualcuno ha deciso arbitrariamente che la scadenza è il prossimo martedì.
Come si presenta la pazienza nella pratica
La pazienza nello sviluppo software non significa muoversi lentamente per il gusto di farlo. Significa essere deliberati su ciò che costruisci e onesti su quanto tempo serve alle cose. Alcuni schemi che ho visto funzionare bene:
- Rilascia presto, ma impegnati lentamente. Rilascia il tuo software agli utenti in fretta, così ottieni feedback, ma sii molto prudente su ciò a cui ti impegni come API stabile. Usa generosamente il versionamento 0.x. Chiarisci che le cose potrebbero cambiare.
- Dì no alle funzionalità. Ogni funzionalità che aggiungi è una funzionalità che manterrai per sempre. I migliori progetti sono opinionati sul proprio perimetro. SQLite elenca esplicitamente le cose che non farà mai, e proprio questa disciplina è il motivo per cui è il database più diffuso al mondo.
- Investi nelle fondamenta. Documentazione, test, messaggi di errore, prestazioni: non sono glamour, ma si accumulano. Un progetto ben documentato con una solida suite di test può andare più veloce al terzo anno di uno scarsamente documentato al primo.
- Proteggi l'energia dei maintainer. Il burnout è il primo killer dei progetti open source. Un ritmo sostenibile conta più della velocità negli sprint. Un maintainer che lavora 20 ore concentrate a settimana per cinque anni rilascia più di uno che lavora 80 ore a settimana per sei mesi e poi sparisce.
La trappola della velocità nelle startup
Le startup affrontano una tensione legittima: devono muoversi in fretta per sopravvivere, ma muoversi troppo in fretta crea sistemi fragili che diventano un passivo man mano che crescono. Le aziende che se la cavano meglio tendono a distinguere tra due tipi di velocità.
Velocità di iterazione: quanto rapidamente puoi testare idee, raccogliere feedback dagli utenti e cambiare direzione. Va massimizzata. Cicli brevi, prototipazione rapida, disponibilità a buttare via le cose.
Velocità di impegno: quanto rapidamente blocchi decisioni architetturali, API pubbliche e modelli di dati. Va minimizzata. Mantieni le cose reversibili il più a lungo possibile. Più a lungo riesci a rimandare le decisioni irreversibili, più informazioni avrai quando finalmente le prenderai.
L'errore più comune delle startup è confondere le due cose. Si impegnano in architetture alla stessa velocità con cui iterano sulle funzionalità, e poi passano i due anni successivi a pagare il conto delle decisioni premature.
Imparare dai progetti che hanno resistito
I progetti software su cui facciamo più affidamento condividono un tratto comune: a un certo punto sono stati tutti considerati «lenti». PostgreSQL era la scelta noiosa mentre MySQL era l'opzione veloce e disinvolta. Python era «troppo lento» mentre Perl era la scelta pragmatica. Git ha impiegato anni prima di diventare utilizzabile da comuni esseri umani.
Ciò che questi progetti hanno avuto è il tempo: il tempo di sbagliare, imparare dagli errori e costruire qualcosa di solido. Non hanno cercato di essere tutto per tutti nel primo anno. Hanno cercato di eccellere nel loro scopo principale, e sono stati disposti a lasciare che quell'eccellenza richiedesse il tempo necessario.
La prossima volta che ti irriti perché un progetto sta «impiegando troppo tempo», considera che le cose su cui fai più affidamento (il tuo sistema operativo, il tuo database, il runtime del tuo linguaggio, il tuo version control) hanno tutte richiesto più tempo di quanto chiunque si aspettasse. Ed è proprio per questo che funzionano.
Alcune cose richiedono semplicemente tempo. La risposta migliore non è combattere questa realtà, ma costruire sistemi, team e aspettative che la tengano in conto.


