Serie di interviste AI 16: Come dovrebbe essere un buon spec coding?
Un buon Spec Coding (programmazione guidata dalle specifiche) ha come obiettivo trasformare "idee vaghe" in "contratti precisi, verificabili ed eseguibili". Non si tratta solo di scrivere un documento, ma di stabilire un linguaggio di comunicazione senza ambiguità tra umani e AI (o tra umani). Di seguito, spiegherò come dovrebbe essere un buon spec da quattro dimensioni: struttura del contenuto delle specifiche, principi di scrittura, flusso di collaborazione con l'AI e verifica della qualità.
1. Struttura standard del documento delle specifiche (esempio con un modulo funzionale)
| Sezione | Contenuti obbligatori | Esempio |
|---|---|---|
| 1. Obiettivo e ambito | Spiegare in una frase cosa fare e cosa non fare | "Implementare l'API di registrazione utente, senza verifica email" |
| 2. Contratto input/output | Struttura dati, tipo, campi obbligatori/opzionali, valori di esempio | Corpo richiesta POST /register {email: string, password: string}, risposta 201 o 400 con codice errore |
| 3. Comportamento e logica | Regole di business, condizioni limite, transizioni di stato | "Lunghezza password 8-20 caratteri, almeno un numero; se email già esistente restituire 409" |
| 4. Gestione errori | Tutti gli scenari di eccezione possibili e relativi codici/messaggi di errore | "Connessione database fallita → restituire 503, non esporre stack" |
| 5. Requisiti non funzionali | Performance (tempo di risposta < 200ms), sicurezza (query parametrizzate), logging, osservabilità | "Tutte le SQL devono usare prepared statement; registrare email ma non password" |
| 6. Casi di test (cruciali) | Almeno 3 input tipici + 2 input limite/eccezione, con output attesi | Vedi tabella sotto |
| 7. Dipendenze e vincoli | Librerie, versioni, variabili d'ambiente | "Python 3.10+, FastAPI, variabile ambiente DB_URL" |
Esempio di casi di test (incorporati nello spec)
| Scenario | Input | Output atteso |
|---|---|---|
| Registrazione normale | email: a@b.com, pwd: Pass1234 |
201, restituisce user_id |
| Password troppo corta | pwd: Ab1 |
400, codice errore WEAK_PASSWORD |
| Email già esistente | stessa email di cui sopra | 409, codice errore EMAIL_EXISTS |
Un buon spec deve prima scrivere i casi di test, perché l'AI può generarli direttamente come test unitari ed eseguirli automaticamente dopo il completamento.
2. Principi fondamentali per scrivere uno spec (variante SMART)
| Principio | Spiegazione | Controesempio |
|---|---|---|
| Preciso (Precise) | Usare numeri specifici, tipi, condizioni booleane; evitare "il più possibile", "generalmente" | ❌ "La password deve essere abbastanza sicura" → ✅ "Password di almeno 8 caratteri, con maiuscola, minuscola e numero" |
| Verificabile (Verifiable) | Ogni requisito deve poter essere verificato tramite test automatici o ispezione manuale | ❌ "Il codice deve essere elegante" → ✅ "Complessità ciclomatica delle funzioni ≤ 10, nessun blocco di codice duplicato" |
| Senza ambiguità (Unambiguous) | Uno stesso termine deve avere lo stesso significato in tutto il documento; se necessario, fornire un glossario | ❌ "Se l'utente non esiste, restituisci errore" → ✅ "Utente non esistente → restituire 404 e {code: 'USER_NOT_FOUND'}" |
| Completo (Complete) | Coprire il percorso felice, tutti i percorsi di eccezione e i requisiti non funzionali | ❌ Scrivere solo scenari di successo → ✅ Includere timeout del database, permessi insufficienti, ecc. |
| Atomico (Atomic) | Uno spec descrive un solo punto funzionale consegnabile in modo indipendente (facilita il completamento in un'unica sessione dall'AI) | ❌ Usare uno spec per scrivere "l'intero sistema di pagamento" → ✅ Suddividere in "generazione ordine di pagamento", "verifica firma callback", "rimborso" |
3. Flusso di Spec Coding in collaborazione con l'AI
- L'umano scrive lo spec (struttura sopra, in particolare i casi di test e le firme delle funzioni).
- Fornire lo spec all'AI in un'unica volta (nessuna aggiunta di requisiti in modo dialogico, per evitare contaminazioni da "vibe").
- L'AI produce codice + test unitari (l'AI deve generare test eseguibili basati sui casi di test dello spec).
- Eseguire i test: se tutti passano, passare al passo successivo; altrimenti, modificare lo spec o correggere direttamente il codice (a questo punto si può entrare in un piccolo ciclo, ma registrare le modifiche).
- Revisione umana: verificare che non siano state introdotte funzionalità al di fuori dello spec (scope creep), controllare sicurezza e performance.
- Consolidare: impegnare il documento dello spec e il codice finale nel repository come documentazione permanente.
Pratica chiave: Codificare lo spec — usare
spec.md+test_spec.py, dove il file di test deriva direttamente dagli esempi nello spec; in questo modo, modifiche successive al codice possono essere verificate eseguendo i test per controllare se lo spec è stato violato.
4. Effetti di un buon spec (può servire come criterio di accettazione)
- Determinismo: lo stesso spec dato a diverse AI (o persone) produce implementazioni simili.
- Testabilità: subito dopo aver scritto il codice, si può verificare automaticamente il 90% della correttezza.
- Manutenibilità: dopo sei mesi, chiunque legga lo spec può capire le intenzioni progettuali originali.
- Bassi costi di comunicazione: il team discute solo lo spec, non le singole righe di codice.
- Sicurezza/qualità integrata: i requisiti di sicurezza (es. query parametrizzate) e le condizioni limite sono scritti nello spec, l'AI deve rispettarli.
5. Esempio di un buono spec (versione molto ridotta)
# Spec: API di registrazione utente
## Ambito
- Riceve email, password
- Non invia email di verifica, non controlla la validità dell'email
## Contratto
POST /register
Content-Type: application/json
Request: { "email": string, "password": string }
Response 201: { "user_id": string }
Response 400: { "code": "INVALID_PASSWORD" | "INVALID_EMAIL" }
Response 409: { "code": "EMAIL_ALREADY_EXISTS" }
## Comportamento
- L'email deve rispettare il formato base RFC 5322 (a@b.c)
- password: lunghezza 8-20, almeno un numero e una lettera maiuscola
- Crittografare con bcrypt, costo salt 10
- Se prima dell'inserimento nel database si scopre che l'email esiste già → 409
## Casi di test (input -> codice di stato atteso + campo risposta)
| Input email | password | Atteso |
|-------------|----------|--------|
| test@x.com | Pass1234 | 201, user_id presente |
| test@x.com | pass | 400, INVALID_PASSWORD |
| bad | Pass1234 | 400, INVALID_EMAIL |
| (email già esistente) | Pass1234 | 409, EMAIL_ALREADY_EXISTS |
## Non funzionali
- Le SQL devono usare query parametrizzate (anti-iniezione)
- Il log registra l'IP di origine della registrazione, non la password
- Tempo di risposta per il 95% delle richieste < 100ms (escluso bcrypt)
## Dipendenze
- Python 3.10+, FastAPI, bcrypt, asyncpg
Un buon Spec Coding = scrivere le "decisioni di progettazione" umane come "casi di test + firma dei tipi + vincoli di comportamento" della macchina, in modo che l'AI si occupi solo di riempire l'implementazione, mentre l'umano mantiene sempre il controllo sulla qualità e sulla direzione.
评论
暂无已展示的评论。
发表评论(匿名)