Analisi tecnica · software installato presso il cliente

Progettare

Quante versioni del tuo prodotto stai mantenendo davvero?

Ogni «sì, si può fare» detto in trattativa diventa un'installazione diversa da tenere in piedi per sempre. Le abbiamo contate, e poi abbiamo scoperto che i controlli che dovevano coprirle rispondevano verde da mesi senza guardare.

Subject

Un produttore di software gestionale per laboratori di analisi privati, installato dentro le sedi dei clienti. Ogni cliente chiede una variante in fase di contratto, e ogni variante diventa un'installazione diversa da mantenere.

Outcome

Le configurazioni supportate sono diventate un elenco scritto, e «verde» ha smesso di significare tre cose diverse. Il lavoro ha rivelato controlli che dichiaravano successo senza aver verificato nulla e configurazioni senza alcun controllo. Il risultato consegnato è la mappa di dove sono i buchi, e quanto costa ogni riga.

Method

Contare le configurazioni realmente installate, dichiararle in un solo file YAML, e leggerlo da due esecutori diversi: uno smoke test in shell dove non si può installare niente, una suite pytest che installa davvero. Poi tre livelli di controllo per riga.

Structure

Il conto che nessuno teneva · La suite verde che non c'entrava · Una fonte, due esecutori · Il rosso che aveva torto · La mappa dei buchi

Anonymisation

Cliente e settore sono sostituiti; lo stack è quello reale. Restano fuori i nomi dei servizi, gli indirizzi, gli esiti attesi e il numero delle configurazioni: l'elenco completo è l'inventario delle varianti che il cliente vende, e non è mio.

What this document covers

  1. 01

    Il conto che nessuno teneva

    Le configurazioni non si sommano, si moltiplicano

  2. 02

    La suite verde che non c'entrava

    L'applicazione è la stessa ovunque; a rompersi è l'installazione

  3. 03

    Una fonte, due esecutori

    Un file dichiarativo letto da chi verifica e da chi installa

  4. 04

    Il rosso che aveva torto

    L'installazione era sana: sbagliava il file che diceva quando è sana

  5. 05

    La mappa dei buchi

    Tre livelli dichiarati, e il prodotto utile non è la copertura

How to read this

Per decidere

Il conto delle configurazioni e cosa torna al tavolo commerciale: quanto costa davvero una riga in più, e chi la paga.

Per valutare

Come è fatta la verifica: una fonte dichiarativa, due esecutori, tre livelli di controllo e cosa hanno trovato.

Il perimetro è l'installazione, non il prodotto. Va detto prima di qualunque affermazione sui risultati, perché è ciò che rende confrontabili i numeri.

The constraint

Il prodotto è lo stesso ovunque. A rompersi è l'installazione, non l'applicazione, e nessuno sapeva quante installazioni diverse esistessero, perché non erano scritte da nessuna parte.

Context

Il software si installa dentro il cliente, non gira su un'infrastruttura nostra. Ogni contratto porta una richiesta ragionevole: il Keycloak ce l'abbiamo già, la rete è isolata, questo modulo non ci serve. Ogni richiesta accolta in trattativa diventa una combinazione da tenere viva per tutta la durata del contratto.

In brief

Perimetro
L'installazione, non l'applicazione La suite del prodotto era verde e non c'entrava niente: il codice è lo stesso ovunque
Fonte di verità
Un solo file YAML con le configurazioni supportate
Esecutori
Due, che leggono lo stesso YAML Uno smoke test in shell dove non si può installare nulla, una suite pytest che installa davvero
Livelli di controllo
Tre, dichiarati per ogni riga: esiste, risponde, funziona davvero
Fuori scope
Esecuzione automatica a ogni modifica, e la copertura di tutte le righe
G1 · Cosa è cambiato, in tre righe
Le configurazioni
Prima Non erano scritte da nessuna parte
Dopo Sono un elenco che chiunque può aprire
Il significato di «verde»
Prima Un colore solo, per tre situazioni diverse
Dopo Tre livelli dichiarati, riga per riga
La domanda in trattativa
Prima «Si può fare?»
Dopo «Quale riga aggiungiamo, e chi la mantiene?»
il riassunto in tre righe

