Agli inizi della mia carriera da contractor, scrissi una specifica firmware di quaranta pagine per un progetto IoT. Il cliente annuì durante tutto il meeting di review. Il team di ingegneria costruì qualcosa di completamente diverso da ciò che il cliente si aspettava. Entrambi incolparono la specifica.
Il problema non era il livello di dettaglio — era che avevo scritto un unico documento cercando di servire due lettori completamente diversi. Un cliente che legge una specifica vuole risposte su costi, tempistiche e rischi. Un ingegnere vuole indirizzi dei registri, macchine a stati e contratti d'interfaccia. Un singolo documento non può fare bene entrambi i lavori.
Negli ultimi sei anni e una dozzina di progetti embedded, ho definito una struttura a tre livelli che i clienti leggono e gli ingegneri implementano davvero. Ecco come funziona.
La Specifica a Tre Livelli
Invece di un unico documento monolitico, scrivo tre artefatti collegati. Ognuno ha un pubblico chiaro e un lavoro specifico da fare:
| Livello | Destinatari | Scopo |
|---|---|---|
| Specifica Funzionale | Cliente + PM | Cosa fa il sistema, in linguaggio business |
| Documento di Design Tecnico | Team di ingegneria | Come funziona, a profondità d'implementazione |
| Contratto d'Interfaccia | Entrambi (riferimento condiviso) | API, protocolli, strutture dati, mappatura segnali |
Il Contratto d'Interfaccia è l'unico documento che entrambi consultano regolarmente. Diventa la fonte di verità per i punti d'integrazione e i test di accettazione. Gli altri due evolvono indipendentemente: il cliente aggiorna la specifica funzionale, il team aggiorna il design tecnico.
Livello 1: La Specifica Funzionale
Questo documento risponde a tre domande dal punto di vista del cliente:
- Cosa farà il sistema? — Scenari d'uso, non liste di funzionalità. "Quando l'utente preme il pulsante, l'attuatore si sposta in posizione B entro 200 ms" è meglio di "Pulsante → controllo attuatore."
- Come sapremo che funziona? — Criteri d'accettazione espressi in termini osservabili. "Il LED lampeggia verde quando i dati vengono trasmessi con successo" è testabile. "Trasmissione affidabile" non lo è.
- Quali sono i vincoli? — Budget energetico, tempo di risposta, raggio di comunicazione, requisiti normativi. Sono confini non negoziabili, non nice-to-have.
Mantieni questo documento sotto le dieci pagine. Usa elenchi puntati e paragrafi brevi. Il cliente lo leggerà una volta durante il kick-off e mai più — assicurati che quella singola lettura sia sufficiente a intercettare gli equivoci.
Un trucco che uso: dopo aver scritto la specifica funzionale, elimino la parola "supportare" dall'intero documento (come in "il sistema deve supportare X"). La sostituisco con comportamenti concreti. "Supportare OTA" diventa "Il sistema scarica un'immagine firmware firmata dall'endpoint cloud, verifica la firma contro la chiave pubblica memorizzata, la scrive nel bank B e si avvia dal bank B al prossimo ciclo di accensione." Il cliente potrebbe non capire ogni dettaglio, ma capirà per cosa sta pagando.
Livello 2: Il Documento di Design Tecnico
Qui vive il dettaglio ingegneristico. È scritto per chi implementerà il firmware — possibilmente te stesso tra sei mesi. Strutturalo intorno all'architettura hardware:
- Scelta dell'MCU e allocazione periferiche (quale timer, quale canale DMA, quale banco GPIO — e perché)
- Diagrammi delle macchine a stati (testuali o semplici flow chart) per ogni modalità principale: boot, attivo, low-power, errore, OTA
- Mappa di memoria: settori flash, regioni RAM, buffer condivisi con DMA o periferiche
- Layout dei task RTOS: priorità, dimensioni dello stack, comunicazione inter-task (code, semafori, event group)
- Strategia di gestione errori: cosa succede quando una transazione I2C dà NACK, quando scatta il watchdog, quando un controllo CRC fallisce
Il documento di design tecnico dovrebbe contenere anche un registro dei rischi — non roba da project management, ma rischi ingegneristici concreti. Esempio: "Errata 2.4 sulla periferica SPI dello STM32U5: sotto carico DMA elevato, la FIFO RX va in overflow su trasferimenti back-to-back che superano 64 byte. Mitigazione: limitare la dimensione del burst o passare a letture manuali byte-per-byte per gli ultimi 32 byte." Questo tipo di documentazione specifica e referenziata fa risparmiare settimane quando un bug emerge durante i test d'integrazione.
Mantengo il design tecnico tra le quindici e le trenta pagine. Più lungo e nessuno lo aggiorna; più corto e perde i casi limite che tornano a morderti.
Livello 3: Il Contratto d'Interfaccia
Questo è l'unico documento che entrambe le parti approvano formalmente, ed è il più corto dei tre. Definisce ogni confine tra il firmware e il mondo esterno:
- Protocollo comando/risposta — opcode, formato del payload, timeout
- Mappa dei registri I2C (se l'MCU agisce come periferica)
- Temporizzazione segnali GPIO — setup time, hold time, larghezza minima dell'impulso
- Struttura UART — baud rate, parità, bit di stop, controllo di flusso
- Interfaccia diagnostica — cosa emette la UART di debug durante ogni fase del boot
Ogni elemento del contratto d'interfaccia deve essere testabile con un analizzatore logico, un terminale seriale o un test fixture. Se non puoi verificarlo con uno strumento che possiedi oggi, non appartiene al contratto.
Il contratto d'interfaccia definisce anche la suite di test di accettazione. Ogni test corrisponde a una voce del contratto. Quando il cliente chiede "è finito?", esegui i test. Nessuna ambiguità, nessuna negoziazione.
Checklist pratica
- Scrivi tre documenti: specifica funzionale, design tecnico, contratto d'interfaccia — non uno solo
- Elimina "deve supportare" dalla specifica funzionale; sostituisci con comportamenti concreti
- Includi un registro rischi per periferica nel design tecnico
- Ogni voce del contratto d'interfaccia deve essere testabile indipendentemente
- Condividi il contratto d'interfaccia per primo; ottieni l'approvazione prima di scrivere una riga di firmware
- Mantieni la specifica funzionale sotto le 10 pagine, il design tecnico sotto le 30
Cosa ha funzionato per me
La struttura a tre livelli è nata organicamente dopo un progetto in cui il "semplice pulsante" del cliente si rivelò essere un'interfaccia touch capacitiva multi-gesture con feedback aptico — perché nessuno di noi aveva definito cosa significasse "pulsante" nel contratto d'interfaccia.
Da quando ho adottato questo approccio, ho avuto esattamente zero momenti "non è quello che avevo chiesto" al momento della consegna. Le riunioni sono più brevi, la varianza delle stime è minore e il team di ingegneria passa meno tempo a indovinare cosa intendesse il cliente. L'investimento è qualche giorno in più all'inizio del progetto. Il ritorno è evitare un singolo re-spin, che tipicamente costa da quattro a otto settimane.
I contratti negoziano il perimetro. Le specifiche negoziano la comprensione. I due non dovrebbero mai essere lo stesso documento.
📬 Commenti / discussione
Preferisci email: comments@carrese.eu — includi l'URL dell'articolo così posso seguire. Per correzioni o domande più approfondite, di solito rispondo entro 48 ore.