Dites que j'ai deux fonctions essentiellement identiques, où l'on valide ses arguments tandis que l'autre ne le fait pas. La justification: Parfois, vous voulez être en sécurité et que vous voulez parfois aller vite.
Quelle est votre convention de dénomination préférée pour distinguer les deux? Par exemple:
list_err_t list_Push_a(list_t *ref, list_t *item) {
if ((ref != NULL) && (item != NULL)) {
list_Push_b(ref, item);
return LIST_ERR_NONE;
} else {
return LIST_ERR_BAD_ARG;
}
}
void list_Push_b(list_t *ref, list_t *item) {
item->next = ref->next;
ref->next = item;
}
Que voudriez-vous nommer list_Push_a
et list_Push_b
? Je pense list_Push_safe
et list_Push_fast
est un peu verbal - l'un d'entre eux devrait juste être list_Push
. (Et note que je suis non Demander à propos de Camelcase vs Snake_Cêche, etc.)
Il y a déjà eu de bonnes réponses déjà. J'aurais dû mentionner à l'avance que l'environnement de programmation en question est des dispositifs intégrés de faible taux, où la vitesse est importante et que les ressources sont pestées. Par exemple, élever des exceptions n'est pas une option ...
Il y a deux possibilités: l'une est que la vitesse de ce code n'a aucune importance. L'avez-vous mesuré? Sinon, aucune importance. Utilisez le code de sécurité. Deux sont que la vitesse est importante, dans ce cas, prenez la fonction sûre et la déclarer comme "en ligne" ou "statique". Évidemment pas appeler la fonction "rapide" mais l'incorporant. Et vous vérifieriez votre documentation de compilateur s'il existe un moyen d'indiquer quel résultat est attendu, par exemple, si vous vous attendez à ce que, dans 99% de tous les cas, les deux pointeurs ne soient pas nuls.
Une autre possibilité est que l'appelant la fonction avec un pointeur NULL est un bug grave. Dans ce cas, l'appelant est peu probable que le code vérifie la valeur de retour et que vous feriez mieux d'utiliser ASSERT ou similaire à vérifier que les pointeurs ne sont pas nuls. Et si vous trouvez qu'ils sont, corrigez l'appelant.
D'autre part, vous n'avez peut-être même pas besoin d'affirmation car votre programme s'écrasera/tombera dans le débogueur si l'un des indicateurs est null.
Si possible, vous pouvez séparer l'activité réelle et les chèques en deux composants différents. On enveloppe autour des autres et des composants externes qui souhaitent être toujours en sécurité utilisent l'emballage sécurisé tandis que des composants si profonds dans le système Tous les paramètres sont déjà validés à ce stade, passez à la classe laine intérieure qui contient la mise en œuvre non protégée.
De toute évidence, cela ne fonctionne pas pour tous les cas, mais il serait peut-être intéressant de considérer.
Dans ce cas, l'option "Safe" est toujours dangereuse lorsque vous passez dans des pointeurs à la mémoire invalide. La seule façon de l'avoir sûr est d'appeler la fonction correctement. Ceci est vrai pour les deux options. Surtout pour le code C ou C++, je préférerais avoir l'option décochée comme par défaut que de le faire faire des chèques qui peuvent ou non le rendre plus sûr d'une petite quantité et revendiquer une fausse impression de comportement sans danger d'échec.
Si votre cas d'utilisation pour l'option "Safe" est vraiment ne fonction renvoie un objet ou une null, que je souhaite appuyer directement sur la liste si disponible, je suggère d'ajouter la variante vérifiée comme un cas particulier. Nommez-les après le cas d'utilisation: list_Push_if_not_null()
.
Notez que la valeur de retour au cas où rien n'est ajouté n'est pas une erreur ici. C'est le comportement attendu et réussi en cas de null. Pensez à omettre cette valeur de retour. Si vous souhaitez utiliser cette information pour le flux de contrôle externe à cette fonction, vous pouvez également effectuer un contrôle externe à la fonction.
Vérification si le premier paramètre est NULL ne semble pas avoir de sens pour moi ici. Ce n'est pas Java. En C un pointeur non zéro pourrait pointer n'importe où. Vous devriez plutôt ajouter une suite de test au code client pour vous assurer d'appeler la fonction avec un objet réel du type requis. En tant qu'auteur de bibliothèque, vous voudrez peut-être ajouter une documentation et un code d'exemple.
Envisagez également d'ajouter un type différent pour les éléments de la liste. Pour votre propre santé mentale. Et notez que les noms se terminant par _t
sont réservés par la norme POSIX. Donc, s'il s'agit de votre code actuel, vous voudrez peut-être renommer vos types.