Un visualizzatore di repository che ho fatto l'estate scorsa ha otto commit nella sua prima settimana. I primi quattro non toccano una sola riga di applicazione: sono l'init dal mio template e tre commit di documentazione. Il quinto è già l'app intera.
Non è stata disciplina. È che scrivendo il documento ho scoperto di avere sbagliato il modello mentale dell'integrazione, e sistemarlo in un .md costava venti minuti invece di due giorni.
L'errore di partire dal codice in un'integrazione altrui
Quando la logica è tua, leggere il codice è la migliore documentazione che esista. Quando dipende da una API altrui, no: quello che ti serve sapere non sta nel tuo codice né nel loro. Sta nei limiti, nelle quote e nei parametri deprecati.
In quel visualizzatore per un po' ho confuso due connessioni con lo stesso provider. L'OAuth di login e il token di server per leggere l'API sembrano la stessa cosa e non lo sono. Uno serve a far entrare un umano, l'altro a far leggere il server. Falliscono in modo diverso. Scriverlo in un documento diviso in due sezioni è quello che mi ha fatto vedere che un visualizzatore di repo pubblici aveva bisogno solo del secondo.
Se fossi partito dal codice, l'avrei scoperto al terzo 401.
Cosa documento esattamente prima della prima riga
Non documento il design della mia app. Documento quello che non controllo. Nello specifico:
- I limiti reali, misurati, non citati. Non basta copiare "5.000 richieste all'ora" dal sito. L'ho chiesto all'endpoint della quota: 60/h senza autenticazione, 5.000/h autenticato, 30/min in ricerca. E ho misurato che un
304 Not Modifiednon consuma quota — 4972, 4972, 4972 con le condizionali, e 4971 nella stessa chiamata senzaIf-None-Match. Quel numero che si ripete è l'argomento centrale del documento, e senza eseguirlo non ce l'hai. - Quello che non si può automatizzare. La OAuth App non si crea da CLI: non c'è un endpoint per crearla né per leggere il client secret, che si mostra una volta sola nel browser. È un passo manuale, e il giorno in cui rimonterai l'ambiente te ne sarai dimenticato.
- I tetti che sorprendono in produzione. 2.000 creazioni di token all'ora, che è un tetto di login, non di richieste. E riautorizzazione forzata se un utente entra dieci volte in un'ora. Nessuno dei due compare quando leggi l'happy path.
- Quello che la decisione NON risolve. Ho annotato che obbligare al login non elimina la necessità di cache condizionale, perché il bucket dell'utente è condiviso con il suo PAT e con altre app che agiscono a suo nome. Se non lo scrivi, la decisione ti dà una falsa sicurezza.
Niente di tutto questo è opinabile. Sono fatti che o verifichi o ti inventi.
I cookbook: provare ogni pezzo isolato prima di integrarlo
In un servizio di IA per l'analisi documentale ho fatto lo stesso in un altro modo. Prima che qualsiasi pezzo entrasse nel servizio, ognuno aveva un cookbook: uno script che lo esegue da solo, scrive il suo output in una cartella e si registra in un run_all_cookbooks. Parser di PDF, chunker, embedding, rilevatore di numeri, estrazione verificabile. Uno per pezzo.
Il valore non è il test. È che quando l'output del chunker cambia forma, si vede in un file di testo invece che in un errore tre strati più su. Passando la pipeline ad asincrono, i cookbook sono diventati runner con asyncio.run e la migrazione si è fatta pezzo per pezzo, non tutta insieme.
Il costo è che vanno cancellati quando smettono di valere. Mesi dopo c'è un commit che toglie i cookbook deprecati. Un cookbook che non corrisponde più al pezzo è peggio di nessun cookbook.
La documentazione come fonte di verità per auditare dopo
In una galleria di concetti di UI ho scritto prima una guida di design del pezzo — taglie, scala di spaziatura, scala di grigi, quale primitiva si usa per cosa — e poi ho auditato il codice contro di essa.
La cosa interessante è che l'audit ha corretto la guida, non solo il codice. Tre cose che il .md diceva di meno: che il grigio di accompagnamento si gradua in cinque scalini e non in due; che la scala di spaziatura ha quattro gradini e non tre, perché chiamarla da tre trasformava sei usi legittimi in deriva; e che i tre dialoghi sono in realtà lo stesso dialogo, con la stessa scatola e la stessa intestazione, e non dicendolo la correzione era stata applicata a uno solo.
Senza documento preventivo quelle tre scoperte non esistono. Non hai niente con cui confrontare e tutto quello che trovi è "a me sembra".
Quando questo è tempo perso
Il criterio che uso:
- Se l'integrazione è tua da cima a fondo, non documentare prima. Il codice è la verità e il documento invecchia.
- Se è un prototipo che butterai, nemmeno. Un gioco che ho scritto in un giorno non ha niente di scritto e va bene così.
- Se il documento ripeterà quello che dice il riferimento ufficiale, non scriverlo. Serve solo se contiene le tue misure, le tue versioni e le trappole che sono toccate a te.
E c'è un errore che mi è costato caro: il documento scritto prima si porta dentro le tue supposizioni. Nel visualizzatore, la sezione sull'hosting descriveva una piattaforma serverless perché l'avevo dato per scontato scrivendo l'incarico, non perché qualcuno l'avesse deciso. Correggendolo in un container di lunga vita è cambiata l'intera conclusione: in serverless l'SDK di agenti non ci stava; in un worker con quindici minuti di limite per richiesta, sì.
Per questo il passo successivo non è opzionale. C'è un commit il cui unico lavoro è verificare il documento contro fonti vive: eseguire la query che compare nella guida, mandare una versione di API non valida perché sia l'API stessa a elencare quelle valide, controllare che per_page=500 venga tagliato a 100 in silenzio, tipizzare lo snippet che non compilava in modalità strict. Quel commit ha scoperto che 18 delle 20 "issue" restituite erano in realtà pull request.
Un documento non verificato è una supposizione con una bella formattazione. Un documento verificato è l'unica parte dell'integrazione che non ti mentirà tra sei mesi.