La terza riga è l'unica che conta per chi paga: le prime due sono il lavoro tecnico che serve a rendere possibile quel cambio di domanda.

The decisions, and the rule behind them

G2 · Decision tree

Fork

Dove verificare

Chosen L'installazione, con la sua configurazione L'applicazione è identica ovunque: se si rompe qualcosa, si rompe nel modo in cui è stata messa in piedi.
Rejected Allargare la suite di test del prodotto Esisteva già, era verde, e allargarla sembrava il passo naturale.

Fork

Dove vivono le configurazioni

Chosen Un solo file YAML, letto sia dallo smoke test sia dalla suite pytest Due esecutori che leggono la stessa fonte non possono divergere in silenzio.
Rejected Un elenco per esecutore, ciascuno con il proprio formato Ognuno resta semplice e indipendente, finché i due elenchi non si separano senza che nessuno lo noti.

Fork

Cosa significa «verde»

Chosen Tre livelli dichiarati per riga, e per ognuna si scrive quale raggiunge Un verde che non dice cosa ha verificato è indistinguibile da un verde che non ha verificato niente.
Rejected Un unico esito passa/non passa per configurazione Un cruscotto tutto verde è più facile da leggere, e da mostrare.

Fork

Cosa consegnare

Chosen La mappa dei buchi: quali righe non sono coperte, e a che livello Serve a decidere cosa promettere in trattativa, e quella decisione la prende chi vende.
Rejected Una percentuale di copertura È un numero solo, sale nel tempo, e sta bene in una slide.

Il filo comune è che ogni scelta rende visibile qualcosa che prima era implicito. Il costo di una configurazione non era nascosto: semplicemente non era scritto da nessuna parte, e quello che non è scritto non entra in nessun preventivo.

Il conto che nessuno teneva

La call durò quaranta minuti, e la frase che conta arrivò al trentacinquesimo.

«Il nostro Keycloak ce l’abbiamo già. Gli utenti li gestiamo noi, il vostro sistema deve solo fidarsi.»

Il commerciale rispose come rispondono i commerciali quando la richiesta è ragionevole e il contratto è grosso: «certo, si può fare». Aveva ragione. Si poteva fare, si era già fatto altrove, e la stima buttata lì quel giorno (due giorni-uomo) era anche corretta, per la prima volta.

Mesi dopo mi trovai a fare un conto che nessuno aveva mai fatto: quante versioni diverse di quel prodotto erano vive, in quel momento, presso i clienti che l’avevano comprato.

Il conto si ferma intorno alla decina, e già così è più di quanto chiunque si aspettasse. Ma il numero da solo dice poco: quelle configurazioni mettono in gioco una tredicina di servizi diversi, in combinazioni che vanno da due a tutti. Non è una domanda con una risposta ovvia, perché le configurazioni non si sommano. Si moltiplicano. Una struttura porta le proprie utenze dal proprio Keycloak, un altro le lascia gestire al prodotto. Un sede ha la rete isolata verso l’esterno, un altro no. Qui i laboratori sono tre sulla stessa installazione, là uno solo. Ogni scelta è indipendente dalle altre, e ogni combinazione è una cosa che deve funzionare.

Nessuna di queste varianti era stata decisa da un architetto. Erano state tutte concesse in trattativa, una alla volta, ognuna in un momento in cui dire di sì costava meno che dire di no.

E c’è un dettaglio che cambia la natura del problema: chi installa non è uno sviluppatore. In azienda c’è una decina di persone che scrivono codice, e nessuna segue solo quel prodotto. Ma accanto a loro ci sono figure il cui mestiere è preparare l’ambiente per il cliente (background vario, non informatico) che si trovavano davanti a errori che non erano in grado di interpretare. Ogni configurazione in più non era solo una riga di manutenzione: era una situazione nuova in cui qualcuno poteva restare bloccato senza saper dire perché.

