Ho visto progetti fallire non per incompetenza tecnica, ma per specifiche vaghe. "Deve funzionare bene", "l'utente deve poter fare X", "come Spotify ma per Y". Frasi che sembrano dire qualcosa ma non dicono nulla.
Una specifica efficace è diversa. È un documento che:
- Risponde a domande prima che vengano fatte
- Elimina ambiguità (o le evidenzia)
- Può essere usata per validare l'output
- Funziona come input per sviluppatori, QA e AI
In questo articolo ti do template pronti e esempi reali che puoi adattare ai tuoi progetti.
Anatomia di una specifica efficace
Una buona specifica ha sezioni distinte, ognuna con uno scopo preciso:
┌─────────────────────────────────────┐
│ CONTESTO │ ← Dove siamo? Perché esiste?
├─────────────────────────────────────┤
│ OBIETTIVO │ ← Cosa risolve?
├─────────────────────────────────────┤
│ COMPORTAMENTI │ ← Cosa fa in scenari specifici?
├─────────────────────────────────────┤
│ VINCOLI │ ← Limiti e requisiti non-funzionali
├─────────────────────────────────────┤
│ INTERFACCE │ ← Input/Output/API
├─────────────────────────────────────┤
│ CRITERI DI ACCETTAZIONE │ ← Come so che è fatto?
├─────────────────────────────────────┤
│ NON-GOAL │ ← Cosa NON fa
└─────────────────────────────────────┘
Vediamole una per una.
Template completo
Ecco il template che uso. Copia, adatta, usa.
# Feature: [Nome chiaro e descrittivo]
## Contesto
[In quale parte del sistema si inserisce questa feature?
Quali moduli/servizi esistenti tocca?
Qual è il trigger che ha generato questa richiesta?]
## Obiettivo
[Perché stiamo costruendo questa feature?
Che problema risolve per l'utente o per il business?
Qual è il valore atteso?]
## Comportamenti
### Scenario: [Nome scenario]
**Attore**: [Chi compie l'azione]
**Pre-condizioni**:
- [Stato iniziale necessario]
**Flusso principale**:
1. [Step 1]
2. [Step 2]
3. [Step 3]
**Risultato atteso**:
- [Cosa succede alla fine]
**Flussi alternativi**:
- Se [condizione], allora [comportamento alternativo]
### Scenario: [Altro scenario]
...
## Vincoli
### Tecnici
- [Vincolo tecnico 1]
- [Vincolo tecnico 2]
### Di sicurezza
- [Requisito sicurezza]
### Di performance
- [Requisito performance]
## Interfacce
### Input
[Formato e validazione dati in ingresso]
### Output
[Formato dati in uscita]
### API (se applicabile)
[Endpoint, metodi, payload]
## Dipendenze
- [Servizio/modulo da cui dipende]
- [Libreria esterna]
- [API di terze parti]
## Criteri di accettazione
- [ ] [Criterio verificabile 1]
- [ ] [Criterio verificabile 2]
- [ ] [Criterio verificabile 3]
## Non-goal
- [Cosa questa feature NON deve fare]
- [Scope esplicitamente escluso]
## Note aperte
- [Domande ancora da risolvere]
- [Decisioni da prendere]
## File coinvolti
- `path/to/file.ts` - [descrizione ruolo]
Esempi reali
Esempio 1: Feature di autenticazione
# Feature: Login con Magic Link
## Contesto
Il sistema attualmente supporta solo login con email/password.
Gli utenti dimenticano spesso la password e il flusso di reset
è lungo. Vogliamo offrire un'alternativa passwordless.
## Obiettivo
Permettere agli utenti di accedere cliccando un link
ricevuto via email, senza dover ricordare una password.
Ridurre i ticket di supporto per reset password del 40%.
## Comportamenti
### Scenario: Richiesta magic link
**Attore**: Utente registrato
**Pre-condizioni**:
- L'utente ha un account con email verificata
**Flusso principale**:
1. L'utente inserisce la propria email nel form di login
2. Clicca "Accedi con link magico"
3. Il sistema genera un token univoco (UUID v4)
4. Il sistema invia email con link contenente il token
5. L'utente vede conferma "Email inviata"
**Risultato atteso**:
- Email ricevuta entro 30 secondi
- Link valido per 15 minuti
**Flussi alternativi**:
- Se email non registrata: mostra stesso messaggio (no enumeration)
- Se rate limit superato: mostra "Riprova tra X minuti"
### Scenario: Click sul magic link
**Attore**: Utente con link valido
**Pre-condizioni**:
- Link non scaduto
- Link non già utilizzato
**Flusso principale**:
1. L'utente clicca il link nell'email
2. Il sistema valida il token
3. Il sistema crea sessione autenticata
4. L'utente viene reindirizzato alla dashboard
**Risultato atteso**:
- Utente loggato
- Token invalidato (one-time use)
**Flussi alternativi**:
- Se token scaduto: pagina "Link scaduto, richiedine uno nuovo"
- Se token già usato: pagina "Link già utilizzato"
## Vincoli
### Tecnici
- Token: UUID v4, scadenza 15 minuti
- Storage: tabella `magic_links` con indice su token
- Cleanup: job che elimina token scaduti ogni ora
### Di sicurezza
- Rate limit: max 3 richieste per email ogni 15 minuti
- Token hashed in database (non plaintext)
- Link HTTPS only
- Header `Referrer-Policy: no-referrer` nell'email
### Di performance
- Generazione token: < 50ms
- Invio email: < 5 secondi (async)
## Interfacce
### Input - Richiesta link
```json
POST /api/auth/magic-link
{
"email": "user@example.com"
}
Output - Richiesta link
{
"success": true,
"message": "Se l'email è registrata, riceverai un link"
}
Input - Validazione link
GET /api/auth/magic-link/verify?token=xxx
Output - Validazione link
{
"success": true,
"redirect": "/dashboard"
}
Criteri di accettazione
- [ ] Utente registrato riceve email con link entro 30s
- [ ] Link funziona una sola volta
- [ ] Link scaduto mostra errore user-friendly
- [ ] 4+ richieste in 15 min vengono bloccate
- [ ] Email non registrata non rivela se account esiste
- [ ] Token in DB è hashed, non plaintext
Non-goal
- Login via SMS (fase 2)
- Supporto multi-device simultaneo
- "Ricordami su questo dispositivo"
File coinvolti
src/services/auth/magic-link.ts- logica generazione/validazionesrc/routes/api/auth/magic-link.ts- endpointsrc/emails/magic-link.tsx- template emailprisma/schema.prisma- modello MagicLink
---
### Esempio 2: Feature di integrazione
```markdown
# Feature: Sync ordini con Shopify
## Contesto
I clienti usano Shopify per vendere, ma gestiscono fulfillment
nel nostro sistema. Attualmente importano CSV manualmente.
Vogliamo automatizzare con sync real-time.
## Obiettivo
Sincronizzare automaticamente gli ordini Shopify nel nostro
sistema entro 1 minuto dalla creazione, eliminando l'import
manuale e riducendo errori di data entry.
## Comportamenti
### Scenario: Nuovo ordine su Shopify
**Attore**: Sistema (webhook)
**Pre-condizioni**:
- Integrazione Shopify configurata per il merchant
- Webhook registrato su Shopify
**Flusso principale**:
1. Shopify invia webhook `orders/create`
2. Sistema valida HMAC signature
3. Sistema mappa campi Shopify → nostro modello
4. Sistema crea ordine in stato "pending"
5. Sistema notifica merchant via in-app notification
**Risultato atteso**:
- Ordine visibile nel dashboard entro 60s
- Dati cliente, prodotti, totali corretti
**Flussi alternativi**:
- Se HMAC invalido: log warning, return 401
- Se prodotto non mappato: crea ordine, flag "needs review"
- Se webhook duplicato: idempotent, return 200
## Vincoli
### Tecnici
- Idempotenza: stesso webhook processato una sola volta
- Retry: Shopify ritenta per 48h se non 2xx
- Queue: webhook processati via job queue (non sync)
### Di sicurezza
- Validazione HMAC obbligatoria
- Secret Shopify in env vars, mai in codice
- Log sanitizzati (no PII in chiaro)
### Di performance
- Response webhook: < 5 secondi
- Processing completo: < 60 secondi
## Interfacce
### Input - Webhook Shopify
```json
POST /api/webhooks/shopify/orders
Headers:
X-Shopify-Hmac-Sha256: [signature]
X-Shopify-Shop-Domain: store.myshopify.com
Body: [Shopify Order Object]
Output - Response
{ "received": true }
Dipendenze
- Shopify Admin API (per fetch dettagli se necessario)
- Redis (job queue)
- Servizio notifiche interno
Criteri di accettazione
- [ ] Ordine Shopify appare in dashboard entro 60s
- [ ] Webhook con HMAC invalido viene rifiutato
- [ ] Webhook duplicato non crea ordine duplicato
- [ ] Prodotti non mappati flaggano ordine per review
- [ ] Merchant riceve notifica per nuovo ordine
Non-goal
- Sync bidirezionale (ordini creati da noi → Shopify)
- Gestione resi/rimborsi
- Sync inventario
Note aperte
- [ ] Definire mapping prodotti: automatico o manuale?
- [ ] Notifica email oltre a in-app?
---
## Best practice
### 1. Scrivi i criteri di accettazione come test
Ogni criterio deve essere verificabile con un sì/no. Non "funziona bene" ma "risponde in meno di 200ms".
**Sbagliato**: "L'API deve essere veloce"
**Corretto**: "GET /orders risponde in < 200ms per liste fino a 100 elementi"
### 2. Includi sempre i non-goal
Prevenire scope creep è più facile che gestirlo. Se qualcosa è esplicitamente fuori scope, scrivilo.
### 3. Usa esempi concreti
Invece di "gestisce errori", scrivi:
- Se email non valida → `{ error: "INVALID_EMAIL" }`
- Se utente non trovato → `{ error: "USER_NOT_FOUND" }`
### 4. Mantieni le note aperte
Le domande irrisolte non sono debolezze, sono onestà. Meglio una domanda aperta che un'assunzione sbagliata nascosta.
### 5. Aggiorna la specifica
Se l'implementazione diverge dalla spec, aggiorna la spec. Un documento obsoleto è peggio di nessun documento.
---
## Specifiche per AI
Se usi agenti AI, aggiungi:
### File coinvolti
Lista esplicita di file che l'AI deve leggere/modificare.
### Pattern da seguire
Riferimenti a codice esistente che l'AI deve imitare.
### Formato output
Se vuoi codice in un certo stile, specificalo.
```markdown
## Istruzioni per implementazione AI
### File coinvolti
- `src/services/shopify/sync.ts` - servizio principale (da creare)
- `src/services/shopify/mapper.ts` - mapping dati (da creare)
- `src/routes/api/webhooks/shopify.ts` - endpoint webhook (da creare)
### Pattern da seguire
- Struttura servizi: vedi `src/services/auth/session.ts`
- Validazione input: vedi `src/utils/validation.ts`
- Error handling: vedi `src/errors/index.ts`
### Formato output
- TypeScript strict mode
- Zod per validazione runtime
- Nessun `any` esplicito
Conclusione
Una specifica non è burocrazia. È pensiero cristallizzato. Ti forza a rispondere alle domande difficili prima di scrivere codice, quando cambiare idea costa poco.
Il template che ti ho dato è un punto di partenza. Adattalo al tuo contesto, elimina sezioni inutili, aggiungi quelle che ti servono. L'importante è che ogni specifica risponda a:
- Perché stiamo costruendo questo?
- Cosa deve fare esattamente?
- Come facciamo a sapere che è fatto?
- Cosa NON deve fare?
Se sai rispondere a queste domande prima di iniziare, sei già avanti.
Vuoi migliorare il tuo processo?
Se vuoi introdurre specifiche strutturate nel tuo team o migliorare la qualità della documentazione tecnica, posso aiutarti.
Contattami per una consulenza su processi, documentazione e workflow di sviluppo.