it-swarm-fr.com

Soyez libéral dans ce que vous acceptez ... ou pas?

[Disclaimer: Cette question est subjective, mais je préférerais obtenir des réponses soutenues par des faits et/ou des réflexions]

Je pense que tout le monde sait sur le principe de robustesse , résumé habituellement par la loi de Postel:

Être conservateur dans ce que vous envoyez; être libéral dans ce que vous acceptez.

Je conviendrais que pour la conception d'un protocole de communication répandu, cela peut avoir du sens (dans le but de permettre une extension facile), mais j'ai toujours pensé que son application à HTML/CSS était une échec total, chaque navigateur mettant en œuvre son propre tweak silencieux Détection/comportement, rendant presque impossible l'obtention d'un rendu cohérent sur plusieurs navigateurs.

Je remarque cependant que le RFC du TCP Protocol estime-t-il que "une défaillance silencieuse" est acceptable, sauf indication contraire ... qui est un comportement intéressant, de dire le moins.

Il existe d'autres exemples de l'application de ce principe dans l'ensemble du commerce des logiciels qui apparaissent régulièrement parce qu'ils ont des développeurs mordants, du haut de la tête:

  • Insertion de semi-colon JavaScript
  • C (silent) builtin conversions (which would not be so bad if it did not truncated...)

et il existe des outils pour aider à mettre en œuvre le comportement "intelligent":

Cependant, je trouve que cette approche, alors qu'elle peut être utile lorsque vous traitez avec des utilisateurs non techniques ou pour aider les utilisateurs dans le processus de récupération des erreurs, a des inconvénients lorsqu'il est appliqué à la conception de l'interface de bibliothèque/classes:

  • il est un peu subjectif si l'algorithme devine "droit", et il peut donc aller contre le principe du moins d'étonnement
  • cela rend la mise en œuvre plus difficile, mais plus de chances d'introduire des bugs (violation de YAGNI ?)
  • il rend le comportement plus susceptible de changer, car toute modification de la routine "Guess" peut casser de vieux programmes, excluant presque les possibilités de refactorisation ... Dès le début!

Et c'est ce qui m'a conduit à la question suivante:

Lors de la conception d'une interface (bibliothèque, classe, message), vous penchez-vous vers le principe de la robustesse ou non?

J'ai moi-même tendance à être assez strict, en utilisant une validation d'entrée étendue sur mes interfaces, et je me demandais si j'étais peut-être trop stricte.

47
Matthieu M.

Je dirais robustesse quand cela n'introduit pas les ambiguïtés.

Par exemple: lors de l'analyse d'une liste séparée par des virgules, il y a ou non un espace avant/après que la virgule ne change pas le sens sémantique.

Lors de l'analyse d'un guide de chaîne, il devrait accepter un nombre quelconque de formats courants (avec ou sans tirets, avec ou sans bretelles frisées environnantes).

La plupart des langages de programmation sont robustes avec l'utilisation de l'espace blanc. Spécifiquement partout où cela n'affecte pas la signification du code. Même dans Python où WhitSpace est pertinent, il est toujours flexible lorsque vous êtes à l'intérieur d'une liste ou d'une déclaration de dictionnaire.

Je suis vraiment d'accord pour dire que si quelque chose peut être interprété de plusieurs manières ou si ce n'est pas clair à 100% ce qui était censé que trop robustesse peut finir par être une douleur, mais il y a beaucoup de place à la robustesse sans être ambiguës.

34
Davy8

Définitivement pas. Les techniques telles que la programmation défensive obscurent des bugs, rendent leur apparence moins probable et plus aléatoire, ce qui rend leur détection plus difficile qui rend leur isolation plus difficile.

Le fichier écrit du code solide Était énorme en soulignant à plusieurs reprises le besoin et les techniques de rendre des bugs aussi difficiles à introduire ou à cacher. Grâce à l'application de ses principes tels que "Éliminer le comportement aléatoire. Forcer des bugs à reproduire." et "cherche toujours et élimine toujours des défauts dans vos interfaces". Les développeurs amélioreront considérablement la qualité de leurs logiciels en éliminant l'ambiguïté et les effets secondaires incontrôlés responsables d'une grande quantité de bugs.

15
Huperniketes

Malheureusement, le "principe de robustesse" ne conduit pas à la robustesse. Prenez l'exemple HTML. Beaucoup de problèmes, de larmes, de gaspillage de temps et d'énergie auraient pu être évités si les navigateurs avaient strictement analysé HTML du début au lieu d'essayer de deviner la signification du contenu mal formé.

Le navigateur doit simplement avoir affiché un message d'erreur au lieu d'essayer de le réparer sous les couvertures. Cela aurait forcé tous les bunglers à réparer leur désordre.

