BLUD: ogni goccia di latte donato ha un nome
Come abbiamo portato in React e TypeScript il software che traccia il latte umano donato, per oltre un decennio vincolato a Silverlight e Internet Explorer.

A volte una donna che ha appena partorito produce più latte di quanto ne serva. Invece di sprecarlo, può donarlo.
Qualche giorno dopo, in un’incubatrice a chilometri di distanza, quel latte diventa la prima cura di un bambino nato troppo presto, la cui mamma non riesce ancora a produrne. Due donne che non si incontreranno mai, unite da un biberon.
Per quel neonato non è semplice nutrimento: è una terapia.
Dietro quel biberon c’è una Banca del Latte Umano Donato (BLUD), e dietro la banca c’è un software che ne governa ogni passaggio. Questo articolo racconta come lo abbiamo aggiornato.
Per un neonato prematuro il latte donato è una cura
Partiamo dal perché conta: per un prematuro il latte di donna non è una preferenza, è la cura migliore disponibile.
Massimo Agosti, presidente della Società Italiana di Neonatologia, lo ha definito «una vera e propria medicina salvavita»: un «ponte nutrizionale terapeutico» fino a quando la mamma non riesce a produrre il proprio latte (ANSA, 16 maggio 2025).
Sull’effetto più studiato le prove sono solide. La revisione Cochrane più recente (Quigley et al., 2024) ha messo insieme 11 studi e 2.261 neonati molto pretermine o di peso molto basso: nutrirli con latte umano donato invece che con latte artificiale dimezza il rischio di enterocolite necrotizzante (RR 0,53), una delle prime cause di mortalità.
Il problema è la disponibilità. Secondo la quarta indagine dell’Associazione Italiana Banche del Latte Umano Donato (AIBLUD), condotta a febbraio 2025 sugli anni 2023-2024, l’Italia è prima in Europa con 44 banche del latte attive, seguita da Germania (37) e Francia (36), con 1.523 donatrici e quasi 10.000 litri raccolti.
Eppure lo riceve solo un neonato fragile su tre, perché le banche sono distribuite in modo disomogeneo e non fanno rete: solo il 32% è collegato alle altre. Il latte donato è una risorsa preziosa e scarsa, non se ne spreca una goccia e non si può sbagliare: i pazienti sono i più indifesi che esistano.
Ogni biberon ha una storia, e va certificata
Da qui nasce il problema che un software deve risolvere: una banca del latte è, di fatto, una piccola filiera farmaceutica, e ogni biberon ha una storia. Chi l’ha donato, quando l’hanno raccolto, a quale temperatura l’hanno congelato, quando e come è passato in pastorizzazione, quali analisi ha superato, in quale ospedale è arrivato, chi l’ha somministrato.
Se anche un solo anello salta - la catena del freddo che si interrompe, un’analisi non conforme - quel biberon va bloccato prima che arrivi a un bambino.
La tracciabilità totale non è burocrazia: è sicurezza.
Il software funzionava, il browser che lo eseguiva no
C’è una parte di questa storia che dai reparti non si vede. Il gestionale che accompagna da anni il lavoro delle banche del latte è un’applicazione Silverlight, la tecnologia Microsoft usata anni fa per le rich internet application, cioè applicazioni desktop dentro un browser: all’epoca era una scelta più che ragionevole, e ha fatto egregiamente il suo mestiere. È ancora oggi in uso, e da molte persone.
Poi il terreno sotto i piedi si è spostato. Microsoft ha chiuso il supporto a Silverlight, e il plugin girava solo su Internet Explorer, che a sua volta è stato ritirato (Microsoft Lifecycle).
Quanto sia diventato scomodo lo abbiamo capito montando l’ambiente di sviluppo. Per aprire l’applicazione ci siamo scritti uno script PowerShell che istanzia Internet Explorer via COM automation, perché Silverlight non gira da nessun’altra parte; e tra i guasti possibili lo script prevede che Internet Explorer sia stato disinstallato dal sistema operativo, spiegando come riattivarlo. Su una macchina recente non è un’ipotesi remota.
Il software funzionava. Era l’ambiente in cui girava ad essere arrivato a fine corsa.
Cosa c’era sotto: oltre un decennio di VB.NET
Prima di toccare qualcosa siamo andati a fondo nel codice esistente. Oltre 122.000 righe di VB.NET, fra logica applicativa e collegamenti verso i servizi. Decine di schermate e finestre, costruite con DevExpress, una libreria di componenti commerciale dell’epoca. Un centinaio di funzioni esposte dai servizi web, appoggiate su più database SQL Server.
L’accesso ai dati contava oltre 9.000 righe e più di cento funzioni pubbliche, con regole di business e interrogazioni al database nello stesso posto. Sotto c’era LINQ to SQL, il livello con cui allora si parlava al database. Era normale, in molti progetti di quegli anni. Come lo era il modo di avvisare le donatrici, con gli SMS affidati a un modem GSM: una risposta pragmatica a un problema reale.
Il dato più eloquente sono i commenti datati che lo sviluppatore originale lasciava nel codice come changelog: il più antico è di gennaio 2012, il più recente di settembre 2021. Dicono cosa è cambiato e perché, dal cambio del server del database a un nuovo ospedale da servire.
Vale la pena fermarsi su questo prima di entrare nel merito tecnico: oltre un decennio di servizio in un contesto sanitario, senza riscritture. Quel software ha funzionato, e chi l’ha scritto ha fatto un buon lavoro con gli strumenti del suo tempo.
Capire 122.000 righe di VB.NET, con l’aiuto dell’AI
Nessuno del team ha conoscenze approfondite di VB.NET, e il dominio ha un vocabolario tutto suo: donatrici, biberon, lotti, scatole, vassoi, pastorizzazione. Il codice lo usa senza spiegarlo. Prima di poter disegnare una schermata nuova bisognava ricostruire cosa faceva quella vecchia, e il codice sorgente era l’unica documentazione disponibile.
Qui il modello ci ha fatto risparmiare settimane, non a scrivere codice ma a leggerlo. Dare in pasto una schermata da 900 righe e chiedere quali metodi dei servizi chiama, in che ordine, e cosa fa per ogni codice di ritorno comprime in minuti un lavoro di ore; allo stesso modo è uscita la mappa dei dieci stati del ciclo di vita del biberon.
Dove il modello ha sbagliato, e cosa ne abbiamo imparato
Ha sbagliato, e non in modo casuale: in modo plausibile. Tre affermazioni sul comportamento della stessa pagina di congelamento, tutte false:
- «dopo ogni scansione l’input si disabilita, l’operatore deve ricliccare Aggiungi» - in realtà l’input si blocca solo durante la chiamata al server, poi la scansione riprende da sola;
- «viene chiesto “Stampare l’etichetta?” con Conferma e Annulla» - in realtà compare un avviso con una casella già spuntata e un solo pulsante OK;
- «viene chiesto “Confermi l’esclusione?”» - in realtà non viene chiesto niente: premendo OK il biberon è già escluso. La finestra informa, non domanda.
Costo: diverse iterazioni sulla stessa pagina, e scelte prese su informazioni sbagliate.
Il problema non era il modello, era il metodo. Un nome come DisabilitaInsert suggerisce un significato che il codice non ha, e i comportamenti di interfaccia non stanno nel codice che parla col database: stanno nel file che descrive la schermata, e nella finestra che quella schermata apre. Vanno letti lì. Il modello riempiva i buchi con l’inferenza più ragionevole, che su un software legacy è spesso quella sbagliata.
Da lì sono nate diverse regole che hanno governato il resto del porting. Mai affermare come fatto un comportamento del vecchio sistema senza averlo verificato nel codice, citando file e riga. Quando l’informazione manca, non si colma il buco con un’ipotesi: si dichiara che manca. E se qualcuno sta decidendo sulla base di una nostra descrizione, quella descrizione va verificata prima, non dopo.
L’AI, in tutto questo, è stata un acceleratore di lettura e non una fonte: ha ridotto il tempo per arrivare all’ipotesi giusta, mentre la verifica è rimasta lavoro umano.
Il vincolo: rifare il frontend e non toccare il resto
L’approccio era il più chirurgico possibile: rifare soltanto il frontend, cioè tutto ciò con cui operatrici e operatori lavorano ogni giorno, lasciando il backend al suo posto con la logica clinica e i dati collaudati negli anni.
Non era una preferenza tecnica ma un vincolo di progetto, scritto nero su bianco: il backend non si modifica, e dove serve davvero si tocca il minimo indispensabile, mentre tutto il resto si risolve lato client.
La nuova applicazione è scritta in React e TypeScript, con i controlli sui tipi alla massima severità.
Dove è arrivata, in diversi mesi di lavoro: 38 schermate su 21 aree del dominio, 55.600 righe di codice in 323 file. I punti di dialogo col backend esistente sono 106, 56 in lettura e 50 in scrittura.
Le 1.449 frasi dell’interfaccia stanno in un unico dizionario, fuori dal codice. Cambiare una parola, o aggiungere una lingua, non richiede di toccare il programma. E i form non sono scritti a mano: sono descritti come dati, con diciotto tipi di campo. Una schermata nuova si compone, invece di essere costruita da zero.
Per chi sviluppa: build con Vite, interfaccia su MUI, stato e chiamate con Redux Toolkit e RTK Query, permessi con CASL, grafici con Plotly.
Ogni anomalia annotata, con la prova accanto
Quel vincolo ha una conseguenza che si sente ogni giorno: quando trovi un comportamento sbagliato non puoi correggerlo, puoi solo conoscerlo e aggirarlo sempre allo stesso modo. Da qui la parte del lavoro di cui andiamo più fieri, che non è codice ma un file.
Ogni volta che incontravamo un comportamento inatteso del backend lo annotavamo in un catalogo, con una regola precisa: si scrive solo ciò che è verificato, riscontrato nel codice con riferimento a file e riga oppure in una risposta reale del server. Niente sospetti e niente deduzioni, e ogni voce dice qual è la causa, quale l’impatto sul frontend e dove sta il rimedio.
Quando una di quelle anomalie è stata risolta alla radice la voce non è stata cancellata: resta nel file come storico, con l’evidenza del test che lo dimostra, perché il “perché” di una decisione vale quanto la decisione. È il genere di lavoro che non si vede in una demo, e che decide se un sistema così sarà manutenibile fra cinque anni.
Dove il vincolo ha ceduto
Aggirare, però, non sempre bastava. Un’interfaccia nuova ha bisogno di parlare la lingua giusta, e il backend era stato pensato per i client SOAP dell’epoca, il linguaggio con cui allora si parlava ai servizi: su quattro punti non c’era alternativa. Interventi mirati, quindi, non una riscrittura: quanto bastava per reggere il cambiamento e nulla oltre.
Li abbiamo abilitati a rispondere anche in JSON, che è quello che un browser capisce; il passaggio ha fatto emergere qualche limite di configurazione mai incontrato prima, tutti risolti. Sopra ci abbiamo messo un modulo di autenticazione a token, senza toccare la logica dei servizi. Poi quattordici indici sul database, sulle colonne usate da liste e ricerche, con lo script per rimuoverli accanto: non c’erano, e con i volumi di allora probabilmente non servivano.
Il punto più visibile è la velocità, e sono i due numeri di cui siamo più contenti. La matrice dei permessi impiegava 1.442 millisecondi, perché il backend offre due modi di ottenere lo stesso dato e veniva usato il più costoso: cambiato quello e ricostruita la matrice lato client, siamo a 31. La ricerca eventi impiegava 3,4 secondi perché per ogni riga del risultato rifaceva una query da capo; togliendo quel giro a vuoto è scesa a 0,07. Non è una limatura: è la differenza che ci ha permesso di sostituire il pulsante «Visualizza» con una ricerca che si aggiorna mentre si digita.
Abbiamo aggiunto anche qualche funzione che mancava: il ripristino di più biberon bloccati in una sola operazione, la lettura delle giacenze filtrata per data, e la registrazione dei nuovi lotti resa transazionale, così un’interruzione a metà non lascia stati parziali.
L’intervento si è allargato quel tanto che serviva, ma è rimasto sotto controllo. Il cuore del sistema è ancora quello di prima.
Dieci passaggi, dieci firme
Per chi ci lavora cambia la quotidianità: dove prima serviva una postazione desktop con un browser fuori supporto, ora basta un browser aggiornato e non c’è niente da installare.
I permessi seguono i ruoli reali, chi gestisce le donatrici, chi la pastorizzazione, chi il magazzino ospedaliero, e ognuno vede solo ciò che gli compete. Passo dopo passo l’applicazione accompagna ogni biberon lungo il suo intero viaggio: la raccolta dalla donatrice, il congelamento, lo scongelamento, la pastorizzazione, un secondo congelamento, l’inscatolamento, il ritiro, la consegna, l’ingresso nel magazzino dell’ospedale, il prelievo per la somministrazione al neonato.
Dieci passaggi, e ognuno lascia una traccia nella storia del biberon: cosa è avvenuto, quando, e l’operatore che l’ha registrato.
Un’interfaccia per il reparto, non per una vetrina
Un blu profondo come colore portante, rosso per gli stati critici, e diversi componenti personalizzati per avere densità di informazione alta senza rumore. Chi apre l’applicazione trova la propria dashboard, e sono i permessi a decidere quale.
Molte scelte vengono da chi lavora con uno scanner in mano. Dopo ogni lettura l’input riprende il fuoco da solo, perché i biberon si scansionano in sequenza e le mani sono occupate: cercare il mouse fra un codice e l’altro rallenta tutto. Il segnale acustico cambia a seconda della gravità dell’esito, con il volume tarato sulle postazioni reali, dove il rumore di fondo non è quello di un ufficio. Gli errori bloccanti restano finestre modali, e non notifiche che scompaiono da sole: se un avviso passa inosservato, un biberon avanza quando non dovrebbe, e quello non è un problema di usabilità ma di sicurezza.
Le finestre di scansione si trascinano, perché a volte devono stare accanto a qualcos’altro. Le griglie si esportano in Excel, i report in PDF.
Se il processo non è conforme, il lotto si blocca
Il latte è una terapia, e il sistema si comporta come tale.
La pastorizzazione segue il metodo Holder, 62,5 °C per 30 minuti, il trattamento raccomandato dalle linee guida internazionali per le banche del latte, incluse quelle della European Milk Bank Association.
Ma non è il software a decidere se un ciclo è conforme. Il sistema raccoglie l’andamento della temperatura e lo mostra confrontato con le soglie di processo, poi chiede a un operatore di certificare l’esito: conforme o non conforme. La certificazione resta registrata con nome, data e note.
Tutto quello che segue quella firma è automatico. L’esito si propaga a ogni biberon del lotto, e se il ciclo non è conforme i biberon vengono bloccati: da quel momento il sistema rifiuta ogni avanzamento e ogni prelievo.
Sui tempi, invece, decide il software. A ogni cambio di fase il backend ricalcola le distanze fra le date: quanto è passato dalla donazione alla raccolta, quante ore è durato lo scongelamento, quanti giorni il biberon è rimasto congelato.
Se una soglia viene superata il sistema rifiuta il passaggio e il biberon esce dal programma. All’operatore resta un avviso da confermare, non una scelta da fare.
E sulla catena del freddo l’operatore non c’è affatto: quando un congelatore va in allarme grave l’impianto avvisa il gestionale, che blocca tutti i biberon presenti in quella macchina. A sbloccarli, se il caso lo consente, deve essere una persona.
Ogni biberon porta un codice univoco, stampato su etichetta e leggibile da uno scanner, che incorpora già i riferimenti essenziali della donazione: in laboratorio devono bastare un colpo d’occhio e un beep per sapere con precisione cosa si ha in mano.
Dove siamo adesso, e di chi è il merito
Il vecchio gestionale è ancora quello che manda avanti il lavoro quotidiano, per molte persone. La nuova applicazione è in fase di test e verrà adottata a breve: la sostituzione avverrà quando chi lavora in reparto avrà finito di provarla sul campo.
Quello che ci portiamo dietro da questi mesi è una convinzione: su un software con oltre un decennio di vita e utenti reali, il lavoro difficile non è scrivere il codice nuovo, è capire fino in fondo quello vecchio prima di sostituirlo, e resistere alla tentazione di riscrivere ciò che funziona.
Il merito di tutto questo, va detto chiaramente, è di chi quel latte lo dona, di chi lo raccoglie e lo lavora, dei neonatologi e degli infermieri che ogni giorno lo portano alle incubatrici. La cura è la loro. Noi ci abbiamo messo un pezzo, quello digitale: lo strumento che tiene insieme tutta la filiera e fa in modo che nessun passaggio si perda.
Perché la tracciabilità, in fondo, è una forma di cura. Significa che ogni goccia di quel latte ha un nome, ed è sicura per il bambino fragile che la riceve.
Ci piace lavorare a progetti che servono a qualcuno, e questo serve davvero.
Hai un gestionale che funziona ma gira su tecnologie a fine corsa? Oppure un progetto in cui la tecnologia deve risolvere un problema concreto, e non soltanto esistere? Parliamone.