Comment puis-je expliquer que si (xyz == null) les contrôles ne sont pas & # 8220; protecteurs & # 8221;

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

  •  22-07-2019
  •  | 
  •  

Question

J'ai quelques développeurs qui mettent constamment If if null checks

Par exemple:

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

dans leur code car ils pensent protéger leur classe si quelqu'un passe dans un paramètre qui est null. J'essaie de leur expliquer la faille dans leur logique car si quelqu'un passe à null dans ce cas, il s'agit probablement d'un problème avec le code du consommateur et au lieu que cette classe lève une exception et échoue rapidement, elle gère gracieusement le mauvais comportement de le consommateur et continuer à chugging loin.

une autre suggestion est d’avoir une classe de précondition ou de garde qui échoue rapidement et jette des exceptions. en ignorant le fait que le consommateur a probablement un autre problème et que je l’aide à le masquer.

comment amener les gens à apprécier le fait que votre classe ne devrait pas être aussi tolérante. si quelqu'un ne transmet pas de bonnes données, il faut le prévenir.

de bons articles ou des suggestions pour m'aider à faire passer ce message?

Était-ce utile?

La solution

Si votre classe ne peut pas accepter les arguments null , la meilleure chose à faire est la suivante:

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

Cela est nettement préférable à une NullPointerException plus en profondeur dans la pile. Dans le pire des cas, vous mettrez en cache ce null quelque part et ne déclencherez l'exception que bien plus tard, et vous verrez à quel point vous aurez du plaisir à déboguer le problème puis .

Et comme d’autres l’ont dit, le contrat stipule parfois que null est acceptable. Dans ce cas, il est correct d’avoir une clause de garde autour de certaines parties du code, même si j’aimerais dire que la meilleure solution serait d’ajouter une surcharge sans les arguments optionnellement nuls.

Autres conseils

Cela dépend vraiment de la situation précise. Il est rarement conseillé de donner des suggestions générales telles que "ne mettez pas de contrôles nuls dans votre code", comme vous semblez l'indiquer. Le contrat de la classe devrait définir ce qui est légitime et ce qui ne l’est pas. Mais si le contrat stipule clairement que la nullité n'est pas acceptable, une exception constitue une réponse appropriée.

Comme tout le monde l’a déjà dit, il est nettement préférable d’échouer de bonne heure que d’obtenir de mystérieux problèmes de production car la fonction n’a rien fait quand on s’y attendait. si la fonction retourne pour des arguments nuls, comme dans votre exemple).

Même si la fonction ne retourne pas et lève simplement une NullReferenceException , il est plus facile de résoudre un bogue si vous savez qu'un argument est nul. Si une fonction lève une NullReferenceException , vous n’avez aucune idée de ce qui était null ni de sa faute.

J'aimerais ajouter que ArgumentNullException prend un paramètre pour une raison.

Il vaut mieux écrire

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

que de lancer une ArgumentNullException sans NomParam .

Ainsi, si vous avez une exception à une fonction prenant cinq paramètres, vous saurez lequel des paramètres a été à l'origine du problème. Ceci est particulièrement important si vous ne pouvez pas attacher un débogueur. (Par exemple, sur un serveur Web de production ou sur une machine utilisateur final)

Si vous écrivez de nombreuses fonctions, cela peut être très onéreux, d’autant plus qu’il n’ya pas d’IntelliSense pour les chaînes. J'ai écrit un extrait de code pour générer ces vérifications:

<?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>

Les contrats de code dans .net 4.0 rendront ce comportement beaucoup plus cohérent. Tous les articles qui parlent de contrats de code aideront à faire passer l'idée et, à l'avenir, ce type de syntaxe fournira la méthode.

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

Je ne l'ai pas visionné, mais eiffel.com a 2 présentations ( diapositives + audio) sur le thème de conception par contrat . Ces personnes ont inventé le concept, donc si quelqu'un peut l'expliquer, c'est eux :-)

Parfois, vous ne pouvez pas dire aux gens pourquoi une telle pratique est fausse - ils doivent le découvrir eux-mêmes. Mais vous pouvez les aider à atteindre cet objectif en proposant un test unitaire qui provoque une mauvaise défaillance en raison de ce problème, et leur demander de déboguer l'erreur.

Si le contrat de la méthode spécifie que ses arguments ne doivent pas être nuls, la meilleure chose à faire est de l'expliciter, en utilisant un Assert, comme ceci:

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

Cela échouera rapidement lorsque l'exécutable sera créé à l'aide d'une configuration de débogage, mais ne présentera aucune dégradation de performances lorsqu'il sera construit à l'aide d'une configuration finale.

Cela semble être une question sur la meilleure façon d’écrire du code gérable. C'est ma nouvelle conviction que vous devez assumer l'ignorance de tous les consommateurs de votre code. Je me suis attiré des ennuis en supposant que moi-même ou une personne ayant une connaissance approfondie consomme mon code. La seule chose que j'ajouterais au lancement d'une exception serait de créer des exceptions personnalisées tout en laissant des chapelures dans l'exception interne. Je crois fermement qu'il est important de donner à vos développeurs une chance de résoudre le problème, en particulier s'il s'agit de données. Je passe le plus clair de mon temps à rechercher les données qui cassent mon code et si vous pouvez laisser des indices, vous économiserez des semaines dans une année.

Eh bien tout d’abord, vous êtes sans aucun doute incorrect. Vous vous engagez dans une très grave erreur logique. Vous voulez que votre code soit correct en vertu du code en supposant que tout ce qui se passe autour de lui est correct. Comme si la justesse était une sorte de poussière magique de lutin que vous avez juste besoin de vaporiser partout.

Tous les insectes sont ou semblent stupides une fois qu’ils sont exposés. Mais ce sont des chèques comme celui-ci qui les taquinent pour s'exposer. Jusque-là, les bugs sont invisibles. Et pour les projets assez grands et complexes, vous ne savez pas qui trouvera le bogue ni dans quelles conditions il sera trouvé. Le code qui est conçu pour la résilience a généralement des contrôles comme celui-ci et vérifie également les valeurs de retour pour chaque fonction devant inclure des valeurs d'erreur. Vous finissez donc par coder "Je ne peux pas le faire parce que les sous-fonctions sur lesquelles je compte ne fonctionnent pas". sémantique qui est réellement traitée correctement. La grande valeur de ceci est que vous pouvez généralement implémenter assez facilement des contournements ou une instrumentation de débogage en pleine conscience. Pourquoi voulez-vous procéder de la sorte, c'est que les bogues les plus difficiles reposent généralement sur ces deux propriétés pour déboguer correctement.

Apprenez quelques leçons de vos développeurs. Ils mettent des chèques comme ça là-dedans, parce qu'ils ne savent pas pourquoi parfois, ils obtiennent des résultats étranges de fonctions. Vous les appelez naïfs ou excessivement prudents en raison d'un savoir étroit que vous possédez et qu'ils ne maîtrisent pas. Mais lorsque vous déboguez quelque chose de méchant, vous allez vous demander pourquoi vous n'avez pas de telles vérifications dans votre code, et vous allez avoir l'air tout aussi naïf de ne pas pouvoir repérer le bogue en premier lieu.

En bref: aucun code n’est robuste en supposant que son environnement est robuste.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top