9
ThomasX

Je divise les interfaces en plusieurs groupes (ajoutez plus si vous aimez):

  1. ceux qui sont sous votre contrôle devraient être stricts (classes typiquement)
  2. aPI de bibliothèque, qui devrait être aussi strict, mais une validation supplémentaire est conseillée.
  3. interfaces publiques qui doivent gérer chaque type d'abus qui se concrétise (typiquement protocoles, entrées utilisateur, etc.). Ici, la robustesse de l'entrée est réellement payée, vous ne pouvez pas vous attendre à ce que tout le monde va réparer leurs affaires. Et rappelez-vous pour l'utilisateur, ce sera votre faute si l'application ne fonctionne pas, pas la partie qui a envoyé une merde mal formatée.

La sortie doit toujours être stricte.

6
MaR

Je pense que le HTML et le World Wide Web ont fourni un test de la robustesse à grande échelle du principe de la robustesse et lui ont montré qu'il s'agissait d'une défaillance massive. Il est directement responsable du gâchis déroutant de la concurrence de HTML Près des normes qui rend la vie misérable pour les développeurs Web (et leurs utilisateurs) et s'aggrave avec chaque nouvelle version de l'explorateur Internet.

Nous avons connu depuis les années 1950 comment valider le code correctement. Exécutez-le à travers un analyseur strict et si quelque chose ne correspond pas syntaxiquement correct, lancez une erreur et avortez. Ne passez pas aller, ne collectez pas 200 $ et pour l'amour de tout ce qui est binaire Ne laissez pas le programme informatique tenter de lire l'esprit du codeur s'il a commis une erreur!

HTML et JavaScript nous ont montré exactement ce qui se passe lorsque ces principes sont ignorés. Le meilleur plan d'action est d'apprendre de leurs erreurs et de ne pas les répéter.

5
Mason Wheeler

En tant que contrepoint à l'exemple de Mason, mon expérience avec le Protocole d'initiation de la session était que, alors que différentes piles interprètent les RFC pertinents différemment (et je soupçonne que cela se produit avec chaque Norme jamais écrite), étant (modérément) libérale dans ce que vous acceptez signifie que vous pouvez réellement effectuer des appels entre deux périphériques. Étant donné que ces dispositifs sont des éléments physiques habituels par opposition aux logiciels sur un bureau, vous devez simplement être libéral dans ce que vous acceptez, ou votre téléphone ne peut pas appeler un autre téléphone d'une marque particulière. Cela ne fait pas que votre téléphone soit bon!

Mais si vous écrivez une bibliothèque, vous n'avez probablement pas le problème de plusieurs parties interpréter une norme commune de manière mutuellement incompatible. Dans ce cas, je dirais que je serais strict dans ce que vous acceptez, car il élimine les ambiguïtés.

Le fichier de jargon a également une Horror Story sur "Devinez" l'intention d'un utilisateur.

3
Frank Shearar

Vous avez raison, la règle s'applique aux protocoles et non à la programmation. Si vous créez une faute de frappe pendant la programmation, vous obtiendrez une erreur dès que vous compilez (ou exécutez-le si vous êtes l'un de ces types dynamiques). Il n'y a rien à gagner en laissant l'ordinateur deviner pour vous. Contrairement aux gens communs, nous sommes des ingénieurs et capables de dire exactement ce que je veux dire. ;)

Donc, lors de la conception d'une API, je dirais Ne pas Suivez le principe de la robustesse. Si le développeur fait une erreur, ils devraient en savoir tout de suite. Bien sûr, si votre API utilise des données d'une source extérieure, comme un fichier, vous devez être indulgent. L'utilisateur de votre bibliothèque devrait connaître ses propres erreurs, mais pas de personne d'autre.

En côté, je devinerais que "l'échec silencieux" est autorisé dans le protocole TCP, car sinon, si les gens lancent des paquets malformés à vous, vous seriez bombardé avec des messages d'erreur. C'est une simple protection DOS juste là.

Ne manquez jamais silencieusement . En dehors de cela, essayant de deviner ce que l'utilisateur d'une API/bibliothèque voulait, ne sonne pas comme une mauvaise idée. Je ne le suivrais pas cependant; Avoir une exigence stricte, peut exposer des bugs dans le code d'appel et/ou des interprétations erronées sur votre API/votre bibliothèque.