Il momento in cui la cosa ha smesso di essere un fastidio interno ha una data e un nome: una brutta figura davanti a un cliente. L’installazione non era verificata come credevamo, e la messa in servizio è diventata un rimpallo: chiedi una verifica, aspetti, ne chiedi un’altra, aspetti ancora. È costato tempo, ma soprattutto è costato la faccia di un’azienda che quel prodotto lo vende.

Fino a quel giorno il costo delle configurazioni era distribuito e invisibile. Da quel giorno aveva un volto.

Ogni rilascio richiedeva prove manuali su ambienti che nessuno sapeva elencare. Un guasto compariva presso un cliente solo e non era riproducibile altrove. Una persona sapeva «come si fa da quel cliente» e senza di lei ci si fermava. Nessuno rispondeva in trattativa senza chiedere prima a uno sviluppatore. Era tutto vero, e nessuna di queste cose era scritta da nessuna parte.

La suite verde che non c’entrava

La prima reazione, quando conti quel numero, è cercare i test.

I test c’erano, ed erano verdi. Migliaia di asserzioni sul prodotto, scritte bene, mantenute nel tempo. Non servivano a niente per questo problema, e ci volle un po’ per accettarlo.

Il motivo è che l’applicazione è la stessa ovunque. Lo stesso identico codice gira dentro tutte quelle sedi. Non è lì che si rompe qualcosa: si rompe nel modo in cui quel codice viene messo in piedi. Una struttura ruota il certificato di firma del proprio Keycloak e le utenze smettono di arrivare; un altro rinnova la rete e un modulo non raggiunge più il servizio che gli serve. In entrambi i casi la suite del prodotto resta verde, perché il prodotto non ha nulla che non va.

L’oggetto da verificare non era il software. Era l’installazione, con la sua configurazione, dentro il suo ambiente.

Questo sposta il problema in un posto scomodo. Un test sul prodotto lo lanci sulla tua macchina. Un test sull’installazione ha bisogno di un’installazione, e le installazioni vivono dentro le sedi dei clienti dove non entri quando ti pare, e in alcuni casi non entri affatto.

Una fonte, due esecutori

La forma che ha retto è più semplice di quanto sembri.

Un solo file YAML elenca le configurazioni supportate. È un elenco, non codice. Per ogni riga, quali moduli ci sono, come arrivano le utenze, cosa deve rispondere e a che livello.

Quel file viene letto da due esecutori diversi. Il primo è uno smoke test in shell che non installa niente: serve dove non puoi installare, ambienti chiusi, macchine di qualcun altro, situazioni in cui hai il permesso di guardare e non di toccare. Il secondo è una suite pytest che porta su l’ambiente con Ansible, da zero, e poi guarda cosa succede.

La parte che conta è che leggono la stessa fonte. Due elenchi separati, uno per esecutore, sarebbero stati più semplici da scrivere e avrebbero divergito nel giro di qualche mese senza che nessuno se ne accorgesse, perché due elenchi che divergono non producono nessun errore, producono due verdi.

G3 · Una fonte, due esecutori
La fonte Un solo file dichiarativo Per ogni configurazione supportata: quali moduli, come arrivano le utenze, cosa deve rispondere e a che livello. Un elenco, non codice.
letto da entrambi
Primo esecutore Non installa niente Per gli ambienti chiusi dove hai il permesso di guardare e non di toccare.
e in parallelo
Secondo esecutore Porta su l'ambiente da zero Installa e poi guarda cosa succede.
entrambi rispondono su
L'esito Tre livelli, non un passa o non passa Esiste, risponde, funziona davvero.
la forma che ha retto

Il rosso che aveva torto

Poi arrivò il rosso.

Una configurazione falliva. Non a intermittenza, sempre. Passai quaranta minuti sui log a cercare quale pezzo dell’installazione fosse rotto, con quella sensazione crescente che qualcosa non tornasse, perché era una configurazione vecchia, in esercizio da anni, senza una sola segnalazione dal campo.

Alla fine entrai a mano. Aprii il sistema, feci le cose che il controllo diceva di fare, e le vidi funzionare tutte.

