null
L'utilisation dépend de l'application / de la langue
En fin de compte, le choix d'utiliser ou non null
comme valeur d'application valide est largement déterminé par votre application et votre langage de programmation / interface / périphérie.
À un niveau fondamental, je recommanderais d'essayer d'utiliser des types distincts s'il existe des classes de valeurs distinctes. null
peut être une option si votre interface le permet et qu'il n'y a que deux classes d'une propriété que vous essayez de représenter. L'omission d'une propriété peut être une option si votre interface ou votre format le permet. Un nouveau type d'agrégat (classe, objet, type de message) peut être une autre option.
Pour votre exemple de chaîne, si c'est dans le langage de programmation, je me poserais quelques questions.
- Ai-je l'intention d'ajouter de futurs types de valeurs? Si c'est le cas, un
Option
sera probablement meilleur pour la conception de votre interface.
- Quand dois-je valider les appels des consommateurs? Statiquement? Dynamiquement? Avant? Après? Du tout? Si votre langage de programmation le prend en charge, profitez des avantages de la frappe statique car il évite la quantité de code que vous devez créer pour la validation.
Option
remplit probablement ce cas mieux si votre chaîne n'était pas nullable. Cependant, vous devrez probablement vérifier l'entrée de l'utilisateur pour une null
valeur de chaîne de toute façon, alors je reviendrais probablement à la première ligne de questionnement: combien de types de valeurs je veux / veux-je représenter.
- Est
null
indicative d'une erreur de programmation dans mon langage de programmation? Malheureusement, il null
s'agit souvent de la valeur par défaut pour les pointeurs ou références non initialisés (ou initialisés de manière non explicite) dans certaines langues. La null
valeur par défaut est-elle acceptable? Est-ce sûr comme valeur par défaut? Parfois, cela null
indique des valeurs désallouées. Dois-je fournir aux consommateurs de mon interface une indication de ces problèmes potentiels de gestion de la mémoire ou d'initialisation dans leur programme? Quel est le mode d'échec d'un tel appel face à de tels problèmes? L'appelant est-il dans le même processus ou thread que le mien afin que de telles erreurs soient un risque élevé pour mon application?
En fonction de vos réponses à ces questions, vous pourrez probablement déterminer si cela convient ou non null
à votre interface.
Exemple 1
- Votre application est essentielle à la sécurité
- Vous utilisez un certain type d'initialisation de segment de mémoire au démarrage et
null
est une valeur de chaîne possible renvoyée en cas d'échec d'allocation d'espace pour une chaîne.
- Il y a un potentiel qu'une telle chaîne frappe votre interface
Réponse: null
n'est probablement pas approprié
Justification: null
dans ce cas, est en fait utilisé pour indiquer deux types de valeurs différents. La première peut être une valeur par défaut que l'utilisateur de votre interface peut vouloir définir. Malheureusement, la deuxième valeur est un indicateur pour indiquer que votre système ne fonctionne pas correctement. Dans de tels cas, vous souhaitez probablement échouer de la manière la plus sûre possible (quoi que cela signifie pour votre système).
Exemple 2
- Vous utilisez une structure C qui a un
char *
membre.
- Votre système n'utilise pas d'allocation de segment et vous utilisez la vérification MISRA.
- Votre interface accepte cette structure comme pointeur et vérifie que la structure ne pointe pas vers
NULL
- La valeur par défaut et sûre du
char *
membre de votre API peut être indiquée par une seule valeur deNULL
- Lors de l'initialisation de la structure de votre utilisateur, vous souhaitez donner à l'utilisateur la possibilité de ne pas initialiser explicitement le
char *
membre.
Réponse: NULL
peut être approprié
Justification: Il y a un peu de chance que votre structure passe le NULL
contrôle mais n'est pas initialisée. Cependant, votre API peut ne pas être en mesure de tenir compte de cela, sauf si vous avez une sorte de somme de contrôle sur la valeur de la structure et / ou la vérification de la plage de l'adresse de la structure. Les linters MISRA-C peuvent aider les utilisateurs de votre API en signalant l'utilisation des structures avant leur initialisation. Cependant, comme pour le char *
membre, si le pointeur vers struct pointe vers une structure initialisée, NULL
est la valeur par défaut d'un membre non spécifié dans un initialiseur de structure. Par conséquent, NULL
peut servir de valeur par défaut sûre pour le char *
membre struct dans votre application.
Si c'est sur une interface de sérialisation, je me poserais les questions suivantes pour savoir si oui ou non utiliser null sur une chaîne.
- Est
null
indicative d'une erreur côté client potentiel? Pour JSON en JavaScript, il s'agit probablement d'un non car il null
n'est pas nécessairement utilisé comme indication d'un échec d'allocation. En JavaScript, il est utilisé comme une indication explicite de l'absence d'objet d'une référence à définir de manière problématique. Cependant, il existe des analyseurs et des sérialiseurs non javascript qui mappent JSON null
au null
type natif . Si tel est le cas, cela amène à discuter de la question de savoir si l' null
utilisation native est acceptable pour votre combinaison particulière de langue, analyseur et sérialiseur.
- L'absence explicite d'une valeur de propriété affecte-t-elle plus qu'une seule valeur de propriété? Parfois, un
null
indique en fait que vous avez un nouveau type de message entièrement. Il peut être plus simple pour vos consommateurs du format de sérialisation de simplement spécifier un type de message complètement différent. Cela garantit que leur validation et leur logique d'application peuvent avoir une séparation nette entre les deux distinctions de messages fournies par votre interface Web.
Conseils généraux
null
ne peut pas être une valeur sur un bord ou une interface qui ne la prend pas en charge. Si vous utilisez quelque chose qui est extrêmement lâche dans la nature de la saisie de valeurs de propriétés (c'est-à-dire JSON), essayez de pousser une certaine forme de schéma ou de validation sur le logiciel de pointe des consommateurs (par exemple JSON Schema ) si vous le pouvez. S'il s'agit d'une API de langage de programmation, validez l'entrée utilisateur si possible statiquement (via la saisie) ou aussi fort que cela est sensé lors de l'exécution (alias pratiquez la programmation défensive sur les interfaces destinées aux consommateurs). Tout aussi important, documentez ou définissez le bord afin qu'il ne soit pas question de:
- Quel (s) type (s) de valeur une propriété donnée accepte
- Quelles plages de valeurs sont valides pour une propriété donnée.
- Comment un type d'agrégat doit être structuré. Quelles propriétés doivent / devraient / peuvent être présentes dans un type d'agrégat?
- S'il s'agit d'un type de conteneur, combien d'éléments le conteneur peut-il ou doit-il contenir, et quels sont les types de valeurs qu'il contient?
- Dans quel ordre, le cas échéant, les propriétés ou instances d'un type de conteneur ou d'agrégats sont-elles renvoyées?
- Quels sont les effets secondaires de la définition de valeurs particulières et quels sont les effets secondaires de la lecture de ces valeurs?