come posso spiegare che se i controlli (xyz == null) non sono “protettivi”

StackOverflow https://stackoverflow.com/questions/1647666

  •  22-07-2019
  •  | 
  •  

Domanda

ho alcuni sviluppatori che mettono costantemente Se controlli null

Ad esempio:

Run(Order order)
{
  if (order == null) return;
}

nel loro codice poiché pensano di proteggere la loro classe se qualcuno passa un parametro che è nullo. Sto cercando di dire loro il difetto nella loro logica perché se qualcuno sta passando nulla in questo caso, è molto probabilmente un problema con il codice del consumatore e invece di questa classe che genera un'eccezione e fallisce rapidamente, gestisce con grazia il cattivo comportamento di il consumatore e continua a rilassarsi.

un altro suggerimento è di avere una precondizione o una classe di guardia che falliscono velocemente e generano eccezioni. tutt'altro che ignorare il fatto che il consumatore probabilmente ha qualche altro problema e io sono di aiuto per mascherarlo.

come posso far capire alla gente che la tua classe non dovrebbe essere così indulgente. se qualcuno non trasmette dati validi, dovrebbero essere informati.

eventuali buoni articoli o suggerimenti per aiutarmi a superare questo punto?

È stato utile?

Soluzione

Se la tua classe non può accettare argomenti null , la cosa migliore da fare è questa:

if (arg == null)
    throw new ArgumentNullException();

Questo è decisamente preferibile per ottenere un NullPointerException più in profondità nello stack. Nel peggiore dei casi, memorizzerai nella cache quel null da qualche parte e in realtà non innescherai l'eccezione fino a molto tempo dopo, e vedrai quanto ti divertirai a eseguire il debug del problema quindi .

E come altri hanno affermato, a volte il contratto dice che null va bene. In tal caso, avere una clausola di guardia attorno ad alcune parti del codice è corretto, anche se anche allora direi che il miglior design sarebbe aggiungere un sovraccarico senza gli argomenti opzionalmente nulli.

Altri suggerimenti

Dipende davvero dalla situazione precisa. È raramente consigliabile dare suggerimenti generali come " non inserire controlli nulli nel codice " ;, come sembra stia indicando. Il contratto della classe dovrebbe definire ciò che è legittimo e ciò che non lo è. Ma se il contratto chiarisce che il passaggio a null non è accettabile, un'eccezione è davvero una risposta appropriata.

Come hanno detto tutti gli altri, è ampiamente preferibile fallire presto piuttosto che ottenere misteriosi problemi nella produzione perché la funzione non ha fatto nulla quando era previsto. se la funzione ritorna per argomenti null, come nel tuo esempio).

Anche se la funzione non ritorna e genera solo un NullReferenceException , è più desideroso di risolvere un bug quando sai che un argomento era nullo. Se una funzione genera un NullReferenceException , non hai idea di cosa fosse null o di chi fosse la colpa.

Vorrei aggiungere che ArgumentNullException accetta un parametro per un motivo.

È meglio scrivere

if(myArg == null) throw new ArgumentNullException("myArg");

che lanciare un ArgumentNullException senza un paramName .

In questo modo, se hai un'eccezione a una funzione che accetta cinque parametri, saprai quale dei parametri ha causato il problema. Ciò è particolarmente importante se non è possibile collegare un debugger. (Ad esempio, su un server Web di produzione o un computer dell'utente finale)

Se stai scrivendo molte funzioni, questo può essere un sacco di sovraccarico, soprattutto perché non c'è IntelliSense per le stringhe. Ho scritto uno snippet di codice per generare questi controlli:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Check for null arguments</Title>
            <Shortcut>tna</Shortcut>
            <Description>Code snippet for throw new ArgumentNullException</Description>
            <Author>SLaks</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
                <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>Parameter</ID>
                    <ToolTip>Paremeter to check for null</ToolTip>
                    <Default>value</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter<*>quot;);
        $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

I contratti di codice in .net 4.0 renderanno questo comportamento molto più coerente. Qualsiasi articolo che parla di contratti di codice aiuterà a far passare l'idea e, in futuro, questo tipo di sintassi fornirà il metodo.

http : //blogs.msdn.com/bclteam/archive/2008/11/11/introduction-to-code-contracts-melitta-andersen.aspx |

Non l'ho guardato, ma eiffel.com ha 2 presentazioni ( diapositive + audio) sull'argomento progettazione per contratto . Questi ragazzi hanno inventato il concetto, quindi se qualcuno può spiegarlo è loro :-)

A volte non puoi dire alla gente perché una pratica come questa è sbagliata - devono scoprirla da soli. Ma potresti aiutarli ad arrivare lì presentando alcuni test unitari che causano alcuni cattivi guasti a causa di questo problema e li fanno debug dell'errore.

Se il contratto del metodo specifica che i suoi argomenti non devono essere nulli, la cosa giusta da fare è renderlo esplicito, usando un Assert, come questo:

Debug.Assert( item != null, "Null items are not supported );

Ciò fallirà rapidamente quando l'eseguibile viene creato utilizzando una configurazione di debug, ma non presenterà un peggioramento delle prestazioni quando viene creato utilizzando una configurazione di rilascio.

Questa sembra essere una domanda sul modo migliore per scrivere il codice che è gestibile. Sono convinto che tu debba assumere l'ignoranza di tutti i consumatori del tuo codice. Mi sono messo nei guai supponendo che io o qualcuno con una profonda conoscenza consumerei il mio codice. L'unica cosa che aggiungerei al lancio di un'eccezione è la creazione di eccezioni personalizzate oltre a lasciare il pangrattato nell'eccezione interna. Credo fermamente nel dare ai tuoi sviluppatori la possibilità di risolvere il problema soprattutto se è dovuto ai dati. Trascorro la maggior parte del mio tempo a cercare i dati che violano il mio codice e se puoi lasciare dei suggerimenti risparmierai settimane in un anno.

Beh, prima di tutto, sei inequivocabilmente errato. Stai abbracciando un errore logico molto serio. Volete che il vostro codice sia corretto in virtù del codice presumendo che tutto ciò che accade attorno sia corretto. Come se la correttezza fosse una sorta di polvere magica di folletto che devi solo spruzzare ovunque.

Tutti i bug sono o sembrano stupidi una volta esposti. Ma i suoi controlli come questo li prendono in giro per esporsi. Fino ad allora, i bug sono invisibili. E per progetti abbastanza grandi e complessi, non sai chi troverà il bug o in quali condizioni saranno trovati. Il codice progettato per la resilienza in genere presenta controlli come questo ovunque e controlla anche i valori di ritorno per ogni funzione che deve includere valori di errore. Quindi finisci per codificare un " Non posso farlo perché le sotto-funzioni su cui faccio affidamento non funzionano " semantico che viene effettivamente gestito correttamente. Il grande valore di questo è che di solito è possibile implementare abbastanza facilmente soluzioni di lavoro o strumenti di debug autocoscienti. Perché vuoi fare cose del genere è perché i bug più difficili di solito si basano su entrambe le proprietà per eseguire correttamente il debug.

Impara alcune lezioni dai tuoi sviluppatori. Inseriscono assegni del genere, perché non sanno perché a volte ottengano strani risultati dalle funzioni. Li chiami ingenui o eccessivamente cauti a causa di una conoscenza ristretta che hai che non hanno. Ma quando esegui il debug di qualcosa di brutto ti chiederai perché non hai tali controlli nel tuo codice e finirai per sembrare altrettanto ingenuo per non essere in grado di individuare il bug in primo luogo.

In breve: nessun codice è reso robusto assumendo solidità per l'ambiente che li circonda.

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