Agile & Architecture: un rapporto complicato
In un recente articolo [1] su MokaByte, Giovanni Puliti ci ha parlato del Manifesto Antifragile; in particolare ho apprezzato il paragrafo che affronta la misurazione del rischio. Riprendendo il pensiero di Nicolas Taleb ne Il Cigno Nero, Giovanni ci ricorda che lo studio della gestione del rischio non è lo studio di un evento prevedibile e collocabile nel futuro, come invece succede nella realtà, e soprattutto nel mondo esplorato da Taleb. La sua esplorazione è rivolta in particolare all’applicazione dei principi dell’Antifragilità nelle organizzazioni; possiamo estendere tutto questo a livello architetturale?
Quando si parla di Agilità, il ruolo che ricopre — o dovrebbe ricoprire — l’architettura non è più un semplice argomento di discussione, ma parte del motivo per cui le iniziative Agile falliscono e i software architect sono sempre meno credibili. Un sondaggio condotto da IASA Global pochi anni fa su un campione di 260 aziende rivela che più del 75% sta implementando una forma di pratica Agile. Delle aziende interpellate, meno del 50% hanno integrato l’architettura all’interno dei loro processi Agili. Il quadro generale che emerge è che, al momento, Agile e Architettura stanno ancora lottando per trovare una forma di collaborazione.
Secondo questo paper esiste una terza soluzione, ossia Agile attraverso Antifragile. Vale a dire, piuttosto che sforzarsi di controllare o di rimuovere il controllo stesso, cerchiamo di costruire sistemi, sia tecnici che di business, che puntino a essere Antifragili rispetto al cambiamento. Questo approccio permette la realizzazione di architetture che abilitano l’Agilità attraverso la capacità di essere antifragili al cambiamento.
VUCA: serve un nuovo approccio
La situazione in cui ci troviamo oggi sembra essere troppo complicata per essere affrontata con pratiche descritte in manuali datati di oltre vent’anni. Come descrive Taleb nei suoi libri (Antifragile e Il cigno nero) serve un approccio che crei sistemi in grado di prosperare nel caos, non di controllarlo o dominarlo.
Il mondo è in continua mutazione, il business cambia continuamente, e così le richieste che ci arrivano dai Clienti che ci chiedono continui cambiamenti, o nuove implementazioni, ai software che abbiamo implementato o, peggio, stiamo ancora progettando. Si parla di scenari VUCA, acronimo creato a partire dalle parole Volatility, Uncertainty, Complexity, Ambiguity. Di questa capacità di prosperare nella volatilità, nell’incertezza sembra proprio essercene un gran bisogno oggigiorno. Stiamo entrando in una nuova fase della crisi del software, che già era stata analizzata in un rapporto della NATO nel 1968 [2], ma le conseguenze sembrano essere più serie.
Come ci suggerisce Nicholas Negroponte [3]
Computing is not about computers anymore. It’s about living
A fronte di questa analisi, il mondo VUCA sembra necessitare di un nuovo approccio.
Accettare la complessità
Nei primi anni di questo secolo, Dave Snowden, durante il suo lavoro alla IBM, sviluppò un’“infrastruttura concettuale” per indagare e classificare la complessità, il Cynefin (/kəˈnɛvɪn/), termine gallese che significa habitat.
I sistemi aziendali contemporanei, secondo questo framework, non sono classificati semplicemente complicati, sono classificati come complessi. Un sistema è complesso perché non risponde in modo lineare agli input, ai cambiamenti. Per risolvere un problema di business creiamo un modello del sistema; il modello, per sua stessa natura, è una semplificazione della realtà, perché sarebbe impossibile replicare esattamente il mondo reale; una citazione di Rebecca Wirfs Brook esprime chiaramente il concetto:
A model is a simplified representation of a thing or phenomenon that intentionally emphasizes certain aspects while ignoring others. Abstraction with a specific use in mind.
Cosa rende fragile un sistema?
I problemi nascono proprio nel momento in cui il modello semplificato della realtà è troppo distante dalla stessa, e le risposte che ci fornisce, se ancora è in grado di farlo, non sono più valide! È quanto descritto da Nassin Nicholas Taleb nel libro Il Cigno Nero. I problemi di business appartengono proprio alla categoria dei sistemi complessi, hanno comportamenti imprevedibili, e tentare di risolverli con pratiche inadeguate porta al fallimento dei progetti, proprio a causa della piega platonica descritta da Taleb. La soluzione a questo problema è accettare la complessità come qualcosa che non possiamo né predire, né tantomeno controllare: possiamo solo costruire sistemi antifragili, in grado di diventare più forti e resilienti al cambiamento del business nel tempo.
Il grado di fragilità di un sistema è generalmente funzione della sua struttura interna, di come è stato progettato. La sua abilità al cambiamento, come abbiamo già visto in precedenti articoli, dipende dal grado di interconnessione delle sue parti, quanto queste sono accoppiate fra loro, più che che coese. È fondamentale, per l’evoluzione del sistema, che le singole parti non siano accoppiate fra loro, in modo da poter intervenire con facilità su ognuna di esse senza il timore di fare danni sulle altre.
Approcci orientati al cambiamento
Tuttavia, nel 1972, David Parmas, pioniere dell’ingegneria del software, ha sollevato un ampio dissenso sul concetto di modularizzazione del software affermando che è possibile costruire sistemi software migliori focalizzando l’attenzione su cosa cambierà piuttosto che su ciò che accadrà a livello funzionale. Juval Lowy, tramite il suo approccio IDesign [4] pone l’attenzione tra decomposizione funzionale e volatilità e propone alcune alternative che ne semplificano la realizzazione.
Questi approcci, a differenza di altri che si focalizzano sulla modularizzazione, si concentrano sugli elementi che possono cambiare, più che su requisiti concreti che soddisfano bisogni immediati. Il libro Anti-fragile ICT System [5] di Kjell Jørgen Hole descrive le proprietà che hanno i sistemi antifragili:
- modularità: componenti indipendenti, collegati fra loro;
- legami deboli: basso livello di accoppiamento fra i componenti;
- ridondanza: presenza di più istanze di un componente, per far fronte ad un guasto;
- diversità: la capacità di risolvere un problema in modi diversi con componenti diversi.
Dobbiamo cambiare il modo in cui progettiamo i nostri sistemi se vogliamo affrontare le sfide proposte dall’analisi VUCA. Seguendo i suggerimenti di Taleb, Parmas e Lowy, dobbiamo concentrarci su ciò che non sappiamo, accettando i nostri limiti e la nostra capacità limitata di prevedere il futuro. Questo è anche l’approccio suggerito da Dan North che sostiene che all’inizio di ogni progetto dovremmo avere l’umiltà di porci al secondo livello di ignoranza, in accordo con Phillip Armour [6] ossia accettare la nostra mancanza di consapevolezza: non sappiamo di non sapere. Un interessante approfondimento è disponibile nell’articolo Introducing Deliberate Discovery [7] di Dan North stesso.
Residuality Theory
Questo nuovo modo di pensare alle architetture software è proprio ciò che propone Barry O’Reilly nel suo libro Residues [8].
Secondo l’autore
the future of a system is a function of its residues – the leftovers of the system after the impact of a stressor
Barry parte da presupposti filosofici, per dimostrare matematicamente la sua idea. Il presupposto di partenza è proprio il fatto che nessuno degli approcci tradizionali è in grado di misurare tempo, incertezza, cambiamento. Se progettiamo la resilienza delle nostre architetture basandoci solo su ciò che conosciamo, o pensiamo di conoscere, senza pensare fuori dagli schemi, non otterremo mail il risultato sperato.
Quest’idea richiama il “mito della caverna” di Platone o, se preferite un approccio più moderno, Matrix. Nel mito della caverna, raccontato nel VII libro della Repubblica, il prigioniero incatenato lì dentro riesce a vedere solo le ombre proiettate sul fondo della grotta di ciò che passa fuori e pensa che sia quella la realtà. Ma, quando esce dalla grotta, può invece vedere la realtà vera, che proiettava quelle ombre sul fondo della caverna. Dopo un primo momento di rifiuto, con la tentazione di tornare all’interno e di incatenarsi nuovamente nella sua comoda realtà, egli vorrebbe liberare tutti i prigionieri, ma non tutti sono disposti ad aprire gli occhi, a soffrire per l’esposizione alla luce del sole, e preferiscono rimanere incatenati… capite perché ho citato Matrix? Non sembri una mancanza di riguardo verso il filosofo greco: anche questo è un esempio di come si possa pensare oltre gli schemi.
L’importanza degli stressori
O’Reilly spinge il lettore a non focalizzarsi troppo durante la prima progettazione dell’architettura, quella che lui definisce un’architettura naive. Piuttosto è interessante analizzare quali sono gli stressori, ossia qualsiasi evento capace di alterare il funzionamento dell’architettura stessa. Uno stressore è un qualsiasi evento — dal mancato login al crollo del mercato azionario, dal server che non risponde allo scoppio di una guerra che altera tutti gli equilibri — che rompe il modello che noi ci eravamo costruiti per risolvere il problema di business. Ecco dunque emergere la capacità di pensare fuori dagli schemi, l’importanza del pensiero laterale, di cui Edward De Bono è stato maestro assoluto con libri come Sei Cappelli per Pensare [9].
Per individuare quanti più stressori possibile, è fondamentale esplorare a fondo il problema e, lo abbiamo già citato più volte, questo comporta il coinvolgimento di tutti i membri del team. Una volta individuati gli stressori il compito del software architect è identificare gli impatti che questi hanno sui componenti dell’architettura naive. Per portare a termine questo lavoro, tutto ciò di cui abbiamo bisogno è un foglio Excel.
Su questo foglio riporteremo tutti gli stressori individuati; se prendiamo come esempio il nostro solito ERP di produzione e vendita della birra potremo ritrovarci in questa situazione.
Come possiamo notare, non ci sono solo stressori tecnici, ma anche situazioni inaspettate e imprevedibili che potrebbero irrompere nel nostro mercato.
Reti booleane
Attorno al 1960 Kauffman introdusse il concetto di Random Boolean Network (RBN), rete booleana randomica. Si tratta di una matrice in cui gli elementi commutano da 0 a 1 in modo randomico quando stimolati, proprio come può succedere nei sistemi complessi composti da molti componenti. Durante i suoi esperimenti, Kauffman si accorse che connettendo i nodi in modi particolari otteneva di volta in volta maggiore o minore stabilità e influenzava il numero di possibili configurazioni dei loro elementi, chiamate stati di fase, presenti in ogni rete.
Si accorse che il numero di nodi (N), il numero di collegamenti tra di loro (K) e la tendenza dei nodi a comportarsi in modo simile (P), influivano sul numero di stati di fase di un sistema. Inoltre, si accorse che collegare i nodi tra loro, creando delle dipendenze, riduceva drasticamente il numero di stati di fase, anche di molti ordini di grandezza, e che il sistema sembrava tornare costantemente allo stesso gruppo di stati di fase. Chiamò questi stati di fase attratori.
Le reti booleane di Kauffman hanno influenzato molti studi, perché esistono attrattori in ogni sistema complesso. Nonostante la molteplice possibilità di combinazione dei nodi nei sistemi complessi, un ordine appare sempre, e il sistema tende a restituire sempre lo stesso gruppo di attrattori. Nella società questo spiega la ripetibilità di alcuni pattern comportamentali mentre, restando vicini al nostro mondo, i pattern che tutti conosciamo e applichiamo nei nostri sistemi possono essere visti come attrattori. Risolvono problemi simili che si ripetono continuamente. Un attrattore è uno stato particolare a cui il sistema tende continuamente. Volete un esempio? Come esseri umani siamo attratti dal riposo quando siamo stanchi, dal cibo quando siamo affamati. Un buon software architect deve trovare quali sono gli attrattori per il sistema che sta costruendo.
Tra criticità ed equilibrio
Nei suoi esperimenti Kauffman individuò la proprietà di criticità, ovvero, a un certo numero di nodi (N) e di collegamenti (K) un sistema è resiliente a cambiamenti inaspettati, e allo stesso tempo non così complicato da far collassare le sue risorse. Esempi del tutto simili li troviamo quotidianamente nel nostro lavoro, comparando i sistemi monolitici (basso numero di N e K) con i sistemi a microservizi (alto numero di K e N), e sappiamo benissimo quanto sia critico trovare il giusto equilibrio fra queste soluzioni.
Un terzo valore, P, descrive la propensione, se preferite i bias, di un nodo verso un particolare insieme di comportamenti. Questo valore è applicato alle architetture software proprio per limitare il comportamento dei suoi componenti all’interno del sistema. Non a caso utilizziamo interfacce, e non classi concrete, nella comunicazione fra componenti fra loro coesi. Le metodologie e i principi che applichiamo nel nostro lavoro — OOP, SOLID, DRY, etc. —servono a trovare il giusto equilibrio di N, K e P nei nostri sistemi. La difficoltà sta proprio nel trovare questo equilibrio, rendendolo a volte — sempre? — una questione di congetture, esperienza, e confronti.
Questo problema si risolve proprio simulando in modo casuale l’ambiente, finché l’architettura non mostra segni di criticità. Ecco lo scopo del foglio Excel. Riportare il livello di stress al nostro sistema e verificare se abbiamo trovato o meno questo equilibrio.
Esiste una grande differenza tra criticità e correttezza. È impossibile raggiungere la correttezza in un sistema complesso, mentre un sistema critico è auspicabile. L’obiettivo di un software architect è proprio quello di trovare la criticità per il sistema che sta costruendo, non l’assoluta correttezza. Quella è l’obiettivo di un matematico, o al più di uno sviluppatore, ma non di un software architect.
Come ricordato nel più volte citato Software Architecture. The Hard Parts:
Don’t try to find the best design in software architecture. Instead, strive for the least worst combination of trade-offs
Alla ricerca della criticità
Il primo foglio Excel ci serve per identificare quali sono gli stressori in grado di compromettere il funzionamento del nostro sistema. Una volta trovati, dovremo intervenire — ricordiamo che siamo ancora in fase di progettazione! — e ottenere un nuovo sistema, costruito sui residui del precedente. A questo punto sottoponiamo il nostro nuovo sistema a un nuovo test, con nuovi stressori. Ricordate? Un sistema raggiuge la criticità quando è stabile al sopraggiungere di stressori inaspettati). Otterremo un nuovo fogio Excel.
Nella prima colonna troviamo il nostro sistema precedente, o naive, e nella seconda quello ottenuto dai residui. A questo punto possiamo calcolare l’indice del residuo:
Al numeratore troviamo la differenza fra l’architettura residua e quella naive, al denominatore la rispettiva somma. Otterremo un indice compreso fra
Se l’indice è positivo significa che il nostro sistema è più resiliente a stressori inattesi, ma possiamo continuare la nostra ricerca. Se è negativo significa che non abbiamo proprio lavorato benissimo… Ad un certo punto, ci accorgeremo che l’indice è molto vicino allo 0: significa che abbiamo trovato il giusto equilibrio e che, ragionevolmente, il nostro sistema sarà in grado di reggere a situazioni inaspettate.
Conclusioni
L’agilità, ossia l’abilità ad adattarsi al cambiamento, è spesso vista come la soluzione ai rapidi cambiamenti. Tuttavia, e lo stiamo vedendo, non è sufficiente. L’agilità è spesso funzione delle circostanze, e noi possiamo adattare le risorse che abbiamo a disposizione.
Un’architettura povera può rapidamente compromettere il sistema e il business, limitando l’agilità al cambiamento. Residual Architecture cerca di dare un contributo alla realizzazione di sistemi antifragili basando la propria teoria su aspetti filosofici dimostrati poi matematicamente.
Riferimenti
[1] Giovanni Puliti, Antifragile Manifesto. Un manifesto per gli anni a venire. MokaByte 305, maggio 2024
https://www.mokabyte.it/2024/05/15/manifestoantifragile/
[2] Peter Naur – Brian Randell (eds.), Software Engineering. Report on a conference sponsored by the NATO Science Commitee. Garmisch, Germany, 7th to 11th October 1968. January 1969
https://www.scrummanager.com/files/nato1968e.pdf
[3] La pagina Wikipedia su Nicholas Negroponte
https://it.wikipedia.org/wiki/Nicholas_Negroponte
[4] IDesign
https://www.idesign.net/about
[5] Kjell Jørgen Hole, Anti-fragile ICT Systems. Springer, 2016
[6] Phillip Glen Armour , The Five Orders of Ignorance. Communications of the ACM 43(10), October 2000
https://www.researchgate.net/publication/27293624_The_Five_Orders_of_Ignorance
[7] Dan North, Introducing Deliberate Discovery
https://dannorth.net/introducing-deliberate-discovery/
[8] Barry O’Reilly, Residues. Time, Change, and Uncertainty in Software Architecture. LeanPub, 2024
https://leanpub.com/residuality
[9] Edward De Bono, Sei cappelli per pensare. Manuale pratico per ragionare con creatività ed efficacia. Rizzoli, 2013