L’installazione era sana. Sbagliava il file che avevo scritto io per dire quando è sana. Descriveva un esito che quel sistema, in quella configurazione, non produceva e non aveva mai prodotto.

È un momento istruttivo, e non per il bug. Per quaranta minuti avevo dato per scontato che l’oracolo avesse ragione e la realtà torto. È lo stesso riflesso per cui una suite verde rassicura: si finisce per fidarsi dello strumento invece che della cosa che lo strumento dovrebbe misurare. Ci ero già passato con una suite che mi mentiva sulla propria copertura, e non l’avevo riconosciuto.

La scoperta peggiore

Se un controllo può sbagliare dicendo rosso a un sistema sano, può sbagliare anche nell’altra direzione. Andai a rileggerli tutti.

Uno controllava il flusso di autenticazione OIDC e accettava come successo qualunque risposta sotto il 500. Un 401 passava per verde. Un 403 passava per verde. In quella configurazione il controllo aveva risposto verde per mesi senza aver mai verificato un accesso riuscito, e stampava a schermo un esito che non corrispondeva a quello che aveva davvero misurato.

E c’era il secondo pezzo, peggiore del primo perché più banale: diverse configurazioni avevano la casella dei controlli semplicemente vuota. Nessun controllo scritto. Nel cruscotto non comparivano come mancanti: non comparivano affatto.

Sommate le due cose, la matrice mostrava una fila di verdi che significavano tre cose diverse: questa funziona, questa non è stata guardata bene, questa non è stata guardata per niente. Tutte disegnate uguali.

È la stessa domanda che mi ero già fatto quando i test hanno cominciato a scriverli gli agenti: chi controlla che funzionino davvero? Qui non li aveva scritti un modello, li avevo scritti io, e il risultato era identico. Un controllo che nessuno verifica è un controllo di cui non sai niente, a prescindere da chi tiene la penna.

La mappa dei buchi

La riparazione non è stata scrivere i controlli mancanti. È stata dichiarare cosa significa verde.

Tre livelli, scritti esplicitamente. Esiste: il container è su, la porta risponde. Risponde: l’endpoint restituisce qualcosa di sensato. Funziona davvero: un login OIDC completo arriva fino al token, con un esito che solo un successo autentico può produrre. Per ogni configurazione si scrive quale livello raggiunge, e le caselle non raggiunte restano bianche.

Il risultato non è un cruscotto tutto verde. È una griglia in cui il bianco si vede, e si vede soprattutto nella terza colonna.

I numeri, quando la griglia è stata compilata per la prima volta: quasi la metà delle configurazioni restava fuori dal giro automatico, testabile solo chiedendolo esplicitamente, cosa che nessuno faceva. Sempre quasi la metà non aveva alcun controllo sul flusso applicativo, e per un paio il controllo si riduceva a verificare che i container fossero accesi.

Il prodotto utile di questo lavoro non è la copertura: è la mappa dei buchi. Una percentuale sarebbe stata più comoda da mostrare e inutile da usare, perché non dice quale configurazione è scoperta, e le configurazioni non sono intercambiabili. Sapere che sei coperto al settanta per cento non serve a nessuno se il trenta scoperto è quello del cliente più grosso.

G4 · La mappa dei buchi
Esiste Risponde Funziona
Installazione di riferimento Tutti i moduli, utenze gestite dal prodotto
Cliente con Keycloak proprio Le utenze arrivano dal sistema dell'cliente
Sede con rete isolata Nessuna uscita verso l'esterno
Installazione multi-laboratorio Più laboratori sulla stessa istanza
Ambiente di collaudo del cliente Dati finti, moduli parziali
verificato verificato in parte nessun controllo
Configurazioni di esempio, inventate: le righe reali sono l'inventario delle varianti vendute

La prima riga è quella su cui si lavora tutti i giorni, ed è l'unica coperta fino in fondo. Le altre esistono in produzione da anni. La colonna che conta è la terza, dove il bianco è quasi tutto.

Chi può fare il lavoro, adesso

Il primo effetto è stato su chi può fare il lavoro.

