Comprendo la tua domanda come " Dovresti convalidare i dati di input? ", invece di "Dovresti usare Eccezioni invece dei codici di errore?".
Quando accetti i parametri di input dall'esterno, che si tratti di un metodo con parametri di chiamata, dati di input XML da una chiamata di servizio o una pagina web con campi utente, hai fondamentalmente due scelte :
- effettua rigorus controlla se i dati di input corrispondono al formato previsto
- fidati del tuo chiamante solo per chiamarti con dati corretti
L'aggiunta di controlli aggiunge complessità
- lo sviluppatore iniziale deve pensare di tutti i valori validi (o "eventualmente non validi") e aggiungere controlli appropriati. Idealmente questo viene fatto all'inizio del metodo, anche se a volte deve essere fatto in seguito (ad esempio se "valore di input valido" è "l'ID di un oggetto effettivamente esistente nel database")
- altri sviluppatori che cercano di capire la reale logica del metodo, poiché aggiunge più linee per investigare.
-
overhead di runtime per controllare tutte le ipotesi
D'altro canto, la convalida dell'input offre preziosi vantaggi :
- Ti consente di rendere le ipotesi più in profondità nella codifica, poiché sono già verificate
- altri sviluppatori potrebbero avere più cose da leggere, ma fare delle ipotesi sui dati di input espliciti anche aiuta a capire la logica , e quei casi d'angolo sono presi in considerazione.
- Assicura che nessuno stato di programma corrotto (arresti anomali, corruzione dei dati, vulnerabilità della sicurezza) possa verificarsi.
Quindi la scelta di aggiungere controlli dovrebbe essere eseguita nel contesto dove viene utilizzato il tuo metodo.
- È esposto a dati esterni non attendibili, come siti Web o API pubbliche? Quindi esegui definitivamente la validazione.
- è un metodo privato in un cosiddetto inner-loop, protetto dalla codifica esterna? Quindi probabilmente non vuoi controlli ridondanti. Potresti voler documentare le tue aspettative (ad es. JavaDoc), anche se questo è raramente fatto in pratica.
- alcune lingue forniscono asserzioni compilate condizionatamente, che sono abilitate nelle build di debug per rilevare errori di logica del programma, ma disabilitate per le prestazioni in uso produttivo
- per le librerie devi decidere di quanto ti fidi dei chiamanti. Meglio sbagliare sul lato della cautela e aggiungere controlli, specialmente se non vuoi che i tuoi invarianti di libreria siano compromessi. Per le funzioni relative alla velocità, tuttavia, puoi decidere in modo diverso (e documentarlo).
- di solito viene eseguita una combinazione: buona convalida sui metodi di fronte esterno, alcune convalida sui livelli di interfaccia, pochissimi (spesso solo NullPointerCheck) nel funzionamento interno di un programma.
Se la tua domanda tuttavia era " Le eccezioni sono il modo giusto per segnalare i dati di input non validi? ", la risposta è: molto probabilmente sì .
Le
eccezioni impongono un sovraccarico sulle prestazioni del runtime, ma rendono il ragionamento sul flusso del programma drasticamente più semplice. Ciò riduce la programmazione errata (errori semantici), soprattutto perché ti costringe a gestirli - essi "falliscono in modo sicuro" chiudendo il programma se vengono ignorati. Sono ideali per "situazioni che non dovrebbero accadere". Inoltre possono trasportare i metadati come uno stacktrace.
I codici di errore , d'altra parte, sono leggeri, veloci, ma costringono il chiamante del metodo a controllarli esplicitamente. In caso contrario, i difetti del programma, che possono variare da un danneggiamento silenzioso dei dati, buchi di sicurezza, a dei fuochi d'artificio se il tuo programma è in esecuzione all'interno di un razzo spaziale.
Un esempio in cui personalmente avrei preferito i codici di errore invece delle eccezioni è il metodo String.parseInt () in Java. Ottenere una stringa non digitata da una sorgente di input (ad es. Un utente) non è del tutto inaspettato e devo affrontarlo in ogni caso - a volte semplice come usare un valore predefinito. Come chiamante, non ho modo di controllare i dati se provocherebbe un'eccezione (a meno di implementare la logica di validazione da solo), generando così l'eccezione come parte del normale flusso di programma e l'utilizzo di blocchi try-catch è l'unica scelta qui .
Tieni presente che i codici di errore potrebbero essere sia in-band che out-of-band:
-
In-band : un valore speciale (magico) viene dichiarato come marker per la condizione di errore. Spesso qui viene utilizzato null o -1, ad es. nei metodi di ricerca delle stringhe
-
Out-of-Band : viene restituito un valore separato, che indica "nessun errore" (in genere 0 o null) o l'errore specifico. Questo può essere fatto come / un parametro di ritorno aggiuntivo (per le lingue che supportano più valori di ritorno, ad esempio Googles GO lo supporta in particolare per gli errori) o come requisito per chiamare un metodo speciale "getError ()".