8
votes

Les références dans les langages de programmation orientées objet sont-elles non nullables par défaut?

Les pointeurs NULL ont été décrits comme le " € de milliards de dollars ". Certaines langues ont des types de référence qui ne peuvent pas être attribués à la valeur null.

Je me demande si vous souhaitez concevoir un nouveau langage orienté objet si le comportement par défaut devrait être destiné aux références pour éviter d'être attribués null. Une version spéciale du peut alors être utilisée pour remplacer ce comportement. Par exemple: P>

MyClass notNullable = new MyClass();
notNullable = null; // Error!
// a la C#, where "T?" means "Nullable<T>"
MyClass? nullable = new MyClass();
nullable = null; // Allowed


7 commentaires

Passer au langage de programmation fonctionnel ;-)


@jldupont: veuillez poster cela comme une réponse.


J'ai ajouté un lien. Bien sûr, NULLS ne sont pas aussi gros de problème en Java, C # ou Python, comme chez C ou C ++. Cependant, il reste encore beaucoup de code de plaque de chaudière dans ces langues dédiées à la vérification nulle, et beaucoup de temps de développement dépensé à la poursuite des pointeurs NULL. Type de stupide lorsque vous pensez que cela pourrait être évité à la compilation, en ajoutant un personnage supplémentaire.


Un pointeur null est dangereux. Une référence d'objet nulle n'est pas; Si vous n'avez pas utilisé NULL pour indiquer une référence d'objet non initialisée, vous devez inventer une autre valeur sentinelle pour servir le même objectif


@Steven A Lowe - Le but est de se débarrasser de la possibilité de «l'état non initialisé» / sentinelle lorsqu'il est inutile (le cas commun). Vous pouvez toujours revenir avec un type nullable si nécessaire.


BTW, la conversation enregistrée est ici: Infoq. com / présentations / ...


Dupliqué possible de types de référence non nullables , Que-S-Le-puevue-of-null


7 Réponses :


5
votes

L'obstruction principale que je vois aux types de référence non nullables par défaut est que certaines parties de la communauté de programmation préfèrent le modèle d'utilisation de création-set: xxx

sur les constructeurs surchargés: xxx

et cela laisse le concepteur API dans une liaison avec la valeur initiale des variables d'instance qui pourraient sinon être null.

bien sûr, comme 'null «lui-même, le modèle d'utilisation de la création de création crée de nombreux états d'objet sans signification et empêche les invariants utiles, donc en train de débarrasser de cela est vraiment une bénédiction plutôt qu'une malédiction. Cependant, cela affecte un peu de conception de l'API de manière à ce que beaucoup de gens ne soient pas familiers. Ce n'est donc pas quelque chose à faire à la légère.

mais dans l'ensemble, oui, s'il y a un grand cataclysme qui détruit tous les Langues et compilateurs, on ne peut que l'espoir que lorsque nous reconstruisons, nous ne répéterons pas cette erreur particulière. La nullabilité est l'exception, pas la règle!


2 commentaires

Un X.Prop non nullable doit être réglé sur une valeur défectueuse ou une valeur vide significative. Le consommateur de l'API peut ensuite le remplacer comme avant, mais sachez du type qu'ils ne peuvent pas la mettre à NULL.


Je pense qu'un X.Prop non nullable devrait être garanti d'être initialisé avant d'être utilisé. Si vous avez besoin d'un état «non initialisé», c'est ce que NULL est pour, et peut-être que X.Prop devrait effectivement être nullable.



-1
votes

null n'est qu'un problème, car les développeurs ne vérifient pas que quelque chose est valide avant de l'utiliser, mais si les gens commencent à abuser de la nouvelle construction nullable, il n'aura pas résolu de véritables problèmes.

Il est important de simplement vérifier que chaque variable pouvant être NULL est vérifiée avant d'être utilisée, et si cela signifie que vous devez utiliser des annotations pour permettre de contourner le chèque, sinon, sinon le compilateur pourrait échouer compiler jusqu'à ce que vous vérifiez.

Nous mettons de plus en plus logiques dans les compilateurs pour protéger les développeurs d'eux-mêmes, qui sont effrayants et très tristes, car nous savons ce que nous devrions faire, et pourtant sauter des étapes.

Donc, votre solution sera également soumise à des abus et nous serons de retour à l'endroit où nous avons commencé, malheureusement.

mise à jour:

Basé sur certains commentaires ici, c'était un thème de mes réponses. Je suppose que j'aurais dû être plus explicite dans ma réponse originale:

Fondamentalement, si l'objectif est de limiter l'impact des variables nulles, demandez à ce que le compilateur jette une erreur lorsqu'une variable n'est pas vérifiée pour NULL, et si vous souhaitez supposer que cela ne sera jamais nul, alors besoin d'une annotation. ignorer le chèque. De cette façon, vous donnez aux gens la capacité de supposer, mais vous facilitez également de trouver tous les endroits du code qui possèdent l'hypothèse et, dans un examen de code, il peut être évalué si l'hypothèse est valide.

