Passer null à une méthode
Je suis dans le milieu de la lecture de l'excellent Code Propre
Une discussion concernant la transmission des valeurs null dans une méthode.
public class MetricsCalculator {
public double xProjection(Point p1, Point p2) {
return (p2.x - p1.x) * 1.5;
}
}
...
calculator.xProjection(null, new Point(12,13));
Il représente les différentes façons de traiter ce:
public double xProjection(Point p1, Point p2) {
if (p1 == null || p2 == null) {
throw new IllegalArgumentException("Invalid argument for xProjection");
}
return (p2.x - p1.x) * 1.5;
}
public double xProjection(Point p1, Point p2) {
assert p1 != null : "p1 should not be null";
assert p2 != null : "p2 should not be null";
return (p2.x - p1.x) * 1.5;
}
Je préfère le les assertions approche, mais je n'aime pas le fait que les assertions sont désactivés par défaut.
Le livre enfin états:
Dans la plupart des langages de programmation il n'y a pas de bonne façon de traiter avec une valeur null qui est transmis par un appelant accidentellement. Parce que c'est le cas, l'approche rationnelle est d'interdire passage de la valeur null par défaut.
Il n'a pas vraiment comment vous le feriez appliquer cette restriction?
N'importe quel d'entre vous ont des opinions fortes.
source d'informationauteur toolkit
Vous devez vous connecter pour publier un commentaire.
À la fois l'utilisation d'allégations et le fait de lancer des exceptions sont des approches valables ici. Soit le mécanisme peut être utilisé pour indiquer une erreur de programmation, pas une erreur d'exécution, comme c'est le cas ici.
Le choix dépend vraiment de l'pratiques en matière de développement du projet. L'ensemble du projet doit décider sur une affirmation politique: si le choix est de permettre à des affirmations cours de développement, je dirais que pour utiliser les assertions de vérifier ce genre de paramètre non valide - dans un système de production, une NullPointerException levée en raison d'une erreur de programmation est peu probable d'être en mesure d'être capturées et traitées de manière significative, de toute façon et donc va agir comme une affirmation.
Pratiquement, si, je sais que beaucoup de développeurs qui n'ont pas confiance, que les assertions sera activée lorsque cela est approprié et ainsi opter pour la sécurité de lancer une exception NullPointerException.
Bien sûr, si vous ne pouvez pas appliquer une politique de votre code (si vous êtes en train de créer une bibliothèque, par exemple, et donc dépendent de la façon dont d'autres développeurs d'exécuter votre code), vous devez opter pour l'approche sécuritaire de jeter NullPointerException pour ces méthodes qui font partie de la bibliothèque de l'API.
Règle générale est que si votre méthode ne vous attendez pas
null
arguments, alors vous devriez jeter Système.ArgumentNullException. Jetant bonException
vous protège non seulement contre des ressources de la corruption et d'autres mauvaises choses, mais sert comme un guide pour les utilisateurs de votre code d'économiser le temps passé à déboguer votre code.Également lire un article sur Une programmation défensive
Également pas d'usage immédiat, mais liées à la mention de Spec#... Il y a une proposition visant à ajouter "null-sûr type" pour une future version de Java: "Améliorée de la gestion des valeurs null - Null-safe types".
En vertu de la proposition, votre méthode pourrait devenir
où
#Point
est le type de non-null
des références à des objets de typePoint
.Vous faire respecter, il en jetant un ArgumentExcexception si ils passent dans la valeur null.
Je préfère l'utilisation d'affirmations.
J'ai une règle que je n'utilise que des assertions contenues dans le public et protégé méthodes. C'est parce que je crois que la méthode d'appel doit s'assurer qu'il est en train de passer des arguments valables pour des méthodes privées.
Spec# a l'air très intéressant!
Quand quelque chose comme ce qui n'est pas disponible, en général, je test non-méthodes privées avec un null-case, et les revendications des méthodes internes. Plutôt que de code le nul de vérifier explicitement dans chaque méthode, j'ai délégué à une classe d'utilitaires avec un chèque null méthode:
Puis de vérifier, se transforme en:
Que peuvent être ajoutées à l'aide de l'éditeur de macros, ou un code-script de traitement.
Edit: détaillé vérifier pourrait être ajoutée de cette façon, mais je pense que c'est nettement plus facile à automatiser l'ajout d'une seule ligne.
J'ai trouvé JetBrains'
@Nullable
et@NotNull
annotations approche pour traiter cette question avec le plus ingénieux, jusqu'à présent. C'est de l'IDE spécifique, malheureusement, mais très propre et puissant, de l'OMI.http://www.jetbrains.com/idea/documentation/howto.html
Avoir cette (ou quelque chose de similaire) comme un standard java serait vraiment sympa.
Bien qu'il n'est pas strictement lié, vous voudrez peut-être jeter un oeil à Spec#.
Je pense qu'il est encore en développement (par Microsoft), mais certains CTP sont disponibles et il semble prometteur. Fondamentalement, il vous permet de le faire:
ou
Il fournit également une autre des caractéristiques comme Notnull types. Il est construit sur le sommet de la .NET Framework 2.0 et il est entièrement compatible. Le syntaxt, comme vous pouvez le voir, est C#.
@Chris Karcher, je dirais tout à fait correcte. La seule chose que je dirais est de vérifier les paramètres séparément et ont l'exeption rapport au param c'était nul aussi car il rend le suivi de où la valeur null est à venir à partir de beaucoup plus facile.
@wvdschel wow! Si l'écriture du code, c'est trop d'effort pour vous, vous devriez regarder dans quelque chose comme PostSharp (ou Java équivalent si un seul est disponible) qui peut post-traiter vos assemblées et insérez param vérifie pour vous.
Légèrement hors-sujet, mais une des caractéristiques de findbugs que je pense est très utile, c'est d'être capable d'annoter les paramètres de méthodes pour décrire les paramètres ne doivent pas être passé à une valeur nulle.
À l'aide de l'analyse statique de code, findbugs peut ensuite point des endroits où la méthode est appelée avec potentiellement une valeur null.
Cela a deux avantages:
Utile seulement si vous avez accès au code qui appelle vos méthodes ... mais c'est habituellement le cas.
Depuis hors-sujet semble être devenu le sujet, Scala prend une approche intéressante. Tous les types sont supposés être non nulle, sauf si vous explicitement l'envelopper dans un
Option
pour indiquer qu'il peut être null. Donc:Je préfère en général ne pas le faire, puisque c'est seulement ralentir les choses. NullPointerExceptions sont jetés plus tard, de toute façon, ce qui conduira rapidement à l'utilisateur de découvrir qu'ils sont en passant null à la méthode. J'ai utilisé pour vérifier, mais 40% de mon code a fini par être le code de vérification, à quel point j'ai décidé qu'il était juste pas la peine de la belle affirmation des messages.
Je suis d'accord ou pas d'accord avec wvdschel postça dépend de ce qu'il est précisément en train de dire.
Dans ce cas, bien sûr, cette méthode se crash sur
null
de sorte que la vérification explicite ici n'est probablement pas nécessaire.Cependant, si la méthode stocke simplement les données passées, et il y a une autre méthode que vous appeler plus tard qui permettra de traiter avec elle, la découverte de mauvaise entrée le plus tôt possible est la clé de la résolution de bugs plus rapidement. À ce moment plus tard, il pourrait y avoir une multitude de façons que les données de mauvaise qualité qui est arrivé à être donné à votre classe. C'est en essayant de comprendre comment les rats sont venus dans votre maison après le fait, en essayant de trouver le trou quelque part.
Thwrowing C#
ArgumentException
ou JavaIllegalArgumentException
à droite au début de la méthode me semble que le plus clair de solutions.Il faut toujours être prudent avec les Exceptions d'Exécution - les exceptions qui ne sont pas déclarés à la signature de la méthode. Puisque le compilateur ne les appliquent pas vous attraper ces il est vraiment facile de les oublier. Assurez-vous que vous avez une sorte de "catch all" gestion des exceptions pour éviter que le logiciel d'arrêter brusquement. C'est la partie la plus importante de votre expérience utilisateur.
La meilleure façon de traiter ce serait vraiment l'utilisation d'exceptions. En fin de compte, l'affirme allez finir par donner une similaire l'expérience de l'utilisateur final, mais sans préciser de façon pour le développeur d'appeler votre code pour gérer la situation, avant de montrer une exception à l'utilisateur final. Ultimatley, vous voulez vous assurer que vous tester pour les entrées invalides dès que possible (surtout en public en face de code) et de fournir les exceptions appropriées que le code appelant pouvez attraper.
Dans une Java façon, en supposant que la valeur null vient d'une erreur de programmation (ie. ne doit jamais aller à l'extérieur de la phase de test), puis laissez le système de le jeter, ou si il y a des effets secondaires atteindre ce point, vérifier la valeur null au début et à la jeter, soit IllegalArgumentException ou NullPointerException.
Si la valeur null peut venir d'une réelle exceptional affaire, mais vous ne voulez pas utiliser un checked exception pour que, alors vous avez certainement envie d'aller le IllegalArgumentException route au début de la méthode.