Devo controllare i null in setter e metodi simili?

0

Ho un sacco di setter nelle mie classi, oltre a molti metodi per aggiungere un elemento o un insieme di elementi agli elenchi o alle mappe.

Dovrei controllare i null per ognuno di essi, o dovrei permettere che NullPointerException accada? Questo è pericoloso per le mappe, dato che potrei finire con valori nulli e non vorrei che.

Quindi in pratica, se ho questo:

public void setMyMap(Map<Key, List<Value>> map) {
    myMap = map;
}

public void addItem(Key k, Value v) {
    if (map.containsKey(k)) 
        map.get(k).add(v);
    else
        map.put(k, new ArrayList<Value>(Arrays.asList(v)));
}

public void addItems(Key k, List<Value> values) {
    for (Value v : values) addItem(k, v);
}

Ecc. Dovrei farlo?:

public void setMyMap(Map<Key, List<Value>> map) {
    if (map != null) myMap = map;
}

public void addItem(Key k, Value v) {
    if (k == null || v == null)
        return;

    if (map.containsKey(k)) 
        map.get(k).add(v);
    else
        map.put(k, new ArrayList<Value>(Arrays.asList(v)));
}

public void addItems(Key k, List<Value> values) {
    if (k == null || values == null)
        return;

    for (Value v : values) addItem(k, v);
}

Domanda a margine: non mi piace usare return; come ho fatto io. Normalmente vorrei avvolgere l'intero blocco in un'istruzione if controllando se entrambi non sono nulli, piuttosto che uscire prima dal metodo. Sono accettate entrambe le pratiche? Quale dovrei piuttosto fare? O è solo una questione di gusti?

    
posta dabadaba 20.04.2016 - 21:22
fonte

3 risposte

1
public void setMyMap(Map<Key, List<Value>> map) {
   if (map != null) myMap = map;
  }

Finirà anche con null :-). Se non si desidera consentire a null di essere tu a lanciare l'eccezione di runtime con un IllegalArgumentException.

È un vecchio problema.

Cosa fare con null?

Preferisco controllare i null al livello aziendale o al livello di controllo, ma mai al livello di persistenza né alle entità del modello dati. Non è la loro responsabilità (coerenza dei dati / integrità). Responsabilità di costruttore / fabbrica.

Ho anche lasciato che DB lanciasse i propri errori se qualsiasi null è settato in una colonna non nulla. Il problema è al lavoro, non alla facciata di persistenza.

Può essere l'eccezione del controllo dei null (nel tuo caso) sarebbe a addItem / s , removeItem / s . Perché non succede niente se non possono fare la sua funzione. Il risultato sarà lo stesso di passare una lista vuota o un oggetto nullo.

Nell'ultimo caso, non è sempre consentito aggiungere oggetti nulli. Dipende dall'implementazione della mappa.

Se c'è un po 'di funzionalità, allora spetta a te controllare null o lanciare la tua eccezione.

Un'altra possibile soluzione potrebbe essere

public void setMyMap(Map<Key, List<Value>> map) {
    if (map != null) myMap = map ? 
         new HashMap<Key,Value>();
 }

Quindi myMap non sarà mai nullo. A causa di questo ultimo cambiamento non devo preoccuparmi di myMap.

    
risposta data 20.04.2016 - 21:43
fonte
3

No, non dovresti assolutamente farlo. È necessario prendere una decisione su dove null è accettabile. Se è accettabile che la mappa sia nullo, impostala sull'argomento senza controllare. In caso contrario, lancia un'eccezione perché il chiamante si fa incazzare e devono trovarlo il prima possibile .

Certamente non impostarlo su un valore completamente casuale, come il valore precedente, una nuova mappa arbitraria, o impostarlo su null comunque.

OnErrorGotoNext è una strategia terribile. Non impiegarlo. Se il tuo chiamante non ha rispettato il contratto del metodo, throw nei loro volti.

    
risposta data 20.04.2016 - 22:22
fonte
0

Si riduce a ciò che viene passato un null a questo punto significa e quali problemi causerà in seguito.

Se la specifica di questo metodo chiarisce che il superamento di un valore nullo non è accettabile, in questo momento puoi giustamente generare una NullPointerException. In questo caso cambia il tuo codice qui sopra per lanciare l'eccezione piuttosto che restituire null o andare con la tua prima versione e utilizzare il Lombok @NonNull annotazione.

Se è accettabile che il chiamante passi il nulla e la specifica del metodo dichiari che semplicemente non aggiungerà gli elementi nulli, allora la seconda opzione va bene. Tuttavia, ti consiglio di inserire una linea di log adatta in modo che tu possa scoprire da dove vengono, nel caso in cui sia inaspettata.

L'ultima opzione è che va bene chiamare con null e che la specifica del metodo dice che la aggiungerà alla mappa. In tal caso, potrebbe voler ancora mettere un test in una riga di log di nuovo semplicemente in modo che se il null inserito continua a causare problemi in altre sezioni del codice usando la tua collezione puoi ottenere una traccia di quale codice l'ha messo lì in primo luogo.

In pratica di programmazione difensiva, è ragionevole trattare i valori nulli il più vicino possibile alla fonte. Considerando che un tempo era noioso codice gesso come hai elencato in tutte le posizioni pertinenti, l'annotazione Lombok rende ora la scrittura di un codice difensivo molto economico - certamente molto più economico del costo di provare a fare il debug perché il consumatore della tua lista occasionalmente cadrà con una NullPointerException.

(Osservazione finale ... se il codice sopra è veramente quello che stai scrivendo, dovresti forse guardare Guava ListMultiMap )

    
risposta data 20.04.2016 - 21:56
fonte

Leggi altre domande sui tag