Cela aidera à protéger tout en limitant le développeur, mais il est facile de savoir où il est supposé ne pas être nul.

Je pense que nous avons besoin de flexibilité et je préférerais que la compilation prendrait plus de temps que quelque chose d'avoir une incidence négative sur le runtime, et je pense que ma solution ferait ce qui est souhaité.


13 commentaires

Votre troisième paragraphe a bogué mon esprit. Vous souhaitez éviter des solutions automatisées à des problèmes courants car les humains ont besoin du travail supplémentaire pour promouvoir l'éthique de ne pas «sauter des marches»?


Oui, je suis d'accord avec Brian ici. Plus de travail est mis en compilateurs pour rendre les développeurs plus productifs. Pragmatisme pas idéalisme.


@Brian - J'ai suggéré que nous puissions forcer le développeur à indiquer que certaines variables peuvent être nuls et ne seront pas vérifiées, car nous supposons que ce ne sera pas nul, mais c'est aussi loin que j'irais, comme c'est Difficile d'abuser, et s'il est abusé, il est facile d'écrire un outil qui vérifie tous les non-contrôles et décidez s'ils sont valides, dans un examen de code, par exemple.


@Jason - C'est bien, si nous mettons quelque chose dans le compilateur, nous devrions faciliter la connaissance de l'intention, donc cela peut être vérifié. Mais, il y a tellement de façons de mettre dans des trous de sécurité, les développeurs doivent être plus prudents, sinon nous pouvons également interdire les requêtes SQL dynamiques et forcer toutes les questions à utiliser des déclarations préparées.


@James Black: Le compilateur est un détail de mise en œuvre.


@barkmadley - Je trouve SQL dynamique à être utile, mais c'est quand j'utilise rien de l'utilisateur dans la requête, en particulier s'il n'y a pas de paramètres à passer. La solution Haskell était intéressante, BTW.


blog.moertel. com / articles / 2006/10/18 / ... dynamique SQL Bad ... supprimé mon autre commentaire


@Jason - Ne mettez pas quelque chose dans le langage qui peut être maltraité lorsque le pointeur NULL est actuellement. Pour moi, c'est la solution la plus pragmatique, comme alors que quelqu'un peut regarder pour voir où le développeur suppose qu'il ne peut pas être nul et vérifie que l'hypothèse est valide.


@James Black: Il est presque impossible d'empêcher la maltraitance de la langue. Il n'y a pas de construction ni d'outil pouvant sauver de mauvais programmeurs d'eux-mêmes (à court de piratage de leurs doigts). Les contrats de code, cependant, sont une très belle idée.


@James Black: Si le compilateur conserve une valeur d'être NULL, cela utilise essentiellement un type non nullable, à l'exception de Devs peut toujours le modifier à NULL plus tard (en supposant que la référence soit réglée). Je veut le compilateur pour rendre ma vie plus facile en garantissant cela de manière à ce que la valeur n'est pas null , pas seulement "supposé ne pas être nulle".


@ Apollode217 - Si vous utilisez une chaîne, par exemple, quelle est la valeur quand elle n'est pas définie? Il est dans un état inconnu, comme vous ne l'avez jamais défini explicitement, NULL est aussi bonne valeur que tout, sinon vous supposez ce que c'est. C'est un problème trouvé dans certaines langues où les pointeurs du mode de débogage peuvent être définis sur zéro, mais en libération ne sont pas définis du tout, alors peut pointer n'importe où n'importe où. Donc, si vous ne voulez pas que ce soit dans un état inconnu, définissez-le lorsque vous le déclarez.


@James Black: Vous avez déjà proposé une fonctionnalité de compilateur pour veiller à ce que les valeurs soient initialisées à quelque chose avant d'avoir accès, éliminant ainsi la nécessité de NULL dans ces cas. Ce sont les cas où la nullabilité est une nuisance (IMAO). Si la variable ne représente rien ou ne serait pas ininitialisée, il devrait être d'un type nullable.


@ Apollode217 - Toute solution aura des compromis entre protéger le programmeur des erreurs stupides et gêner le programmeur. J'ai tendance à opter pour laisser le programmeur créer des problèmes s'il choisit, mais essayez de vous assurer que de manière non intrusive, vous essayez de protéger le programmeur.



4
votes

J'aime la méthode OCAML de traiter avec le problème "peut-être nul". Chaque fois qu'une valeur de type 'A code> peut être inconnue / indéfinie / unialistialisée, elle est enveloppée dans un type code>' "une option code>, qui peut être soit Aucun code > ou certains x code>, où x code> est la valeur non nullable réelle. Lorsque vous accédez au x code>, vous devez utiliser le mécanisme correspondant pour débrancher. Voici une fonction qui augmente un integer nullable et renvoie 0 sur Aucun code> xxx pré>

