Il codice più prezioso è il codice che non dovresti scrivere

Il codice più prezioso è quello che non devi mai scrivere

Nelle mie precedenti articoli, ho scritto di come massimizzare il tuo vantaggio competitivo come sviluppatore software umano contro l’avanzata dell’IA. Ho illustrato perché sarà sempre difficile scrivere software utile, con o senza l’assistenza delle macchine. Una cosa a cui non ho dato risposta è come tutto questo possa togliere la gioia di scrivere codice. Non intendo i progetti Open-Source che fai con passione. Continua pure a farlo. Intendo i giganti delle imprese che scriviamo e manteniamo per uno stipendio. Per riassumere la discussione sull’efficienza e l’efficacia: se l’IA può scrivere quel codice allo stesso modo (al momento, è ancora un “se”), sarà quasi sempre più conveniente assumerla per fare il lavoro, oltre ad essere più affidabile (nessuna assenza per malattia) e più flessibile (ore straordinarie illimitate/nessun inserimento richiesto). Mi dispiace per questo.

La meccanizzazione ci libera dal lavoro manuale che è troppo duro, pericoloso o sporco. Nessun contadino medievale amava tirare una carriola. Quindi, usavamo cavalli e altri animali. Abbiamo inventato strumenti e macchine, e non solo per sostituire i muscoli. Ammettiamolo, anche se alcuni lavori mentali possono essere noiosi a farsi addormentare, la maggior parte non è particolarmente pericolosa o sporca. Ci sono delle eccezioni fastidiose, come la moderazione dei social media, ma gran parte di questa attività è stimolante e fa bene al cervello. Allora, perché dovremmo lasciare che l’IA faccia qualcosa che gli esseri umani già amano fare e che fanno bene, come scrivere sceneggiature o comporre canzoni? Un calcolatore cinico direbbe che non ha senso fare qualcosa a mano se la macchina può ottenere una qualità accettabile a un prezzo più basso. C’è un mercato di nicchia per capi di maglia fatti a mano, ma non ci sono abbastanza persone che sanno lavorare a maglia per vestire il mondo.

Se hai un buon datore di lavoro, gli importerà della tua salute e del tuo benessere, ma la loro preoccupazione principale non è garantirti un’esperienza di coding senza interruzioni, soprattutto quando l’IA potrà produrla a una frazione del costo attuale. Il codice è un mezzo per creare valore, ma è anche un costo. È costoso crearlo e mantenerlo, se possiamo ottenere lo stesso valore con meno (o senza) codice, tanto meglio.

Non so quando le competenze nelle lingue di programmazione tradizionali (con classi, tipi, variabili e strutture di controllo) diventeranno obsolete, ma prevedo che accadrà molto prima della mia pensione. Fino a quando non arriverà questa singolarità, l’abilità nel coding tradizionale (enigmi come l’Avvento del codice) diventerà sempre più una sfida mentale che i computer potranno affrontare meglio. Lo pratichiamo per divertimento o in competizione con altre persone. Come gli scacchi e il go.

Nel frattempo, per favore, tieni queste cose fuori dai colloqui tecnici. Non importa più, e non credo che abbia mai avuto importanza. Sapere come scrivere un’implementazione scadente di una lista di array o di un merge sort su una lavagna bianca cosa ti dice, esattamente? Che sai reinventare la ruota. Congratulazioni, ma credo che una competenza più preziosa per uno sviluppatore senior sia sapere quando non scrivere codice. Ecco perché presento l’intervista senza codice, basata su una sfida di programmazione in cui la decisione più saggia dovrebbe essere quella di lasciare tutto com’è.

Potrebbe essere così.

L’intervista senza codice

<strong:intervistatore: “Supponiamo di avere un’applicazione autonoma scritta in Java 6 con una GUI Swing molto semplice che legge un file XML, trasforma e arricchisce i dati effettuando diverse ricerche nel database e produce un report Excel. È stata creata e mantenuta da uno sviluppatore che ci ha lasciato un anno fa. Il nostro architetto senior ha esaminato il codice e ha deciso che la qualità è molto bassa. È la solita spaghettata, con pochi test unitari. Come procederesti per migliorarlo e portarlo a un buon livello?”</strong:intervistatore:

<strong:candidato: “Prima di guardare il codice sorgente, vorrei innanzitutto capire quanto urgente e quanto importante è questo refactoring. Perché sono due aspetti diversi.”</strong:candidato:

Intervistatore: “Come mai?”

