Quando i marginal gains non bastano: migliorare un sistema che nessuno vede più

|

Migliorare una pipeline di CI di qualche minuto. Automatizzare un controllo manuale. Parallelizzare una suite di test. Eliminare un passaggio dalla checklist di release.

Presi singolarmente sono quasi sempre interventi sensati. È difficile contestare l’idea di rendere continuamente un sistema un po’ migliore.

Il problema nasce quando il sistema che stiamo migliorando è diventato talmente complesso che nessuno riesce più a descriverlo davvero end-to-end.

È una situazione tutt’altro che rara nei prodotti SaaS maturi: anni di evoluzione, debito tecnico, pipeline stratificate, controlli introdotti dopo incidenti, approvazioni, script, ambienti diversi, verifiche manuali e conoscenza distribuita fra molte persone. Alcuni passaggi sono documentati, altri sono tramandati oralmente. Alcune regole continuano a esistere perché tutti sanno che rimuoverle potrebbe essere rischioso, anche se pochi ricordano esattamente perché siano state introdotte.

In questi contesti, applicare una strategia di marginal gains senza prima recuperare una comprensione sufficiente del sistema crea un paradosso: possiamo diventare sempre più efficienti nel migliorare parti di un processo senza migliorare davvero il processo.

Il problema non sono i piccoli miglioramenti

La conclusione sbagliata sarebbe: con molto debito tecnico servono grandi trasformazioni invece del miglioramento incrementale.

Spesso vale esattamente il contrario.

Più un sistema è fragile, meno è prudente sostituirlo con un’unica grande iniziativa di redesign. Piccoli interventi rendono più semplice isolare gli effetti, limitare il blast radius, tornare indietro e imparare progressivamente come si comporta il sistema.

Il miglioramento incrementale può quindi essere particolarmente prezioso proprio nel legacy.

Ma bisogna distinguere due concetti che sembrano simili e non lo sono: small change e local optimization.

Una modifica molto piccola può avere un enorme valore sistemico se agisce sul principale constraint del flusso.

Al contrario, un progetto di automazione costoso e tecnicamente sofisticato può essere una pura ottimizzazione locale se accelera una parte che non limita il sistema.

È questa distinzione, più della dimensione dell’intervento, che dovrebbe interessare un Tech Leader.

Una pipeline più veloce non significa necessariamente una delivery più veloce

Prendiamo un esempio volutamente semplificato.

Supponiamo che dal momento in cui una modifica è pronta a quando raggiunge la produzione trascorrano mediamente 26 ore:

FaseTempo trascorso
CI3 h
Attesa QA6 h
Regression4 h
Attesa approval8 h
Preparazione release2 h
Deployment e verifica3 h

Immaginiamo ora che il team investa due sprint nell’ottimizzazione della CI, portandola da tre ore a due.

È un risultato tecnicamente significativo: 33% di riduzione del tempo della CI.

End-to-end, tuttavia, il miglioramento massimo teorico è inferiore al 4%.

E potrebbe essere ancora minore se l’ora risparmiata non modifica la finestra nella quale può iniziare QA o non evita di attendere la stessa approvazione.

I numeri sono illustrativi, non un benchmark. Il principio, invece, è importante: la percentuale di miglioramento locale non misura il valore sistemico dell’intervento.

La guida DORA al Value Stream Mapping rende esplicito un concetto analogo. Suggerisce di misurare non soltanto le attività, ma anche wait time, handoff e punti nei quali il lavoro si accumula. Osserva inoltre che, quando alcune parti di un processo richiedono minuti e altre ore o giorni, l’ottimizzazione dei minuti difficilmente cambia in maniera significativa il risultato complessivo.

Prima di ottimizzare bisogna rendere il sistema abbastanza visibile

Il punto critico è “abbastanza”.

Non serve sospendere ogni miglioramento per sei mesi mentre qualcuno produce la documentazione definitiva dell’SDLC. Probabilmente quella documentazione sarebbe già obsoleta al momento della pubblicazione.