Comment fonctionne: p>

 >>> let f = function  Some x -> x+1 ;;
 Characters 8-31:
 let f = function  Some x -> x+1 ;;
         ^^^^^^^^^^^^^^^^^^^^^^^
 Warning P: this pattern-matching is not exhaustive.
 Here is an example of a value that is not matched:
 None
 val f : int option -> int = <fun>


1 commentaires

+1 F # prend également en charge les types d'options, mais malheureusement, il doit toujours prendre en compte les nulls du framework .NET.



1
votes

Même mieux, désactivez les références nulles. Dans de rares cas où "rien" est une valeur valide, il pourrait y avoir un état d'objet qui correspond à cela, mais une référence indiquerait toujours à cet objet, ne pas avoir de valeur nulle.


2 commentaires

Est-ce le modèle d'objet NULL? EN.Wikipedia.org/wiki/Null_Object_Pattern


Je n'ai pas eu le modèle nul à l'esprit, mais des types d'options: en.wikipedia.org/wiki/Option_Type < / a>



1
votes

Si je comprends bien, la justification de Martin Odersky pour inclure NULL à Scala consiste à utiliser facilement les bibliothèques de Java (c'est-à-dire que toutes vos API ne semblent pas avoir, par exemple, "objet?" partout):

http://www.artima.com/scalazine/articles/goals_f_scala.html

Idéalement, je pense que NULL doit être inclus dans la langue en tant que fonctionnalité, mais non nullable doit être la valeur par défaut pour tous les types. Cela ferait économiser beaucoup de temps et prévenir les erreurs.


0 commentaires

-1
votes

non.

L'état de uninitialisé existe de manière sûre en raison de la nécessité logique; Actuellement, la dénotation est NULL.

Peut-être un concept "valide mais non initialisé" d'un objet peut être conçu, mais comment est-ce significativement différent? La sémantique de "accéder à un objet non initialisé" existe toujours.

Un meilleur itinéraire consiste à avoir une vérification du temps statique que vous n'écrivez pas à un objet qui n'est pas affecté à (je ne peux pas penser à quelque chose en haut de ma tête qui empêcherait que les devises de string). < / p>


3 commentaires

Le point que j'essayais de faire était que la nécessité d'une "valeur non initialisée" ou "sentinelle" pour une variable ou un argument est l'exception plutôt que la règle. Quand il est nécessaire, je ne vois aucune raison de ne pas utiliser "NULL", et le formulaire nullable (par exemple "mytype?").


"Vérification du temps statique que vous n'écrivez pas à un objet qui n'est pas affecté à" l'initialisation des guranties, mais ne garantit pas contre NULL (c'est-à-dire que cela peut toujours être initialisé ou ensuite remplacé par NULL). Ce sont des problèmes distincts. Et si vous avez un paramètre de méthode qui ne devrait jamais être nul? Un contrôle statique pour vous assurer que la valeur n'est pas null est à l'aide d'un type non nullable. Vérification de NULL manuellement et de faire face à NullReferenceException est douloureuse.


Non, types peut utiliser être utilisé. Ils ne doivent pas être ...



0
votes

La plus grande "erreur liée à NULL" dans la conception linguistique est l'absence d'un piège lors de l'indexation des pointeurs NULL. De nombreux compilateurs vont piéger lorsque vous essayez de déréférence, un pointeur NULL ne piège pas si l'on ajoute un décalage à un pointeur et essaie de la désarférence. Dans la norme C, essayer d'ajouter le décalage est un comportement indéfini et le coût de la performance de la vérification du pointeur ne serait pas pire que de vérifier la déséroférence (surtout si le compilateur pouvait se rendre compte que s'il vérifiait que le pointeur était non null Ajout du décalage, il pourrait ne pas avoir besoin de revérifier par la suite).

En ce qui concerne la prise en charge linguistique pour les variables non nullables, il peut être utile d'avoir un moyen de demander que certaines variables ou champs dont les déclarations comprennent une valeur initiale devraient automatiquement tester toutes les écritures afin de s'assurer qu'une exception immédiate se produira si une exception immédiate sera une tentative est fait pour écrire NULL pour eux. Les matrices pourraient inclure une caractéristique similaire, s'il y avait une manière idiomatique efficace de construire un tableau en construisant tous les éléments et à ne pas rendre l'objet de réseau lui-même disponible avant que la construction soit terminée. Notez qu'il devrait probablement également être un moyen de spécifier une fonction de nettoyage à appeler sur tous les éléments de construction précédemment si une exception se produit avant que tous les éléments aient été construits.

Enfin, il serait utile que l'on puisse spécifier que certains membres d'instance devraient être invoqués avec des appels non virtuels et devraient être invoquables même sur des articles nuls. Quelque chose comme string.isnullorempty (somestringvariable) est hideux comparé à somestringvariable.isnullorempty . .


0 commentaires