Analizza bug segnalati da altri con un workflow pratico per riprodurre problemi, isolare UI/API/DB e richiedere una correzione AI minima e testabile.

Fare il debug di un bug report che non hai scritto è più difficile perché ti manca la mappa mentale dell'autore. Non sai cosa è fragile, cosa è “normale” o quali scorciatoie sono state prese. Un piccolo sintomo (un pulsante, un refuso, una schermata lenta) può comunque provenire da un problema più profondo nell'API, nel database o in un job in background.
Un bug report utile ti dà quattro cose:
La maggior parte dei report dà solo l'ultimo: “Il salvataggio non funziona”, “è rotto”, “errore casuale”. Quello che manca è il contesto che lo rende ripetibile: ruolo utente, record specifico, ambiente (prod vs staging) e se è iniziato dopo una modifica.
L'obiettivo è trasformare un sintomo vago in una riproduzione affidabile. Una volta che riesci a farlo succedere a comando, non è più misterioso. È una serie di controlli.
Quello che puoi controllare subito:
“Fatto” non è “Penso di averlo risolto.” Fatto è: i tuoi passi di riproduzione passano dopo una piccola modifica e ritesti rapidamente i comportamenti vicini che potresti aver influenzato.
Il modo più veloce per perdere tempo è cambiare più cose contemporaneamente. Congela il punto di partenza in modo che ogni risultato del test significhi qualcosa.
Scegli un solo ambiente e attieniti a quello finché non riesci a riprodurre il problema. Se il report viene da produzione, confermalo lì prima. Se è rischioso, usa lo staging. Locale va bene se riesci ad avvicinare dati e impostazioni.
Poi individua quale codice è effettivamente in esecuzione: versione, data di build e qualsiasi feature flag o config che influenzi il flusso. Piccole differenze (integrazioni disabilitate, URL base API diverso, job in background mancanti) possono trasformare un bug reale in un fantasma.
Crea una configurazione di test pulita e ripetibile. Usa un account nuovo e dati noti. Se puoi, resetta lo stato prima di ogni tentativo (logout, pulisci cache, parti dallo stesso record).
Annota le assunzioni mentre procedi. Non è lavoro inutile; ti evita di discutere con te stesso dopo.
Un template per le note di baseline:
Se la riproduzione fallisce, queste note ti dicono cosa variare dopo, una manopola alla volta.
La vittoria più rapida è trasformare una lamentela vaga in qualcosa che puoi eseguire come uno script.
Inizia riscrivendo il report come una breve user story: chi fa cosa, dove e cosa si aspettava. Poi aggiungi il risultato osservato.
Esempio di riscrittura:
"Come amministratore fatturazione, quando cambio lo stato di una fattura in Pagata e clicco Salva nella pagina della fattura, lo stato dovrebbe persistere. Invece, la pagina resta uguale e lo stato non cambia dopo il refresh."
Poi cattura le condizioni che rendono vero il report. I bug spesso dipendono da un dettaglio mancante: ruolo, stato del record, locale o ambiente.
Input chiave da annotare prima di cliccare in giro:
Raccogli prove mentre hai ancora il comportamento originale. Gli screenshot aiutano, ma una breve registrazione è meglio perché cattura i tempi e i clic esatti. Segna sempre un timestamp (inclusa la timezone) così puoi abbinare i log dopo.
Tre domande chiarificatrici che rimuovono la maggior parte delle congetture:
Non iniziare indovinando la causa. Fai succedere il problema di proposito, nello stesso modo, più di una volta.
Per prima cosa, esegui i passi del reporter esattamente come scritti. Non "migliorarli". Nota il primo punto in cui la tua esperienza diverge, anche se sembra banale (etichetta del pulsante diversa, campo mancante, testo d'errore leggermente diverso). Quella prima discrepanza è spesso l'indizio.
Un flusso semplice che funziona nella maggior parte delle app:
Dopo che è ripetibile, varia una cosa alla volta. Test a variabile singola che spesso pagano:
Termina con uno script di repro breve che qualcun altro può eseguire in 2 minuti: stato iniziale, passi, input e la prima osservazione che fallisce.
Prima di leggere tutto il codice, decidi quale layer sta fallendo.
Chiediti: il sintomo è solo nella UI, o è anche nei dati e nelle risposte API?
Esempio: “Il mio nome profilo non si è aggiornato.” Se l'API restituisce il nuovo nome ma la UI mostra ancora il vecchio, sospetta lo stato UI/caching. Se l'API non lo ha mai salvato, sei probabilmente in area API o DB.
Domande rapide per il triage che puoi rispondere in pochi minuti:
I controlli UI riguardano la visibilità: errori nella console, scheda Network e stato stantio (UI che non fa refetch dopo il salvataggio o legge da cache vecchia).
I controlli API riguardano il contratto: payload (campi, tipi, ID), codice di stato e body di errore. Un 200 con un body sorprendente può contare tanto quanto un 400.
I controlli DB riguardano la realtà: righe mancanti, scritture parziali, vincoli violati, update che toccano zero righe perché la WHERE non matcha.
Per restare orientato, abbozza una piccola mappa: quale azione UI invoca quale endpoint e quali tabelle legge o scrive.
La chiarezza spesso arriva dal seguire una singola richiesta reale dal click fino al database e ritorno.
Cattura tre ancore dal report o dal tuo repro:
Se non hai un correlation ID, aggiungine uno nel gateway/backend e includilo negli header di risposta e nei log.
Per evitare di annegare nel rumore, cattura solo ciò che serve a rispondere “Dove è fallito e perché?”:
Segnali da tenere d'occhio:
Se “ieri funzionava” ma oggi no, sospetta deriva dell'ambiente: flag cambiati, segreti ruotati, migrazioni mancate o job che hanno smesso di girare.
Il bug più facile da fissare è un esperimento piccolo e ripetibile.
Riduci tutto: meno clic, meno campi, il dataset più piccolo che fallisce ancora. Se succede solo con “clienti con tanti record”, prova a creare un caso minimo che lo attivi. Se non ci riesci, è un indizio che il bug è legato al volume dei dati.
Separa lo “stato corrotto” dal “codice difettoso” resettando lo stato di proposito: account pulito, tenant o dataset fresco, build nota.
Un modo pratico per mantenere il repro chiaro è una tabella di input compatta:
| Given (setup) | When (azione) | Expect | Got |
|---|---|---|---|
| User role: Editor; one record with Status=Draft | Click Save | Toast "Saved" + updated timestamp | Button shows spinner then stops; no change |
Rendi il repro portabile così qualcun altro può eseguirlo rapidamente:
Il percorso più rapido è spesso noioso: cambia una cosa, osserva, prendi appunti.
Errori comuni:
Un esempio realistico: un ticket dice “Export CSV è vuoto.” Tu testi con un account admin e vedi i dati. L'utente ha un ruolo ristretto e l'API restituisce una lista vuota a causa di un filtro di permessi. Se applichi solo una patch sulla UI per mostrare “Nessuna riga,” perdi la questione reale: quel ruolo dovrebbe poter esportare o il prodotto dovrebbe spiegare perché è filtrato?
Dopo ogni fix, riesegui gli stessi passi di repro, poi testa uno scenario vicino che dovrebbe ancora funzionare.
Otterrai risposte migliori da un collega (o da uno strumento) se porti un pacchetto compatto: passi ripetibili, un layer probabile che fallisce e prove.
Prima che qualcuno cambi codice, conferma:
Poi fai una rapida passata di regressione: prova un ruolo diverso, un secondo browser/finestra privata, una funzionalità vicina che usa lo stesso endpoint/tabella e un input edge-case (vuoto, testo lungo, caratteri speciali).
Un messaggio di supporto dice: "Il pulsante Salva non fa nulla nel form Modifica Cliente." Un follow-up rivela che succede solo per clienti creati prima del mese scorso e solo quando cambi la email di fatturazione.
Inizia dalla UI e assumi il fallimento più semplice. Apri il record, fai la modifica e cerca segni che il “nulla” sia in realtà qualcosa: pulsante disabilitato, toast nascosto, messaggio di validazione che non viene renderizzato. Poi apri la console del browser e la scheda Network.
Qui, cliccando Salva si innesca una request, ma la UI non mostra mai il risultato perché il frontend considera successo solo il 200 e ignora gli errori 400. La Network tab mostra una risposta 400 con un body JSON come: {\"error\":\"billingEmail must be unique\"}.
Ora verifica che l'API falli davvero: prendi esattamente il payload dalla richiesta e replayalo. Se fallisce anche fuori dalla UI, smetti di inseguire bug di stato frontend.
Poi controlla il database: perché la unicità fallisce solo per i record più vecchi? Scopri che i clienti legacy condividono una billing_email segnaposto di anni fa. Un controllo di unicità più nuovo ora blocca il salvataggio di qualsiasi cliente che ha ancora quel segnaposto.
Repro minimo che puoi consegnare:
billing_email = [email protected].billingEmail must be unique.Test di accettazione: quando l'API restituisce un errore di validazione, la UI mostra il messaggio, conserva le modifiche dell'utente e l'errore indica esattamente il campo che è fallito.
Una volta che il bug è riproducibile e hai identificato il layer probabile, chiedi aiuto in modo da ottenere una patch piccola e sicura.
Prepara un semplice “case file”: passi minimi di repro (con input, ambiente, ruolo), expected vs actual, perché pensi sia UI/API/DB e l'estratto di log più piccolo che mostra il fallimento.
Poi rendi la richiesta stretta:
Se usi una piattaforma vibe-coding come Koder.ai (koder.ai), questo approccio con il case file mantiene la proposta focalizzata. I suoi snapshot e rollback possono anche aiutare a testare piccole modifiche in sicurezza e tornare a una baseline nota.
Affida a uno sviluppatore esperto quando la fix tocca sicurezza, pagamenti, migrazioni di dati o qualsiasi cosa che potrebbe corrompere i dati di produzione. Affida anche se la modifica continua a crescere oltre una patch piccola o non riesci a spiegare il rischio in parole semplici.
Inizia riscrivendo il report in uno script riproducibile: chi (ruolo), dove (pagina/flusso), quali input esatti (ID, filtri, payload), cosa ti aspettavi e cosa hai visto. Se manca qualche pezzo, chiedi un account di esempio e un ID record così puoi eseguire lo stesso scenario end-to-end.
Scegli un ambiente e resta su quello finché non riesci a riprodurre il problema. Registra poi build/versione, feature flag, configurazione, account/ruolo di test e i dati esatti usati. Questo ti evita di “risolvere” un bug che esiste solo perché il tuo setup non corrisponde a quello del reporter.
Fallo succedere due volte con gli stessi passi e input, poi rimuovi tutto ciò che non è necessario. Punta a 3–6 passi da uno stato pulito con un record o body riutilizzabile. Se non riesci a ridurlo, spesso indica dipendenza da volume di dati, temporizzazione o job in background.
Non cambiare nulla all’inizio. Esegui prima esattamente i passi del reporter e annota il primo punto in cui la tua esperienza diverge (etichetta del pulsante diversa, campo mancante, testo d’errore diverso). Quella prima discrepanza spesso indica la condizione reale che scatena il bug.
Controlla se i dati sono effettivamente cambiati. Se l’API restituisce il valore aggiornato ma la UI mostra ancora quello vecchio, è probabile uno stato UI, cache o mancato refetch. Se la risposta API è sbagliata o il salvataggio non avviene, concentra l’attenzione su API o DB. Se la riga DB non si aggiorna (o aggiorna zero righe), il problema è nella persistenza o nelle condizioni della query.
Verifica che una richiesta di rete venga inviata quando clicchi il bottone, poi ispeziona payload e body della risposta, non solo il codice di stato. Salva un timestamp (con timezone) e un identificatore utente così puoi incrociare i log di backend. Un 200 “di successo” con un body inaspettato può essere importante quanto un 400/500.
Varia un solo parametro alla volta: ruolo, record (nuovo vs legacy), browser/dispositivo, sessione pulita (incognito/cache svuotata) e rete. Testare a variabili singole ti dice quale condizione conta e ti impedisce di inseguire coincidenze causate dal cambiare troppe cose insieme.
Cambiare più variabili insieme, testare in un ambiente diverso da quello del reporter e ignorare ruoli/permessi sono le maggiori perdite di tempo. Un altro errore comune è correggere il sintomo superficiale in UI mentre sotto c’è ancora un errore di validazione API/DB. Dopo ogni modifica riesegui esattamente il repro e poi testa uno scenario vicino.
Considera “done” come: il repro minimo originale ora passa e hai ritestato un flusso vicino che potrebbe essere impattato. Mantieni il controllo concreto, per esempio un messaggio di successo visibile, la risposta HTTP corretta o la modifica attesa nel DB. Evita “penso sia risolto” senza rieseguire gli stessi input sulla stessa baseline.
Fornisci un case file conciso: passi minimi con input esatti, ambiente/build/flag, account e ruolo di test, expected vs actual e un pezzo di prova (request/response, testo d’errore o frammento di log con timestamp). Poi chiedi la patch più piccola che faccia passare il repro e includi un piccolo piano di test. Se usi Koder.ai, abbinare questo case file a snapshot/rollback aiuta a testare piccole modifiche in sicurezza e ripristinare se serve.