Candidato: “Beh, la mia dichiarazione dei redditi annuale è molto importante, ma dato che mancano ancora sei mesi, non è urgente. D’altra parte, se voglio prendere un biglietto per il teatro stasera, è urgente ma non molto importante. Quindi, quanto è importante questo strumento per l’organizzazione? Quanti benefici offre e quanti danni può causare? Cosa succede se gli utenti non possono accedere allo strumento per un’ora? E per un giorno, una settimana? Cosa succede se produce dati errati? Quanti utenti si affidano a questo strumento? Quanto spesso viene utilizzato? E per urgenza, intendo quanto tempo possiamo permetterci di posticipare il lavoro? Gli utenti finali hanno un problema adesso? Funziona in modo affidabile in produzione? Ci sono state incidenti recenti? Quanto frequenti sono le richieste di modifiche? Quanto stabili sono le specifiche di input e output? Dipende da qualche tecnologia obsoleta che deve essere aggiornata o è richiesta dalla politica aziendale?”

Intervistatore: “Ottime domande. Per riassumere: l’applicazione viene utilizzata due volte l’anno per produrre l’input per un questionario interno. Il file in entrata è un dump dalla retribuzione ed è molto stabile. Le richieste di nuove funzionalità arrivano tre/quattro volte l’anno. Credo sia scritta in Java 6 e viene eseguita sulla macchina dello sviluppatore.”

Candidato: “Riguardo a queste richieste di nuove funzionalità: quanto è scomodo apportare modifiche?”

Intervistatore: “A quanto pare, è un grande fastidio. Abbiamo avuto due sviluppatori diversi che hanno apportato modifiche minori di recente e entrambi si sono lamentati dicendo che avrebbero potuto farle in una frazione del tempo se il codice fosse stato più leggibile.”

Candidato: “Erano simili queste richieste di funzionalità?”

Intervistatore: “Sì. Per lo più si trattava di aggiungere o rimuovere una colonna nell’output.”

Candidato: “Eppure il secondo sviluppatore si è lamentato comunque che ci ha messo troppo tempo. È giusto pensare che il primo sviluppatore non ha documentato il processo e non ha fatto alcun refactoring?”

Intervistatore: Touché

Candidato: “Questo è già il tuo primo piccolo successo. Ma ho l’impressione che un rinnovamento completo non sia né importante né urgente, quindi non lo consiglierei. Lo sforzo dovrebbe essere rivolto a rendere meno dolorosi i cambiamenti incrementali. Rifattorizza con questo obiettivo in mente.”

Intervistatore: “Mi piacciono le tue risposte finora. Ora, supponiamo ti dicessi che lo strumento è molto utilizzato e gli errori sono inaccettabili. Supponiamo di essere un’azienda bancaria e calcola un tasso di interesse per un’offerta di prestito. Un errore potrebbe significare che addebitiamo o addebitiamo ai clienti somme di milioni. Le richieste di nuove funzionalità sono frequenti e varie, e l’azienda ci chiede di adeguarla agli standard. Come ti metteresti al lavoro?”

Candidato: “Che ne dici della copertura dei test unitari?”

Intervistatore: “Inferiore al 20%”

Candidato: “Se un datore di lavoro fosse così leggero riguardo a un componente così critico per il business, non credo che vorrei lavorare per loro. Quindi, sono contento che sia solo ipotetico. Dobbiamo affrontare la copertura dei test prima di toccare qualsiasi sorgente. Il rischio di regressione è troppo grande se si inizia il rifattorizzazione senza di essa. Creare test unitari dettagliati probabilmente non è fattibile se tutto è strettamente accoppiato. Cominciamo con un singolo test di componente black-box. La base di codice è fragile, quindi con ogni modifica, dovremmo assicurarci di non aver rotto nulla.

Crea un file di input XML rappresentativo e un database contenitore. Esegui l’applicazione una volta e prendi il file Excel che produce come riferimento. Ora, ogni volta che il test di componente esegue l’applicazione con lo stesso input e lo stesso stato del database, l’output dovrebbe corrispondere al file di riferimento pezzo per pezzo (a meno che non si basi sulla data/ora corrente in qualche punto). Ora puoi iniziare a decouplare l’I/O del file e l’accesso al database dalla logica di business e creare test unitari adeguati senza il rischio di rompere nulla. Ma poiché stai aggiungendo test come un’idea secondaria, dimentica l’ortodossia del TDD. Il vantaggio di scrivere test contemporaneamente al codice di produzione è già svanito. Probabilmente scoprirai che il tuo singolo test di componente ha già aumentato la copertura del 30%.”

Intervistatore: “La mia ultima domanda. Non ti piace un buon codice?”

Candidato: “Certo che mi piace. Ma amo di più un software utile. Sono sicuro che ci sono ottime applicazioni con un codice sorgente terribilmente poco pulito sotto il cofano. Lo stesso qui. Il codice potrebbe ferire il nostro senso di maestria, ma non è rotto a meno che non abbiamo un problema acuto o imminente. E questo può accadere dopo un bene intenzionato miglioramento. Fai questi miglioramenti solo in risposta a effettive richieste di funzionalità. Limita il tempo dedicato a questo, in tal caso. È allettante portare un voto F a un voto A, ma raramente ha senso dal punto di vista del business.”