La frattura
Immagina Tommaso e Sandro, due Senior davanti allo stesso ticket Jira: «Aggiungere l’esportazione in CSV alla pagina dei report». Nella mia esperienza, questo passa già per un buon ticket. Hanno a disposizione lo stesso agente e un’ora di lavoro.
Tommaso legge e parte. Descrive il compito all’agente, ottiene una funzione pulita, la collega al bottone e verifica che il file venga scaricato. In cinquanta minuti la funzionalità è pronta. Risponde alla richiesta e chiude il ticket.
Sandro, prima di scrivere qualsiasi cosa, si ferma su una parola: report. «Quali report?», si chiede. Verifica chi userà l’esportazione, con quale frequenza e dentro quale processo. Scopre che il CSV non è il reale bisogno della richiesta, bensì una soluzione che il ticket contiene già. Gli utenti vogliono riconciliare i numeri con un altro sistema di rendicontazione, e l’esportazione trasferirebbe su di loro un passaggio manuale quotidiano. Si aprono così domande che il ticket iniziale non conteneva: chi possiede il dato, quale formato accetta il sistema di rendicontazione, come vengono gestiti errori e duplicati, chi risponde quando la riconciliazione non ha successo. Prima di costruire, Sandro riapre la richiesta: forse serve una vista, forse un’integrazione, forse il CSV resta il compromesso meno costoso. Non ha ancora tutti gli elementi per scegliere l’implementazione corretta.
Tommaso ha prodotto codice conforme alla lettera del ticket prima di chiarire il problema. Sandro, per quasi tutta l’ora, non ha prodotto codice, ma ha evitato che una soluzione non ancora giustificata diventasse subito software da mantenere.1
Questa scelta ha un costo, per l’azienda e per Sandro. Il ticket resta aperto, bisogna coinvolgere gli utenti e la consegna slitta. Dopo il confronto con loro si potrebbe perfino decidere di rilasciare comunque il CSV, ma come soluzione ponte, accettandone il lavoro manuale e fissando il momento in cui rivederla. Il costo resta, ma non è più nascosto dentro una richiesta apparentemente già risolta.
Sandro non ha scritto codice migliore. Ha riconosciuto che, in quel momento, il problema non era eseguire: bisognava prima decidere che cosa valesse la pena costruire. Il codice, lì, non era il fattore limitante.
Il fattore limitante si è spostato
Per molto tempo, tradurre una decisione in codice richiedeva competenza e assorbiva gran parte della giornata di uno sviluppatore. Era un passaggio obbligatorio, e la velocità con cui lo si faceva era facile da osservare e misurare. Era naturale finire per usare quella capacità come indice del contributo professionale, e spesso era anche ciò per cui si veniva pagati.
Oggi, in una parte crescente di quel lavoro, ottenere codice plausibile richiede molto meno tempo. Questo guadagno non rende facile produrre codice corretto, integrato, sicuro e mantenibile; nei domini critici, nel legacy intricato e nei problemi algoritmici duri, produrre codice di quel livello può restare il collo di bottiglia. Il guadagno di tempo significa soltanto che ottenere in fretta una funzione dall’aspetto credibile non basta più a dimostrare che sia quella giusta. Quando l’esecuzione accelera, il fattore limitante si sposta, e con esso il valore: dove si concentra, ora?
Il limite si sposta sulla decisione: che cosa vale la pena costruire? Per rispondere bisogna leggere una richiesta insieme al processo di business che dovrebbe servire, ai dati che tratta, al codice e ai servizi con cui dovrà integrarsi, all’infrastruttura che dovrà sostenerla e all’operatività di chi ne gestirà gli errori. Bisogna riconoscere, in un requisito di una riga, l’ambiguità che costerà cara; sapere quale errore è recuperabile e quale no; rispondere delle conseguenze quando il sistema è in produzione alle tre di notte. L’accelerazione dell’esecuzione non risolve nessuno di questi problemi; permette soltanto di percorrere più in fretta anche una direzione sbagliata.
Questa è la visione d’insieme che il ticket affidato a Tommaso e Sandro non contiene. La richiesta delimita una modifica, ma il Senior deve vedere oltre: dove quella modifica atterra e che cosa cambia nel sistema. Non perché conosca in anticipo ogni dettaglio, ma perché attraversa i domini coinvolti con le domande che ne fanno emergere i confini.
L’agente può ricostruire dipendenze, esplorare il sistema e ampliare l’indagine, e in questo lavoro diventare indispensabile; può perfino proporre domande che il Senior non aveva considerato. Il contributo specifico del Senior sta nel riconoscere quali domande qualificano davvero il problema, quali risposte cambiano la direzione e quali conseguenze sono accettabili.
L’esperienza del Senior non è soltanto un archivio di risposte: è una gamma di domande con cui riconoscere il sistema nascosto dentro una richiesta locale.2
Non è un aggiornamento, è una frattura
Lo spostamento del limite sulla decisione è reale; resta da capire di che natura sia. La generazione di codice guidata da un modello può sembrare un altro miglioramento degli strumenti a disposizione degli sviluppatori, una sorta di «IntelliSense 2.0». Non è così. Per chi, come me, ha legato il proprio contributo professionale all’esecuzione manuale, quella generazione produce una discontinuità molto più profonda: cambia il modo in cui si definisce il ruolo dello sviluppatore.
Linguaggi più espressivi, librerie e IDE visuali hanno già spostato molte volte il confine tra ciò che si scrive a mano e ciò che si affida agli strumenti. Un agente consente però di affidare a un sistema una porzione più ampia dell’esecuzione: esplora, propone e modifica artefatti attraverso più passi, oltre alla codifica autonoma.
La frattura di cui parlo riguarda il terreno sul quale hai costruito la tua identità professionale: la capacità di produrre codice. È proprio quel terreno a cedere. «Il codice lo scrivo bene e in fretta», qualità e velocità insieme, conta di meno come misura del tuo contributo. Saperlo fare resta necessario, ma non basta più a dire dove hai portato valore. Perdere il metro con cui ti misuravi è ciò che disorienta.
Si indebolisce l’idea del programmatore come macchina che traduce il pensiero in codice. Acquista più peso la responsabilità sull’intero percorso della soluzione: comprendere il problema, dirigere l’esecuzione, verificare il risultato e seguirne le conseguenze nel sistema.
Il mestiere non è scomparso: il suo baricentro si è soltanto spostato.
Perché le due tentazioni sbagliano bersaglio
Davanti a questo spostamento emergono due reazioni opposte. La prima è il rifiuto: continuare a scrivere tutto a mano per difendere il mestiere. La seconda è la resa: lasciare fare all’agente e limitarsi ad accettarne l’output. Sembrano incompatibili, ma condividono lo stesso errore. Continuano a misurare il valore sul terreno del codice.
Il rifiuto difende quel terreno proprio mentre, in molti casi, l’esecuzione manuale smette di essere il principale collo di bottiglia: vi si arrocca come se coincidesse con il mestiere. La resa presume invece che, tolta l’esecuzione, non resti altro da fare. Ignora una distinzione già posta nei Fondamenti: l’agente può esplorare alternative, formulare valutazioni e prendere decisioni operative circoscritte, ma la responsabilità finale e le decisioni direzionali designate non passano automaticamente insieme all’esecuzione.
Entrambe guardano ancora a quanto codice viene prodotto, proprio mentre la frattura chiede di valutare la direzione e le conseguenze.
Che cosa resta
Resta il giudizio.
È il principio da cui parte tutto il resto del libro: il valore di un Senior risiede nel suo giudizio, non nella quantità di codice che produce. Sandro non è stato più bravo a scrivere codice: non ne ha scritto affatto. Ha riconosciuto che il requisito conteneva già una soluzione non ancora giustificata, e l’ha ricollocata nel sistema tecnico e di business dell’azienda. Il risultato non si misura in righe: il giudizio di Sandro ha orientato il lavoro.
Nella storia di Sandro i tre livelli si distinguono con nettezza. Ciò che deve restare vero per soddisfare il bisogno è il principio; interrogare la richiesta e confrontare le alternative è il metodo; la funzione CSV, la vista o l’integrazione sono implementazioni contingenti. Produrne una è soprattutto esecuzione, proprio il livello che oggi costa meno. Il giudizio, invece, attraversa tutti e tre i livelli e li tiene insieme: riconosce quale principio è in gioco, valuta i compromessi e assume la responsabilità della direzione scelta. Per questo la frattura non elimina il lavoro del Senior: lo porta in primo piano.
Il giudizio è meno facile da vedere del codice scritto: se ne osservano le decisioni, le ragioni e le conseguenze, non una quantità prodotta e misurabile. Passare un’ora a capire che stavi per costruire la cosa sbagliata, e non avere una riga di codice da mostrare a fine giornata, ti fa sembrare di non aver lavorato affatto.
Per anni hai imparato a sentirti produttivo quando l’editor si riempiva. La frattura ti chiede di disimparare quel riflesso e di trovare un altro modo, meno immediato, di riconoscere una giornata ben spesa: non da quanto hai prodotto, ma dalle scelte che hai orientato.
Una parola che dice troppo
«Giudizio» è però una risposta che apre subito un problema: la parola può voler dire troppe cose.
Una parte di questo giudizio sembra affiorare senza sforzo: una domanda posta prima ancora di sapere perché, un rischio intravisto ai margini del ticket, il ricordo impreciso di un sistema che si era rotto nello stesso modo. Sono segnali che vengono da anni di esposizione a sistemi reali, e che il Senior porta con sé anche quando non saprebbe formularli come una regola. Ma chiamarli «esperienza» non dice ancora perché a volte portano fuori strada.
Finché la parola tiene insieme fenomeni diversi, non si capisce che cosa distingua il giudizio da un’abitudine, né come il confronto con un agente possa renderlo più esplicito. Il capitolo che segue prova a separarli.
Costruire una soluzione non ancora giustificata che poi andrà mantenuta alimenta ciò che in inglese si chiama product debt, per analogia con il technical debt: il costo futuro di aver costruito la cosa sbagliata, quando il codice diventa una passività da testare, aggiornare e infine rimuovere.↩︎
Leggere una richiesta locale come parte di un sistema più ampio, con i suoi processi, input, output e punti di rottura, invece che come compito isolato, è ciò che in inglese si chiama systems thinking.↩︎