Con le configurazioni scritte e i controlli dichiarati, non serve più ricordarsi se un caso è nuovo o già visto: si guarda. E persone con meno anzianità hanno cominciato a gestire installazioni che prima richiedevano qualcuno che «se le ricordava»: comprese quelle figure non tecniche il cui mestiere è preparare l’ambiente, che davanti a un errore adesso hanno un posto dove cercare.

La conoscenza ha smesso di stare nelle teste. È il cambiamento che un estraneo avrebbe potuto vedere entrando in azienda, e l’unico che continua a valere anche se domani nessuno tocca più quella matrice.

Il conto torna al commerciale

A questo punto la matrice ha smesso di essere un documento tecnico.

Ogni riga è una configurazione che qualcuno deve tenere viva: quando esce una versione va provata su quella riga, quando cambia una dipendenza va ricontrollata su quella riga, e quando il cliente rinnova qualcosa dalla sua parte è su quella riga che si rompe. Ha un costo mensile, e quel costo esisteva già da anni. Semplicemente non era scritto da nessuna parte, e quello che non è scritto non entra in nessun preventivo.

Il costo di tenerla in piedi è misurabile e non è spaventoso: circa un migliaio di righe fra il file dichiarativo, i due esecutori e i loro test. È una cifra che vale la pena dire a chi teme che mettere ordine costi più del disordine.

La matrice è il listino vero. Non quello dei moduli: quello delle combinazioni.

E cambia la domanda che si fa al tavolo della trattativa. Non più «si può fare?», che ha quasi sempre risposta sì. Ma: quale riga stiamo aggiungendo, e chi la mantiene?

La riga che non abbiamo aggiunto

L’ultima richiesta arrivò quando la matrice esisteva già.

Era ragionevole quanto le altre, tecnicamente fattibile in pochi giorni, e chiedeva una combinazione nuova che nessun’altra installazione aveva. Con la griglia sul tavolo, però, la conversazione fu diversa: non si discusse se si potesse fare, ma quanto sarebbe costato tenerla in piedi per la durata del contratto, e chi l’avrebbe provata a ogni rilascio.

La risposta al cliente non fu no. Fu che quella combinazione si poteva avere accostandola a una riga che esisteva già, rinunciando a un dettaglio che nella pratica non gli cambiava la giornata. Il cliente accettò senza pensarci troppo: era un dettaglio, per l’appunto. Nessuno l’aveva mai potuto proporre prima, perché prima nessuno sapeva che l’alternativa costava una riga in più per sempre.

E questa non è rimasta una volta sola. È diventato il modo di lavorare: davanti a una richiesta si guarda se ricade in qualcosa che esiste già, o se ci si può far ricadere adattandola. È smettere di dire sì per riflesso, che non è dire di no ed è una cosa diversa e molto più difendibile al tavolo.

La frase che riassume tutto non l’ha detta un cliente: è uscita in una revisione interna, dal team che quel prodotto lo installa.

«Sembrava che un’installazione per un cliente nuovo fosse un progetto a sé stante, invece di dare un comando ed eseguire un applicativo, come ci si aspetterebbe.»

Ogni flessibilità concessa in trattativa è una riga di manutenzione che qualcuno pagherà ogni mese, e finché non la scrivi da qualche parte, quel qualcuno non lo sa nessuno.


Il caso è reale, il settore no: dominio, ruoli e terminologia sono stati sostituiti. Tempi e scene sono compressi, e le configurazioni mostrate nella figura sono inventate. Restano fedeli l’esistenza di una fonte dichiarativa unica letta da due esecutori diversi, le configurazioni prive di controlli che passavano lo stesso, e il controllo che accettava risposte di errore come successo dichiarando un esito che non corrispondeva.

What remains open

Ogni flessibilità concessa in trattativa è una riga di manutenzione che qualcuno pagherà ogni mese, e finché non la scrivi da qualche parte, quel qualcuno non lo sa nessuno.

Related article →

Quanto costa, oggi, l'ultima installazione andata storta?

Se la risposta richiede più di trenta secondi, il costo esiste già: semplicemente non è scritto, quindi non è né a bilancio né in preventivo. Contarle è un lavoro delimitato.