Controllare un numero è un’interazione. Controllarne cinquantamila è un processo a lotti con una sua economia: il costo per riga deve essere piccolo, i modi di fallire devono essere leggibili senza che un essere umano legga ogni riga, e l’output deve essere abbastanza buono perché qualcuno possa agire la mattina dopo.
La tentazione è ripetere in ciclo la routine interattiva sull’intero file e stampare i fallimenti. Funziona per qualche centinaio di righe e poi crolla, perché produce rumore indifferenziato e nasconde i due fatti di cui un revisore ha davvero bisogno: quali righe sono sbagliate, e in che modo.
In che cosa differisce la validazione massiva dal controllo di un singolo valore?
Le differenze riguardano tutte ciò che accade dopo l’aritmetica. Un controllo interattivo restituisce un giudizio a una persona che può vedere il valore sullo schermo. Un controllo a lotti restituisce un giudizio per ogni riga di un file che nessuno ha ancora guardato, e il rapporto è l’unica cosa che qualcuno leggerà.
La scala cambia anche la forma del lavoro. Leggere un file grande in memoria tutto in una volta fallirà sugli input più grandi, quindi la catena deve funzionare in streaming. Ricalcolare la configurazione condivisa per ogni riga spreca la maggior parte del tempo di esecuzione, quindi le ricerche degli schemi dovrebbero essere risolte una volta sola. E la stessa riga può essere elaborata due volte se un processo si riavvia, quindi l’operazione deve essere sicura da ripetere.
Infine, il pubblico è diverso. Un rapporto a lotti viene letto da qualcuno che decide cosa correggere, il che significa che deve essere ordinato, categorizzato e specifico riguardo alla posizione. Il messaggio a valore singolo che dice che una cifra di controllo è fallita è tecnicamente corretto e praticamente inutile in un file con quarantamila righe.
Ogni valore citato in questo articolo è descritto anziché riportato. Un’esecuzione a lotti su dati reali dovrebbe avere tali valori mascherati prima che qualsivoglia cosa venga scritta in un rapporto, e gli esempi qui sono soltanto forme illustrative.
Prima pulire, poi validare: la catena
L’ordine delle operazioni è ciò che rende possibile il resto del lavoro, ed è lo stesso ordine di un controllo su singolo campo, applicato però riga per riga.
- Leggi il file come testo, conservando i valori originali esattamente come sono stati forniti.
- Normalizza ogni valore — elimina i separatori, comprimi gli spazi, riduci le maiuscole e minuscole — e conserva entrambe le forme.
- Risolvi lo schema o gli schemi per ogni riga, in base alla colonna da cui proviene il valore e, dove la colonna è mista, in base al valore stesso.
- Esegui il controllo appropriato, oppure registra che non si applica alcuna regola.
- Assegna ogni riga a una categoria, poi scrivi il rapporto.
Normalizzare l’intero file prima di validare significa che un unico percorso di codice gestisce sia il controllo sia l’analisi dei duplicati. Significa anche che il rapporto può mostrare entrambe le forme fianco a fianco, che è il modo più rapido per un revisore di notare un problema sistematico come un’intera colonna che arriva con un separatore in più.
Esegui la risoluzione dello schema una volta per ogni schema distinto anziché una volta per riga. Un file con un solo tipo di identificatore ha bisogno di una sola ricerca, e persino un file misto di solito contiene una manciata di forme distinte, quindi mettere in cache la risoluzione trasforma un costo per riga in un costo per file.
Quali categorie dovrebbe contenere un insieme di risultati?
Le categorie sono ciò che trasforma un elenco di fallimenti in una diagnosi, e dovrebbero corrispondere ai giudizi che il validatore già produce anziché inventare un nuovo vocabolario.
| Categoria | Cosa significa | Causa tipica |
|---|---|---|
| Controllato e valido | L’algoritmo pubblicato è stato applicato e il carattere finale concorda | Valori autentici, o valori generati per il test |
| Controllato e non valido | L’algoritmo è stato applicato e il carattere finale non concorda | Un errore di battitura nel corpo o nel carattere finale |
| Solo formato | La forma è stata confermata; nessun algoritmo è pubblicato | Uno schema nel livello intermedio di copertura |
| Schema sconosciuto | Nulla di ciò che lo strumento implementa corrisponde alla forma | Una colonna mista, un’intestazione fuori posto o un valore di un altro sistema |
| Duplicato | Il valore normalizzato compare altrove nel file | Lo stesso record esportato due volte |
I duplicati meritano una categoria propria anche se non sono fallimenti di validazione. In un’importazione sono spesso il singolo risultato più rilevante, e seppellirli tra righe malformate garantisce che vengano trascurati.
Tieni separati anche solo formato e sconosciuto. Portano ad azioni diverse: un risultato di solo formato significa che i dati sono buoni quanto è possibile giudicare, mentre uno schema sconosciuto richiede che qualcuno scopra cosa contiene davvero la colonna.
Duplicati, celle vuote e file molto grandi
Tre situazioni ordinarie spiegano la maggior parte della difficoltà nei file reali.
I duplicati devono essere rilevati sul valore normalizzato, perché due copie punteggiate in modo diverso di un numero sono lo stesso numero. Segnala la prima occorrenza come posizione ed elenca le altre come riferimenti, così un revisore può vedere se la ripetizione è accidentale o strutturale.
Le celle vuote non sono fallimenti. Uno spazio vuoto dove era richiesto un valore è un problema di completezza, e inserirlo nella categoria dei non validi gonfierà il conteggio degli errori e manderà qualcuno a cercare un bug della cifra di controllo che non esiste. Conta gli spazi vuoti separatamente, e lascia che il consumatore decida se sono accettabili.
I file grandi richiedono streaming e un profilo di memoria stabile. Leggi riga per riga, conserva solo l’indice di deduplicazione e i contatori, e scrivi le righe del rapporto a lotti così che l’output non diventi il collo di bottiglia. Se l’indice di deduplicazione stesso cresce oltre la memoria, ripiega su un’unione esterna ordinata o su un archivio temporaneo anziché cercare di tenere tutto in una volta.
Cosa rende un rapporto utilizzabile
Un revisore alle nove del mattino ha bisogno di quattro cose dall’output: il numero di riga, il valore come è arrivato, la categoria e una breve motivazione. Tutto il resto è decorazione.
I numeri di riga devono riferirsi a qualcosa che il revisore possa trovare. Di’ chiaramente se sono righe del file o righe di dati, perché un’intestazione le sposta di uno e un revisore che si fida della convenzione sbagliata modificherà il record sbagliato. Includi il valore originale esattamente come fornito, poiché è quello che cercherà, e includi la forma normalizzata quando differisce.
Anche l’ordine conta. Raggruppare per categoria mette insieme ogni istanza di un problema, il che permette a un revisore di riconoscere uno schema anziché leggere quarantamila righe. Dentro una categoria, ordina per riga così il file può essere modificato dall’alto verso il basso.
Infine, rendi onesto il riepilogo. Un conteggio delle righe valide deve dire quale giudizio lo ha prodotto, perché un file in cui la maggior parte delle righe è di solo formato è stato confermato solo nella forma, e un riepilogo che le segnala come valide verrà citato fuori contesto.
Per gli sviluppatori: suddivisione in blocchi, concorrenza e idempotenza
Il livello di batching è dove uno script funzionante diventa un processo affidabile.
- Elabora a blocchi dimensionati in base alla memoria anziché a numeri tondi, e rendi configurabile la dimensione del blocco.
- Parallelizza l’aritmetica, non l’output. Ogni worker dovrebbe restituire risultati, e un unico scrittore dovrebbe assemblare il rapporto così che l’ordine resti deterministico.
- Rendi l’esecuzione idempotente: lo stesso file di input deve produrre lo stesso output, compreso l’ordine, così due esecuzioni possono essere confrontate.
- Registra la versione dell’insieme di regole e il checksum dell’input nell’intestazione del rapporto, così un risultato può essere riprodotto mesi dopo.
- Non scrivere mai valori completi nei log. I rapporti sono destinazioni per i valori, i log no, e la regola di mascheramento va applicata prima che qualsiasi cosa lasci il processo.
Il mascheramento non è opzionale quando il file contiene valori reali. Un’esecuzione massiva legge tutto in una volta, quindi un singolo rapporto non oscurato è un’esposizione molto più grande di un singolo invio di modulo fallito. Decidi prima della prima esecuzione quali colonne possono essere riprodotte e quali devono essere troncate. Il legame tra un’esecuzione a lotti e l’API che la alimenta vale la pena di essere letto dopo: la validazione ai confini delle API copre cosa dovrebbe fare il servizio ricevente quando il file arriva, e come funziona la validazione dei numeri è la logica per riga su cui questa catena è costruita.
Passi successivi
Esegui il tuo processo attuale su un file che contenga deliberatamente una riga per ogni categoria — una riga valida, una riga non valida, una riga di solo formato, una forma sconosciuta e un duplicato — e controlla se il rapporto rende tutte e cinque evidenti senza aprire il file di origine. Lo strumento di validazione dei numeri è un posto comodo per confermare la formulazione di ogni giudizio prima di fissarla nel formato del rapporto.