En outre, comme cela a déjà été souligné, cela dépend de la difficulté de deviner ce que l'utilisateur attendait. Si c'est très facile, vous avez deux cas:

  1. Votre bibliothèque doit être conçue un peu différemment (renommer une certaine fonction ou diviser en deux) afin que l'utilisateur puisse s'attendre à ce que vous fournissez réellement.
  2. Si vous croyez que votre bibliothèque est conçue correctement, ce qui signifie une nommaison claire/directe, vous pouvez alors essayer d'inférer ce que l'utilisateur a voulu.

En tout état de cause, il n'est pas 100% évident et déterministe, qu'une entrée doit être convertie en une autre, vous ne devez pas faire les conversions, pour un certain nombre de raisons déjà mentionnées (compatibilité de la compatibilité de refactoring, moins l'étonnement des utilisateurs).

Lorsque vous traitez avec un utilisateur final, essayez de réparer leur entrée/devinette est la bienvenue. Il est attendu d'entrer des informations non valides; Ce cas est totalement exceptionnel. Un autre développeur n'est cependant pas un simple utilisateur non technique. Il a l'expertise pour comprendre une erreur et l'erreur peut avoir une signification/être bénéfique pour lui. Ainsi, je suis d'accord avec vous pour concevoir des API strictes, tandis que - de la stricté de cours est accompagnée d'une clarté et d'une simplicité.

Je vous recommanderais de lire - cette question de mienne , d'un cas similaire.

1
Reinstate Monica

OMI, robustesse est un côté d'un compromis conception pas un principe de " préférer ". Comme beaucoup l'ont souligné, pue rien comme quatre heures soufflant à essayer de comprendre où votre JS a mal tourné pour découvrir le vrai problème était qu'un seul navigateur a fait la bonne chose avec XHTML Strict. Il a laissé la page s'évanouir quand une partie du code HTML servi était un désastre complet.

D'autre part, qui veut consulter la documentation d'une méthode qui prend 20 arguments et insiste sur le fait qu'ils soient dans le même ordre exact avec les détenteurs valeur vide ou nulle place pour ceux que vous voulez sauter? La façon robuste tout aussi terrible pour faire face à cette méthode serait de vérifier tous les arg et essayer de deviner qui était pour ce en fonction des positions relatives et les types, puis échouer en mode silencieux ou essayer de " faire avec " args vides de sens.

Ou vous pouvez faire cuire la flexibilité dans le processus en faisant passer un littéral d'objet/dictionnaire/valeur clé liste paire et gérer l'existence de chaque arg que vous obtenez à elle. Pour le compromis entre perf très mineur, c'est un gâteau et le manger trop scénario.

Args de manière Surcharge intelligente et cohérente interface est une façon intelligente d'être robuste sur les choses. Ainsi, la redondance est la cuisson dans un système où il est supposé la livraison de paquets sera régulièrement ne pas être livré dans un réseau compliqué massivement détenu et géré par tout le monde dans un domaine émergent de la technologie avec une grande variété de moyens potentiels de transmission.

Tolérer abject échec, cependant, en particulier dans un système que vous contrôlez, n'est jamais un bon compromis entre. Par exemple, je devais prendre une pause pour éviter de jeter un ajustement sifflants dans une autre question de mettre JS en haut ou en bas de la page. Plusieurs personnes ont insisté sur le fait qu'il était préférable de mettre JS en haut car alors si la page n'a pas pu charger complètement, vous auriez encore potentiellement avoir une certaine fonctionnalité. pages demi-travail sont pires que des bustes complets. Au mieux, ils entraînent plus de visiteurs sur votre site, vous en supposant raison êtes la incompétente avant de savoir à ce sujet que si la page Busted up est tout simplement rebondi sur une page d'erreur lors de l'échec de son propre contrôle de validation suivi d'un e-mail automatisé quelqu'un qui peut faire quelque chose à ce sujet. Vous sentiriez à l'aise remise vos informations de carte de crédit sur un site qui était à moitié cassé tout le temps?

Toute tentative de fournir des fonctionnalités 2010 sur un navigateur 1999, vous pouvez simplement fournir une page de faible technologie est un autre exemple d'un compromis entre design téméraires. Les possibilités soufflés et l'argent que j'ai vu perdu le temps de développement consacré à des solutions de contournement punaisés juste pour obtenir des coins arrondis sur un vol stationnaire au-dessus d'un élément! @ # $ Ing fond dégradé par exemple, me ont complètement époustouflé. Et pour quoi? Pour fournir des pages de technologie supérieure qui exécutent mal à technophobes éprouvées tout en vous limitant les choix sur les navigateurs haut de gamme.

Pour que ce soit le bon choix, le choix à l'entrée de la poignée d'une manière robuste doit toujours rendre la vie plus facile des deux côtés du problème, à court et à long terme de l'OMI.

1
Erik Reppen