modulo 07 / lezione 42

Leggere e verificare codice generato

Flusso dei dati: input, trasformazioni, output

Seguire i dati nel codice per capire davvero cosa succede, dove si validano e dove possono rompersi.

75 min Vibe Coding

Flusso dei dati: input, trasformazioni, output

Il codice è un sistema di tubature: i dati entrano, scorrono, escono. Capire il flusso (chi mette cosa, chi trasforma cosa, chi consegna cosa) è il modo più rapido di capire un sistema. Più rapido di leggere file in ordine alfabetico. Più rapido di seguire commenti. Più rapido di fidarsi dei nomi.

Perché questa lezione conta

Bug e fragilità si nascondono dove il flusso ha “salti”: dato che entra in un punto e ne esce trasformato senza che sia chiaro chi e come. Validazione mancante, encoding sbagliato, normalizzazione inconsistente. Tracciare il flusso di un singolo dato (es. email) dall’input al database porta a galla problemi che non si vedono leggendo file isolati.

Obiettivo operativo

Alla fine devi saper:

  1. tracciare il percorso di un dato dall’input alla persistenza/visualizzazione;
  2. identificare i 6 punti di trasformazione tipici (parsing, validazione, mapping, calcolo, normalizzazione, serializzazione);
  3. trovare i punti di rottura potenziali in un flusso.

Nucleo della lezione

1. Da dove arriva un dato

Sei sorgenti di input tipiche:

Input utente diretto: form, click, drag, voice. Sempre non fidato. Va validato.

Parametri URL: query string (?q=foo), path params (/users/:id). Possono essere manipolati. Tipicizzazione: stringhe sempre, anche numeri.

Response API esterne: chiamate a servizi terzi. Non controllabili da te. Possono cambiare schema, fallire, lentamente.

File: upload, lettura disco. Encoding, formato, dimensione: variabili imprevedibili.

Variabili d’ambiente: process.env, file .env. Spesso stringhe, spesso assenti, da validare al boot.

Stato interno: cookie, localStorage, contesto del modello, cache. Persistenti, possono essere stale.

Per ognuno di questi, chiediti: chi controlla questo input? Quali ipotesi sto facendo che potrebbero essere violate?

2. Sei trasformazioni tipiche

Tra input e output, i dati passano attraverso queste fasi (in ordine variabile):

Parsing: stringa → struttura. JSON.parse, parseInt, parsing di date. Può fallire. Sempre gestire errore.

Validazione: il dato è coerente con le aspettative? (formato, range, lunghezza, presenza). Lato client per UX, lato server per sicurezza. Lib: zod, valibot, joi, yup, pydantic.

Mapping: trasformare la forma. Da DTO API a model interno. Da snake_case a camelCase. Da timestamp a Date. Mappature una alla volta, tipizzate.

Calcolo: derivazioni. Subtotale, score, distanza, conversione valuta. Logica di business pura.

Normalizzazione: rendere uniforme. Email lowercase, telefono in E.164, trim spazi, codifica unicode (NFC). Importante per ricerche e confronti.

Serializzazione: struttura → stringa. JSON.stringify, codifica per persistenza, formato output. Inverso di parsing.

Errore frequente: saltare normalizzazione → “ho cercato Mario, ma in DB è salvato come MARIO con spazio”. Errore di flusso, non di logica.

3. Punti di rottura

Cinque rischi tipici:

Validazione assente o insufficiente: input arriva al database non validato. Disastro.

Tipi mascherati: TypeScript dichiara string, runtime arriva undefined. Tipi sono compile-time, runtime serve verificare.

Encoding diverso fra layer: client manda UTF-8, DB gestisce in latin1. Caratteri italiani spariscono.

Timezone: data salvata come “2025-05-08T10:00:00”, senza timezone. Server in UTC, utente in CET. Errori sottili.

Numeri: float 0.1 + 0.2 !== 0.3. Per soldi, sempre intero (centesimi) o decimal. Mai float.

Null/undefined: dato opzionale arriva, codice assume presente, crash. Gestione esplicita.

Tracciare flusso = identificare dove ognuno di questi rischi può materializzarsi.

Procedura pratica

Tracciare un dato (es. “email” da iscrizione a profilo):

  1. Sorgente: form HTML. Tipo: stringa. Ipotesi: utente inserisce.
  2. Validazione client: regex/lib. Se fallisce, errore inline. Non sicurezza, solo UX.
  3. Invio API: POST /signup, body JSON {email: "..."}.
  4. Parsing server: JSON parser di framework. Verifica content-type.
  5. Validazione server: zod schema. Lunghezza, formato, possibilmente DNS check del dominio.
  6. Normalizzazione: email.toLowerCase().trim(). Standard.
  7. Check uniqueness: query DB.
  8. Mapping a model: { email: normalized, … }.
  9. Insert DB: query parametrizzata.
  10. Output: response JSON con id user creato (no email tornata, evita echo dati).
  11. Visualizzazione: in profilo, fetch dati user, mostra email come è.

