Domanda

I & # 8217; m da uno sfondo .NET e ora dilettandomi in Java.

Attualmente sto riscontrando grossi problemi nel progettare un'API in modo difensivo contro input errati. Supponiamo che io abbia il seguente codice (abbastanza vicino):

public void setTokens(Node node, int newTokens) {
    tokens.put(node, newTokens);
}

Tuttavia, questo codice può fallire per due motivi:

  1. L'utente passa un nodo null .
  2. L'utente passa un nodo non valido, ovvero uno non contenuto nel grafico.

In .NET, lancerei un ArgumentNullException (piuttosto che un NullReferenceException !) O un ArgumentException rispettivamente, passando il nome dell'argomento offensivo ( nodo ) come stringa argomento.

Java non sembra avere eccezioni equivalenti. Mi rendo conto che potrei essere più specifico e semplicemente lanciare qualsiasi eccezione si avvicini di più alla descrizione della situazione, o anche a scrivere la mia classe di eccezioni per la situazione specifica.

È questa la migliore pratica? Oppure ci sono classi di uso generale simili a ArgumentException in .NET?

In questo caso ha anche senso verificare con null ? Il codice fallirà comunque e la traccia dello stack dell'eccezione conterrà la chiamata del metodo sopra. Il controllo su null sembra ridondante ed eccessivo. Certo, la traccia dello stack sarà leggermente più pulita (poiché il suo obiettivo è il metodo sopra, piuttosto che un controllo interno nell'implementazione HashMap di JRE). Ma questo deve essere compensato dal costo di un'ulteriore istruzione if , che, inoltre, non dovrebbe mai avvenire comunque & # 8211; & nbsp; dopo tutto, passando null al metodo precedente non è una situazione prevista, è un bug piuttosto stupido. Aspettarsi che sia decisamente paranoico & # 8211; & nbsp; e fallirà con la stessa eccezione anche se non lo cerco.

[Come è stato sottolineato nei commenti, HashMap.put in realtà consente valori null per la chiave. Quindi un controllo contro null non sarebbe necessariamente ridondante qui.]

È stato utile?

Soluzione

Diversi gruppi hanno standard diversi.

In primo luogo, presumo che tu conosca la differenza tra RuntimeException s (non selezionata) e Eccezione normale (selezionata), se non poi vedi questa domanda e le risposte . Se scrivi la tua eccezione, puoi forzare il rilevamento, mentre sia NullPointerException che IllegalArgumentException sono RuntimeExceptions che sono disapprovati in alcuni ambienti.

In secondo luogo, come con te, i gruppi con cui ho collaborato ma non usano attivamente assert, ma se il tuo team (o consumatore dell'API) ha deciso che utilizzerà assert, allora asserisce che i suoni sono esattamente come il meccanismo corretto.

Se fossi in te userei NullPointerException . La ragione di ciò è precedente. Prendi un esempio API Java da Sun, ad esempio java.util.TreeSet . Questo utilizza NPE proprio per questo tipo di situazione, e mentre sembra che il tuo codice abbia appena usato un valore null, è del tutto appropriato.

Come altri hanno affermato IllegalArgumentException è un'opzione, ma penso che NullPointerException sia più comunicativo.

Se questa API è progettata per essere utilizzata da società / team esterni, rimarrei con NullPointerException , ma assicurati che sia dichiarata in javadoc. Se è per uso interno, potresti decidere che vale la pena aggiungere la tua stessa gerarchia di eccezioni, ma personalmente trovo che le API che aggiungono enormi gerarchie di eccezioni, che saranno solo printStackTrace () d o registrate sono solo uno spreco di sforzi.

Alla fine della giornata, la cosa principale è che il tuo codice comunica chiaramente. L'erarchia di un'eccezione locale è come il gergo locale: aggiunge informazioni per gli addetti ai lavori ma può confondere gli estranei.

Per quanto riguarda il controllo contro null, direi che ha senso. In primo luogo, ti consente di aggiungere un messaggio su ciò che era null (ovvero nodo o token) quando costruisci l'eccezione che sarebbe utile. In secondo luogo, in futuro potresti utilizzare un'implementazione di Map che consente null , quindi perderai il controllo degli errori. Il costo è quasi nulla, quindi a meno che un profiler non dica che si tratta di un problema di circuito interno, non me ne preoccuperei.

Altri suggerimenti

L'eccezione Java standard è IllegalArgumentException . Alcuni lanceranno NullPointerException se l'argomento è nullo, ma per me NPE ha quel "qualcuno che ha rovinato". connotazione e non vuoi che i clienti della tua API pensino di non sapere cosa stai facendo.

Per le API pubbliche, controlla gli argomenti e fallisci in modo tempestivo e pulito. Il tempo / il costo conta a malapena.

In Java normalmente si genera un'eccezione IllegalArgumentException

Se vuoi una guida su come scrivere un buon codice Java, posso consigliare vivamente il libro Efficace Java di Joshua Bloch.

Sembra che questo potrebbe essere un uso appropriato per un assert :

public void setTokens(Node node, int newTokens) {
    assert node != null;
    tokens.put(node, newTokens);
}

Il tuo approccio dipende interamente dal contratto che la tua funzione offre ai chiamanti: è un prerequisito che il nodo non sia nullo?

Se lo è, dovresti generare un'eccezione se il nodo è null, poiché si tratta di una violazione del contratto. In caso contrario, la tua funzione dovrebbe gestire in silenzio il nodo null e rispondere in modo appropriato.

Penso che molto dipenda dal contratto del metodo e dalla conoscenza del chiamante.

Ad un certo punto del processo, il chiamante potrebbe agire per convalidare il nodo prima di chiamare il metodo. Se conosci il chiamante e sai che questi nodi sono sempre convalidati, penso che sia giusto supporre che otterrai buoni dati. Essenzialmente la responsabilità è sul chiamante.

Tuttavia, ad esempio, se si sta fornendo una libreria di terze parti distribuita, è necessario convalidare il nodo per valori null, ecc.

Un illegalArugementException è lo standard java ma è anche RunTimeException. Pertanto, se si desidera forzare il chiamante a gestire l'eccezione, è necessario fornire un'eccezione di controllo, probabilmente una personalizzata che si crea.

Personalmente, vorrei che NullPointerExceptions si verificasse SOLO per caso, quindi è necessario utilizzare qualcos'altro per indicare che è stato passato un valore di argomento illegale. IllegalArgumentException va bene per questo.

if (arg1 == null) {
 throw new IllegalArgumentException("arg1 == null");
}

Questo dovrebbe essere sufficiente sia per coloro che leggono il codice, ma anche per la povera anima che riceve una chiamata di supporto alle 3 del mattino.

(e, SEMPRE fornire un testo esplicativo per le tue eccezioni, le apprezzerai un giorno triste)

come l'altro: java.lang.IllegalArgumentException. Informazioni sul controllo del nodo null, che dire del controllo di input errati durante la creazione del nodo?

Non devo piacere a nessuno, quindi quello che faccio ora come codice canonico è

void method(String s) 

if((s != null) && (s instanceof String) && (s.length() > 0x0000))
{

che mi fa dormire molto.

Altri non saranno d'accordo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top