(Je doute que ce message ait beaucoup de visibilité vu mon temps de découverte de l'article original, mais voici tout de même quelques remarques).
De la programmation par contrat
Tout d'abord, la Programmation par Contrat est totalement méprise—ou très mal présentée. Son objectif n'est pas de gérer des problèmes plausibles et liés à l'environnement tel qu'un fichier illisible, corrompu, ou encore des sockets plantées.
Son objectif est de traiter les erreurs de programmation. C'est pour cela que l'on dit que c'est à l'utilisateur de vérifier le contrat d'appel (pré-conditions avant d'appeler la fonction). Appeler pop() sur une pile vide est idiot. De même que d'accéder à un élément hors bornes, ou d'exécuter sqrt(sin(x)-1) sur tout x. Ce sont autant d'erreurs dont la prévention est de la responsabilité de l'appelant.
Je n'apprécie pas cette méthode car elle est source de nombreux bugs difficiles à trouver.
A ce sujet, je préfère 100 fois une assertion là pour détecter une précondition non remplie qu'une exception pour analyser ce qu'il se passe. En terme d'investigation, c'est un vrai bonheur à contrario de toutes les alternatives dynamiques (pour repérer et tordre le coup aux erreurs de programmation en C&C++, donc). Je suis d'accord accessoirement sur le fait que les types opaques c'est encore plus mieux. Mais cela complexifie les choses car un strictlypositive<> * strictlynegative<> donne un strictlynegative<>, mais quid de l'addition ? (Ou alors, il faut faire comme avec boost.unit et avoir une arithmétique sur des range<min, max>. Hum... C'est tordu, mais ça peu m'amuser à investiguer.)
Il y a effectivement peu d'endroits où la SL choisit de lancer des std::logic_error, qui sont des exceptions qui signifient "erreur de programmation". En général, une approche pure contrat, mais pas toujours instrumentée est employée. Cf les "STL checkées" sur le sujet. Et j'espère qu'après le C++17 si les évolutions sur les contrats sont validées, toute la SL sera annotée pour spécifier les contrats de toutes les fonctions qui en ont.
De mon avis, std::vector<>::at() est une hérésie qui n'aurait jamais du exister.
Ailleurs, s'il y a des choses qui peuvent vraiment échouer, des exceptions de runtime (dans la terminologie C++, je sais que runtime error veut dire le contraire dans d'autres langages) seront lancées—d'autres exemples ont été donnés. J'ai envie de dire que quelque part, c'est plus nos métiers qui vont vraiment détecter des situations exceptionnelles (et plausibles) et à ne pas confondre avec des erreurs de programmation.
A propos d'optional et des erreurs
Si dans le contexte d'une fonction de recherche, un retour optionnel (qui ne signifie pas forcément "erreur") a du sens, dans le contexte de retour d'erreurs de runtime (au sens C++ donc), optional n'est pas un bon outil car il ne porte en lui aucun contexte. Et tu nous montres ici à quel point les enchainements ne sont pas propres/simples.
# Remarques diverses et ... tardives
Posté par lmg HS (site web personnel) . En réponse au journal Gestion de l'erreur - C++ - std::optional. Évalué à 2.
(Je doute que ce message ait beaucoup de visibilité vu mon temps de découverte de l'article original, mais voici tout de même quelques remarques).
De la programmation par contrat
Tout d'abord, la Programmation par Contrat est totalement méprise—ou très mal présentée. Son objectif n'est pas de gérer des problèmes plausibles et liés à l'environnement tel qu'un fichier illisible, corrompu, ou encore des sockets plantées.
Son objectif est de traiter les erreurs de programmation. C'est pour cela que l'on dit que c'est à l'utilisateur de vérifier le contrat d'appel (pré-conditions avant d'appeler la fonction). Appeler
pop()sur une pile vide est idiot. De même que d'accéder à un élément hors bornes, ou d'exécutersqrt(sin(x)-1)sur tout x. Ce sont autant d'erreurs dont la prévention est de la responsabilité de l'appelant.A ce sujet, je préfère 100 fois une assertion là pour détecter une précondition non remplie qu'une exception pour analyser ce qu'il se passe. En terme d'investigation, c'est un vrai bonheur à contrario de toutes les alternatives dynamiques (pour repérer et tordre le coup aux erreurs de programmation en C&C++, donc). Je suis d'accord accessoirement sur le fait que les types opaques c'est encore plus mieux. Mais cela complexifie les choses car un
strictlypositive<> * strictlynegative<>donne unstrictlynegative<>, mais quid de l'addition ? (Ou alors, il faut faire comme avec boost.unit et avoir une arithmétique sur desrange<min, max>. Hum... C'est tordu, mais ça peu m'amuser à investiguer.)Bref, je me suis déjà longuement étendu sur le sujet par ici: http://luchermitte.github.io/blog/2014/05/24/programmation-par-contrat-un-peu-de-theorie/ (série de 3 billets)
Des exceptions dans la SL
Il y a effectivement peu d'endroits où la SL choisit de lancer des
std::logic_error, qui sont des exceptions qui signifient "erreur de programmation". En général, une approche pure contrat, mais pas toujours instrumentée est employée. Cf les "STL checkées" sur le sujet. Et j'espère qu'après le C++17 si les évolutions sur les contrats sont validées, toute la SL sera annotée pour spécifier les contrats de toutes les fonctions qui en ont.De mon avis,
std::vector<>::at()est une hérésie qui n'aurait jamais du exister.Ailleurs, s'il y a des choses qui peuvent vraiment échouer, des exceptions de runtime (dans la terminologie C++, je sais que runtime error veut dire le contraire dans d'autres langages) seront lancées—d'autres exemples ont été donnés. J'ai envie de dire que quelque part, c'est plus nos métiers qui vont vraiment détecter des situations exceptionnelles (et plausibles) et à ne pas confondre avec des erreurs de programmation.
A propos d'
optionalet des erreursSi dans le contexte d'une fonction de recherche, un retour optionnel (qui ne signifie pas forcément "erreur") a du sens, dans le contexte de retour d'erreurs de runtime (au sens C++ donc),
optionaln'est pas un bon outil car il ne porte en lui aucun contexte. Et tu nous montres ici à quel point les enchainements ne sont pas propres/simples.Je vous invite plutôt à vous tourner vers des types comme
expected. Il y a eu un article sur le sujet en 2012 et de l'encre électronique a coulé (pour encore plus de monadification de la bête) après ça :- la vidéo de la conf: http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C
- les slides: https://onedrive.live.com/?cid=F1B8FF18A2AEC5C5&id=F1B8FF18A2AEC5C5%211158&parId=root&o=OneUp
Pour le coup, c'est fait pour. Et c'est plus proche du genre de type que cet article recherche.