Sono d'accordo con @MartinMaat sulla scelta delle tue battaglie.
Ci sono molti casi di "just in case" a causa della scarsa comprensione della lingua nonostante il linguaggio sia fissato nelle sue regole per molte di queste cose - oltre a parentesi di un'espressione che non ne ha bisogno a causa della mancata comprensione del regole di precedenza della lingua. Ma ancora, tale pratica è per lo più innocua.
Quando ero più giovane, sentivo che dovevamo imparare i dettagli della lingua e quindi evitare di scrivere un codice così superfluo. (Uno dei miei pet-peeves era return (0);
con i suoi paramenti superflui.) Tuttavia, ora moderatore quella posizione, in particolare, perché usiamo così tante lingue diverse ora, saltando da client a server, ecc ... Quindi, io ora riduciamo il gioco per alcuni di questi problemi.
Il punto sul ciclomatico inizia ad andare su argomenti logicamente ragionati. Diamo un'occhiata a Copertura del codice e in particolare livelli più elevati di copertura :
- Each decision takes every possible outcome
Poiché non possiamo forzare la nuova operazione a restituire NULL, non c'è modo di raggiungere livelli più elevati di copertura del codice per questa operazione condizionale. Naturalmente, questo può non essere importante per la tua organizzazione!
Tuttavia, a causa di questo problema di copertura del codice, lo assegnerei una priorità più alta rispetto alla sovra-parentesi.
D'altro canto, il codice generato sottostante non subirà probabilmente un bit per questo poiché le generazioni di codice, JIT e gli ottimizzatori comprendono tutti che un valore new
ed non sarà mai nullo. Quindi, il costo reale viene fornito solo in termini di leggibilità e capacità di copertura del codice sorgente.
Vorrei chiederti a cosa assomiglia la "parte opposta" di una simile affermazione?
Se non c'è altra parte, direi che semplicemente cadere alla fine della routine o cadere in un altro codice (cioè non else
per questa if
) è potenzialmente pericoloso, poiché ora questo "solo nel caso in cui "logicamente suggerisce che i chiamanti e / o ulteriore codice lungo la linea gestisce anche NULL.
Se legge:
p = new Object ();
if ( p != null ) {
p.field = value;
}
else {
throw new NullReferenceException ();
}
allora questo è davvero eccessivo, poiché il linguaggio fa tutto questo per noi.
Potrei suggerire di invertire il senso del condizionale - forse il tuo collega sarà più a suo agio in questo:
p = new Object ();
if ( p == null ) {
throw new NullReferenceException ();
}
else {
p.field = value;
}
Ora puoi discutere della rimozione del wrapper else, poiché è molto chiaramente non necessario:
p = new Object ();
if ( p == null ) {
throw new NullReferenceException ();
}
p.field = value;
Con questo, il "just in case" ora è ciò che è condizionale, mentre il codice successivo non lo è. Questo approccio rafforza ulteriormente il fatto che quando l'allocazione fallisce, la risposta appropriata viene lanciata, piuttosto che continuare a eseguire il codice in questo metodo e / o in questa catena di chiamate (senza alcuna altra corretta gestione dell'errore di allocazione).
Quindi, in sintesi ci sono due argomenti logicamente ragionati per fare qui contro questa pratica:
- Non è possibile raggiungere livelli di copertura del codice più elevati poiché non è possibile forzare la memoria esaurita (o qualsiasi errore del costruttore) per restituire null.
- Il "just in case" (come mostrato sopra nella domanda) è incompleto e come tale è viziato a causa dell'incongruenza delle aspettative su come dovevano essere nulle gestito da altro codice oltre / passato il
p.field = value;
.
Fondamentalmente, sembra che forse il tuo collega stia cercando di usare le eccezioni, anche se in C # non c'è scelta per queste cose. ( Se vogliamo codice ben testato non possiamo codificare sia per un modello di eccezione per la gestione di null e un modello non-eccezione che utilizza valori di ritorno null, affiancati.) Forse se ragionate con il tuo collega attraverso questi argomenti, vedranno un po 'di luce!