La mappa deve essere uno strumento decisionale, non un deliverable burocratico.

Per esempio, nel percorso commit-to-production dovrebbe essere possibile rappresentare almeno:

  • le principali fasi attraversate da una modifica;
  • automation e attività manuali;
  • execution time e soprattutto waiting time;
  • gate e approval;
  • principali handoff tra team;
  • failure, retry e rework frequenti;
  • ownership dei passaggi;
  • eccezioni significative;
  • dipendenze dagli environment.

DORA raccomanda esplicitamente di iniziare con una rappresentazione semplice e raffinarla quando emerge la necessità di approfondire un determinato passaggio. Il Value Stream Mapping serve proprio a costruire una comprensione condivisa del flusso e a individuare bottleneck, waste e punti di friction.

Non dobbiamo quindi “documentare tutto prima di agire”.

Dobbiamo conoscere abbastanza del sistema da formulare una buona ipotesi su dove intervenire.

Il debito tecnico diventa anche debito di comprensione

In un sistema maturo, il problema non è soltanto che alcune tecnologie siano vecchie o che il codice sia difficile da modificare.

Esiste una seconda forma di debito: la quantità di conoscenza che una persona deve possedere per riuscire a completare un’attività apparentemente normale.

“Questo test è rosso, ma puoi ignorarlo.”

“Quella pipeline ogni tanto va rilanciata.”

“Prima della release devi chiedere a quel team.”

“Questa configurazione funziona in staging ma non in quell’altro environment.”

“Quello step sembra inutile, ma anni fa è successo qualcosa e nessuno vuole toglierlo.”

Ogni eccezione di questo tipo diventa una piccola tassa cognitiva.

Team Topologies tratta esplicitamente il cognitive load come una variabile organizzativa: se un team deve comprendere una quantità eccessiva di sistemi, strumenti e modalità di interazione, il flusso ne risente. La modellazione delle interazioni viene proposta anche come strumento per individuare gli ostacoli al flow e le sorgenti di cognitive load.

DORA applica un ragionamento simile al Platform Engineering: uno degli obiettivi della piattaforma dovrebbe essere spostare verso il basso la complessità non essenziale, evitando di chiedere a ogni sviluppatore di padroneggiare dettagli infrastrutturali che potrebbero essere incorporati nella piattaforma.

Questo introduce una metrica qualitativa interessante per valutare un improvement: quanta complessità rende inutile conoscere?

Un buon intervento non fa soltanto risparmiare cinque minuti. Può eliminare una decisione, un’eccezione, una verifica manuale o una conoscenza specialistica che centinaia di sviluppatori non dovranno più conservare nella propria testa.

Attenzione all’automazione del debito

L’automazione merita quindi una valutazione più critica: automatizzare un processo inefficiente non equivale necessariamente a semplificarlo.

Potremmo prendere dodici passaggi incomprensibili, racchiuderli dietro un comando e dichiarare di avere migliorato la Developer Experience.

Dal punto di vista dell’utilizzatore potremmo persino averla migliorata realmente.

Ma il sistema sottostante potrebbe essere diventato ancora più difficile da modificare.

La domanda dovrebbe quindi essere: stiamo eliminando complessità oppure la stiamo soltanto nascondendo?

Nascondere complessità non è sempre sbagliato. L’astrazione è uno dei fondamenti dell’ingegneria del software e delle piattaforme interne.

La differenza è nell’ownership.

Una piattaforma può assorbire complessità purché esista qualcuno in grado di comprenderla, gestirla e farla evolvere. Se nessuno possiede veramente ciò che sta dietro l’astrazione, abbiamo semplicemente trasferito il debito.

Misurare il sistema, non soltanto la pipeline

Un secondo errore frequente consiste nel confondere la metrica della componente con l’outcome.

Se portiamo una pipeline da 40 a 32 minuti abbiamo ottenuto un miglioramento misurabile.

