Pair programming + AI: un connubio possibile?
Possiamo immaginare di fare pair programming non con un’altra persona ma con l’intelligenza artificiale? Questa domanda, che può sembrare una provocazione, apre invece una serie di riflessioni molto interessanti e, forse, più attuali di quanto pensiamo. Prima di cominciare a vedere l’argomento in maniera più approfondita, però, è necessario un breve disclaimer:
- nessuna intelligenza artificiale è stata maltrattata per scrivere questo articolo (qualche saltuario accidenti a parte);
- non parleremo nel dettaglio di machine learning o AI, ma vogliamo approfondire l’idea che l’intelligenza artificiale, insieme all’apprendimento guidato o all’autoapprendimento, possa entrare nella vita degli sviluppatori e aiutarli a creare software migliore e di maggiore qualità.
Machine learning vs. Deep learning
È necessario, inoltre, fare una piccola parentesi per chiarire la differenza tra machine learning e deep learning: due termini che sentiamo usare spesso e che hanno alcune differenze sostanziali.
Immaginiamo di avere come input un cane e di dover classificare se è cane o non cane.
Con il machine learning, una persona deve estrarre le caratteristiche per capire se quell’immagine è considerabile un cane (coda, zampe, etc.) e una rete neurale viene addestrata per la sua classificazione. Una volta addestrata, la rete neurale è in grado di classificare in modo corretto se quello che “vede” è cane o non cane
Con il deep learning, l’apprendimento non è supervisionato da una persona: l’estrazione delle caratteristiche e la classificazione viene fatta direttamente dalla rete neurale.
Chiarito il significato di queste tecniche, vedremo in questo articolo come vengono sfruttate da strumenti, sia open source che a pagamento o in fase sperimentale, per aiutarci a scrivere codice migliore.
Che cosa è il pair programming
Il pairing è un aspetto molto importante nelle buone pratiche di Extreme Programming (XP): due persone lavorano a coppia sullo stesso codice, “aiutandosi” l’un l’altro con delle previse metodiche e dei ruoli che si alternano, in maniera tale da migliorare il processo di programmazione. Il pair programming, infatti:
- aiuta a essere più attenti e produttivi quando si sviluppa codice;
- permette di ridurre errori durante lo sviluppo del codice;
- aiuta a condividere la conoscenza;
- una volta che si fa anche a rotazione nel team, diventa uno strumento di team building.
Quando si lavora in team, non è facile scrivere codice in pair programming. Ciascuno, solitamente, scrive il proprio pezzo di codice sul proprio computer e sul proprio schermo. Creatività e design del codice rimangono nella mente delle persone e vengono tradotte in codice dal singolo sviluppatore, ognuno sul proprio schermo.
C’è poca collaborazione — che può essere sicuramente migliorata con Continuous Delivery e altre pratiche — e, in linea di massima, questo approccio rallenta, riduce e postpone i momenti di collaborazione.
Oltre la semplice scrittura di codice
Sappiamo però che realizzare software non è solo una questione tecnica ma è un momento di forte collaborazione tra le persone. È quindi importante trovare dei momenti per fare pairing.
Driver e navigator sono i ruoli tipici dell’attività di pair programming; lavorano con la stessa code base e nello stesso momento, e insieme programmano e soddisfano dei requisiti attraverso la scrittura di codice.
Il driver pensa in modo tattico a come incrementare una funzionalità ed esprime, ad esempio, l’intenzione “filtro lo stream per passarlo a C”.
Il navigator, invece, essendo mani alla tastiera, può avere la visione d’insieme sul perché si sta facendo una determinata azione e può dire: “Perchè non lo mandi a B invece che mandarlo a C?”.
Quella che abbiamo appena descritto è la dinamica tipica di quando si fa pair programming.
TDD (Test Driven Development)
Un altro aspetto importante da affiancare al pairing è il Test Driven Development (TDD). Scrivere un test, scrivere il codice per passare un test e fare refactoring fino a quando il codice è pulito in modo accettabile è fare TDD.
Questo ciclo rapido da fare ogni 10 minuti aiuta a scrivere codice più pulito e semplice perché fa solo quello che serve e niente di più: è testabile e con responsabilità chiare.
Un approccio TDD permette di scrivere codice documentato e manutenibile dalle persone nel tempo; non è quindi un aumento di costi ma anzi una riduzione sia di costi che di tempi di sviluppo perché si vanno a ridurre con certezza problemi che possono emergere successivamente in produzione, o a evitare complessità di codice che non verrà poi realmente utilizzato.
Quante volte ci capita di implementare un’intenzione che non serviva strettamente alla funzionalità che stavamo sviluppando?
Pairing e TDD
Da una parte il pairing, dall’altra il test. Ora proviamo a metterli insieme.
TDD lo facciamo da soli? Si può, però non è così divertente. La cosa migliore sarebbe farlo insieme: aiuta a condividere la conoscenza, a concentrarsi sull’obiettivo e a non disperderlo facendo over-engineering. Quante volte ci sarà capitato di scrivere un pezzo di codice e poi di decidere di aggiungere una parte che pensiamo ci servirà, credendo di avere una sfera di cristallo che ci permette di sapere oggi cosa ci servirà domani?
Tipicamente poi cambiano i requisiti e quella funzionalità si rivela inutile e rimane un pezzo di codice che non serve a nulla.
Facendo TDD insieme, se una delle persone inizia ad andare alla deriva verso la scrittura di qualcosa che esula dall’obiettivo, può essere fermato dal navigator che pone attenzione su quell’aspetto.
Il pair programming può essere efficace anche se iniziamo a farlo in una modalità a ping pong: scrivo un test e passo la palla all’altra persona che scrive codice per soddisfarlo, e poi l’altra persona scrive un test e io scrivo codice in grado di superarlo. In questo modo ci si alterna tra driver e navigator come vuole l’etichetta di un pair efficace e funzionante.
Pair e TDD non vengono fatti così spesso: perché?
Fondamentalmente perché è faticoso: stare con una persona tutto il tempo, essere disciplinati, non andare alla deriva con soluzioni che ci piacciono ma non servono, avere un forte affiatamento col compagno di lavoro, sono tutte cose che richiedono impegno, attenzione e disponibilità.
La voglia di isolamento spesso prende il sopravvento: a tutti piace mettere le cuffie e scrivere codice nel flow. Facendo così, si scrive codice che funziona ma magari non è testabile, manutenibile o pulito.
E l’intelligenza artificiale?
Queste difficoltà non ci fanno però abbandonare del tutto l’idea di fare pair programming e oggi vogliamo infatti provare a sperimentare come si possa farlo in compagnia dell’intelligenza artificiale e non con una persona reale.
Sappiamo però che un programma non può scrivere un programma, e quindi come può funzionare? Cominciamo co lo stabilire i ruoli: la persona è il navigator, colui che ha presente le intenzioni e la big picture, mentre il driver è impersonato dall’Intelligenza Artificiale.
La persona espone la sua intenzione: “Mi aspetto di passare a B i soli record che soddisfano la seguente condizione”. L’AI “sa” cosa vuol dire “passare” e “soddisfare la condizione” e quindi sa applicare probabilmente un filtro, lo implementa e chiede l’OK per proseguire.
Qualcosa di questo processo potrebbe essere considerato come un ciclo di apprendimento da parte dell’AI? Da un certo punto di vista il programmatore non va a descrivere come deve essere scritto il codice, ma solo quali risultati vuole ottenere da questo codice; l’AI, opportunamente addestrata, può fornire possibili implementazioni per una determinata intenzione. Più l’intenzione è scritta in modo formale, più è efficace, e a quel punto c’è l’OK di verifica in cui l’intelligenza artificiale chiede: “Funziona?”
Quindi? AITDD
Mettere insieme AI e TDD significa creare un processo iterativo in cui è fondamentale anche l’aspetto dell’apprendimento.
- Scrivo un test in modo formale.
- Chiedo alla mia AI di implementare qualcosa che soddisfi il test.
- Verifico che il codice implementato effettivamente soddisfi il test; se non lo soddisfa, implemento io come umano il pezzo di codice oppure lo correggo per dare un rafforzativo alla mia AI che impara così a classificare meglio.
- Insieme possiamo fare refactoring fino quando il codice è pulito.
Ora vi starete chiedendo se esista già qualcosa di simile. La risposta è: “non ancora”; ma sarebbe molto interessante perché ci farebbe fare il lavoro puro: quello di esprimere e definire l’intenzione dei componenti software e delegare la scrittura di pezzi di codice che a volte sono banali a un’intelligenza artificiale.
Conclusioni
Abbiamo visto in questo articolo un’ipotesi di lavoro in cui le pratiche del pair programming e del TDD vengono combinate con l’ausilio di una applicazione di intelligenza artificiale che assume il ruolo di driver nella coppia di programmatori. Se è vero che una tale soluzione al momento non è ancora implementata, nel prossimo articolo vedremo però qualcosa di più “concreto” che potrà risultare interessante per molti lettori.