Per ogni step: cosa accade se input è invalido? Cosa accade in errore? Quale è la “fonte di verità” finale?

Laboratorio guidato

Prendi un campo del tuo progetto (es. “prezzo”). Traccia flusso:

Inserimento prodotto admin:

  1. Form: input number → string "19.99".
  2. JS client: parseFloat("19.99") → 19.99 (float).
  3. Invio API: JSON {price: 19.99}.
  4. Server validation: range > 0, max 2 decimali.
  5. Conversione interna: a centesimi → 1999 (intero).
  6. Insert DB: colonna price_cents INTEGER.

Visualizzazione:

  1. Query DB: ottiene 1999.
  2. Mapping: → { priceFormatted: "€19,99" } per UI.
  3. UI: render testo.

Scenari di rottura:

  • Utente inserisce “19,99” (virgola italiana) → parseFloat ritorna 19 perso decimali.
  • Server riceve “19.99” come stringa, non casted → confronto fallisce.
  • Float salvato in DB → 19.989999... per arrotondamento.
  • Visualizzazione senza locale → mostra “19.99” anche in italiano.

Per ogni scenario: c’è gestione? Test? Mitigazione?

Output atteso

Diagramma testuale del flusso di un dato critico del progetto:

[Sorgente] → [Validazione client] → [API] → [Parsing] → [Validazione server]
  → [Normalizzazione] → [Mapping] → [Persistenza] → [Lettura] → [Mapping] → [UI]

Punti di rottura noti:
- ...

Mitigazioni:
- ...

Salvato in docs/data-flow-{nome}.md. Aggiornato quando il flusso cambia.

Studio passo passo

Studia questa lezione in tre passaggi, senza correre subito al prompt o al codice.

  1. Prima lettura: chiarisci l’obiettivo: seguire i dati nel codice per capire davvero cosa succede, dove si validano e dove possono rompersi. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
  2. Seconda lettura: trasforma i contenuti in domande operative:
  • Input utente, parametri URL, response API, file, variabili d’ambiente e stato interno.
  • Trasformazioni: parsing, validazione, mapping, calcolo, normalizzazione, serializzazione.
  • Output: UI, API response, database, file, log, eventi e messaggi di errore.
  1. Applicazione: svolgi il laboratorio: tracciare il percorso di un campo, per esempio email o prezzo, dall’inserimento alla persistenza o visualizzazione. L’output da ottenere è: un diagramma dati con punti di validazione, trasformazione e potenziale errore.

Prima di passare alla lezione successiva, controlla di avere un artefatto concreto: una tabella, un prompt, una checklist, un mini report, un diff commentato o una decisione scritta. Nel vibe coding la comprensione resta astratta finché non produce una traccia verificabile.

Checklist di verifica

  • ho tracciato flusso di almeno un dato critico nel mio progetto;
  • so dove avviene validazione (client + server);
  • so come è gestita normalizzazione (lowercase, trim, encoding);
  • ho test per i punti di rottura tipici;
  • conosco la fonte di verità per ogni dato.

Errori comuni

“Il modello mi dirà”. AI può spiegare, ma flusso è tuo da capire. Solo lavoro tu.

Validazione solo lato client. Già visto in lezione 26. Sicurezza richiede server.

Niente normalizzazione. Email Mario.Rossi@gmail.com e mario.rossi@gmail.com come due utenti diversi.

Float per soldi. Errori di arrotondamento. Centesimi interi o decimal.

Date senza timezone. Bug stagionali (DST), bug per utenti remoti.

Errori swallowed. try { ... } catch {} silenzia. Errore inghiottito = bug invisibile.

Tipi solo a compile-time. TS pensa che sia stringa, runtime dice altro. Validazione runtime per input esterni.

Prompt di lavoro

Tracciamo flusso di questo dato: [nome del dato, es. "email", "prezzo", "data ordine"]

Ho questi file rilevanti:
- [form/UI input]: ...
- [endpoint API]: ...
- [validazione/schema]: ...
- [persistenza]: ...
- [output/visualizzazione]: ...

Aiutami a costruire mappa del flusso. Per ogni step identifica:

1. Cosa entra (tipo, vincoli).
2. Cosa esce (tipo, trasformazioni applicate).
3. Validazioni presenti/assenti.
4. Punti di rottura potenziali (encoding, timezone, null, tipo).
5. Cosa cambierebbe in caso di input ostile o malformato.

Output: diagramma testuale + lista 5 punti di rottura prioritari + suggerimenti puntuali (no riscrittura).

Esercizio finale

Per un dato del tuo progetto in produzione, scrivi due test che simulano input malformati: uno che dovrebbe essere bloccato ma passa, uno che dovrebbe passare ma è bloccato. Spesso almeno uno dei due esiste. Quel test ti rivela un punto di rottura reale che il modello non avrebbe mai trovato senza tracciamento esplicito.