Non sappiamo però ancora se abbiamo migliorato la software delivery.

Le metriche DORA guardano infatti a risultati end-to-end quali change lead time e deployment frequency per il throughput, insieme a change failure rate, failed deployment recovery time e deployment rework rate per osservare l’instabilità.

Questo non significa che ogni organizzazione debba governarsi esclusivamente attraverso cinque metriche.

Significa che il livello di misura dovrebbe essere coerente con il risultato che vogliamo ottenere.

Se l’obiettivo è ridurre il tempo necessario a portare una modifica in produzione, il tempo della CI è un indicatore intermedio.

Il change lead time è molto più vicino all’outcome.

Se invece il problema è il feedback loop dello sviluppatore durante una pull request, allora il tempo della CI può essere esattamente la metrica corretta.

La stessa ottimizzazione può quindi essere molto importante o quasi irrilevante a seconda della domanda che stiamo cercando di risolvere.

Il modello che funziona meglio: visibility → constraint → experiment

Per un sistema ad alto debito tecnico non sceglierei quindi tra “grande trasformazione” e “marginal gains”.

Userei una sequenza differente.

Prima renderei visibile il flusso quanto basta. Poi identificherei il principale constraint rispetto all’outcome desiderato. Infine userei piccoli improvement come esperimenti sul constraint.

DORA suggerisce una dinamica molto simile: visualizzare il value stream, identificare i friction point che incidono sull’outcome scelto, ignorare temporaneamente le opportunità che non lo influenzano e procedere attraverso miglioramenti incrementali gestibili.

Il miglioramento incrementale non scompare. Diventa più disciplinato.

Dopo ogni intervento bisogna inoltre osservare nuovamente il sistema. Se l’intervento funziona, il constraint può spostarsi.

Una pipeline accelerata può rendere improvvisamente evidente la coda di code review.

Una maggiore automazione dei test può far emergere il provisioning degli environment.

L’eliminazione di un approval può rendere evidente un problema di release architecture.

In un sistema complesso non esiste necessariamente un backlog statico di cento miglioramenti da completare in ordine.

Esiste un processo continuo di scoperta del prossimo fattore limitante.

Quando i marginal gains sono invece la strategia giusta

Tutto questo non deve diventare una scusa per trasformare ogni improvement in un progetto di systems analysis.

Il miglioramento locale è perfettamente razionale quando il problema è già noto e circoscritto, il risultato desiderato è chiaro, l’intervento è economico e reversibile oppure il beneficio diretto per lo sviluppatore giustifica l’investimento indipendentemente dall’effetto sull’intero SDLC.

Una pipeline che restituisce feedback in 20 minuti invece di 40 può avere un enorme valore DevEx anche se non dimezza il lead time fino alla produzione.

Il punto è essere espliciti: stiamo ottimizzando il sistema oppure migliorando intenzionalmente una specifica esperienza?

Entrambe possono essere decisioni corrette. Il problema nasce quando misuriamo la seconda e raccontiamo di aver ottenuto la prima.

Quattro domande prima del prossimo improvement

Quando un team propone il prossimo intervento su CI/CD, release engineering o Developer Experience, un Tech Leader può ricondurre la discussione a quattro domande:

  1. Quale outcome stiamo cercando di modificare?
  2. Qual è il principale constraint che oggi limita quell’outcome?
  3. Questo intervento elimina complessità oppure la sposta o la nasconde?
  4. Quale effetto end-to-end ci aspettiamo di osservare se l’ipotesi è corretta?

Non serve conoscere perfettamente il sistema per rispondere.

Se però nessuno riesce nemmeno a formulare una risposta plausibile, quello potrebbe essere il segnale più importante di tutti.

Prima del prossimo marginal gain, forse il miglior investimento è recuperare abbastanza visibilità da capire dove siamo davvero.

Tags: Cognitive Load, DORA, Team Topologies, Value Stream Mapping

Altri articoli che potrebbero piacerti