[Haftungsausschluss: Diese Frage ist subjektiv, aber ich würde es vorziehen, Antworten mit Fakten und / oder Überlegungen zu erhalten.]
Ich denke, jeder kennt das Robustheitsprinzip , das normalerweise durch das Postelsche Gesetz zusammengefasst wird:
Seien Sie konservativ in dem, was Sie senden. Sei liberal in dem, was du akzeptierst.
Ich stimme zu, dass dies für die Entwicklung eines weit verbreiteten Kommunikationsprotokolls sinnvoll sein kann (mit dem Ziel, eine einfache Erweiterung zu ermöglichen). Ich war jedoch immer der Meinung, dass die Anwendung auf HTML / CSS völlig fehlgeschlagen ist und jeder Browser seine eigene stille Optimierung implementiert Erkennung / Verhalten, was es nahezu unmöglich macht, ein konsistentes Rendering über mehrere Browser hinweg zu erzielen.
Ich stelle jedoch fest, dass der RFC des TCP-Protokolls "Silent Failure" als akzeptabel erachtet, sofern nicht anders angegeben ... was gelinde gesagt ein interessantes Verhalten ist.
Es gibt andere Beispiele für die Anwendung dieses Prinzips im gesamten Softwarehandel, die regelmäßig auftauchen, weil sie Entwickler von oben in den Kopf gebissen haben:
- Javascript Semikolon einfügen
- C (stille) eingebaute Konvertierungen (was nicht so schlimm wäre, wenn es nicht abgeschnitten würde ...)
und es gibt Tools, die bei der Implementierung von "intelligentem" Verhalten helfen:
- Phonetische Algorithmen zur Namensanpassung ( Doppelmetaphon )
- String-Distanz-Algorithmen ( Levenshtein-Distanz )
Ich bin jedoch der Meinung, dass dieser Ansatz zwar hilfreich sein kann, wenn es um nicht technische Benutzer geht oder wenn es darum geht, Benutzer bei der Fehlerbehebung zu unterstützen, bei der Gestaltung der Benutzeroberfläche für Bibliotheken / Klassen jedoch einige Nachteile aufweist:
- Es ist etwas subjektiv, ob der Algorithmus "richtig" vermutet, und daher kann er gegen das Prinzip des geringsten Erstaunens verstoßen
- es erschwert die Implementierung und erhöht somit die Wahrscheinlichkeit, Fehler einzuführen (Verstoß gegen YAGNI ?)
- es macht das Verhalten anfälliger für Änderungen, da jede Änderung der "Vermutungs" -Routine alte Programme beschädigen kann, was Refactoring-Möglichkeiten fast ausschließt ... von Anfang an!
Und das hat mich zu folgender Frage geführt:
Neigen Sie beim Entwerfen einer Schnittstelle (Bibliothek, Klasse, Nachricht) zum Robustheitsprinzip oder nicht?
Ich selbst neige dazu, ziemlich streng zu sein und eine umfangreiche Eingabevalidierung für meine Schnittstellen zu verwenden, und ich habe mich gefragt, ob ich vielleicht zu streng bin.
Antworten:
Ich würde Robustheit sagen, wenn dadurch keine Mehrdeutigkeiten entstehen .
Beispiel: Wenn Sie eine durch Kommas getrennte Liste analysieren, ändert sich die semantische Bedeutung nicht, wenn vor / nach dem Komma ein Leerzeichen steht.
Beim Parsen einer Zeichenfolgenführung sollte eine beliebige Anzahl der gängigen Formate akzeptiert werden (mit oder ohne Bindestriche, mit oder ohne umgebende geschweifte Klammern).
Die meisten Programmiersprachen sind robust mit Leerraumnutzung. Insbesondere überall dort, wo es keinen Einfluss auf die Bedeutung von Code hat. Sogar in Python, wo Leerzeichen relevant sind, ist es immer noch flexibel, wenn Sie sich in einer Liste oder Wörterbuchdeklaration befinden.
Ich stimme definitiv zu, dass, wenn etwas auf verschiedene Arten interpretiert werden kann oder wenn nicht 100% klar ist, was gemeint ist, zu viel Robustheit ein Schmerz sein kann, aber es gibt viel Raum für Robustheit, ohne mehrdeutig zu sein.
quelle
{"key": "value",}
als gültig zu akzeptieren , der IE dagegen nicht. Ich bin oft auf dieses spezielle Problem gestoßen, bis ich meinen Build-Prozess mit JSlint verbessert habe.Definitiv nicht. Techniken wie das defensive Programmieren verschleiern Fehler, machen ihr Auftreten weniger wahrscheinlich und zufälliger, was die Erkennung erschwert und die Isolierung erschwert.
Das stark unterbewertete Writing Solid Code hat wiederholt die Notwendigkeit und die Techniken hervorgehoben, Fehler so schwierig wie möglich einzuführen oder zu verbergen. Durch Anwendung seiner Prinzipien wie "Eliminiere zufälliges Verhalten. Erzwinge, dass Fehler reproduzierbar sind." und "Achten Sie immer auf Fehler in Ihren Schnittstellen und beseitigen Sie diese." Entwickler werden die Qualität ihrer Software erheblich verbessern, indem sie die Mehrdeutigkeit und die unkontrollierten Nebenwirkungen beseitigen, die für eine große Menge von Fehlern verantwortlich sind.
quelle
Übermäßige Anwendung von Robustness führt dazu, dass Sie erraten, was der Benutzer wollte. Dies ist in Ordnung, bis Sie es falsch verstehen. Es setzt auch den völlig falschen Glauben voraus, dass Ihre Kunden Ihr Vertrauen nicht missbrauchen und zufälliges Kauderwelsch erzeugen, das zufällig funktioniert, das Sie jedoch in Version 2 nicht unterstützen können.
Übermäßige Anwendung von Korrektheit führt dazu, dass Sie Ihren Kunden das Recht verweigern, geringfügige Fehler zu machen. Dies ist in Ordnung, bis sie sich darüber beklagen, dass ihre Produkte mit dem Produkt Ihres Mitbewerbers einwandfrei funktionieren, und Ihnen mitteilen, was Sie mit Ihrem 5.000-Seiten-Standard tun können, der das Wort hat "ENTWURF" ist immer noch mit Kreide auf dem Cover vermerkt, und mindestens drei Experten behaupten, er sei grundlegend fehlerhaft, und 200 ehrlichere Experten geben an, dass sie das nicht vollständig verstehen.
Meine persönliche Lösung war schon immer die Abwertung. Sie unterstützen sie, sagen ihnen aber, dass sie etwas falsch machen, und (wenn möglich) den einfachsten Weg zur Korrektheit. Auf diese Weise haben Sie, wenn Sie die Bug-Funktion 10 Jahre später ausschalten, zumindest die Möglichkeit, anzugeben, dass "wir Sie gewarnt haben, dass dies passieren könnte".
quelle
Leider führt das sogenannte "Robustheitsprinzip" nicht zu Robustheit. Nehmen Sie als Beispiel HTML. Viel Ärger, Tränen, Zeit- und Energieverschwendung hätten vermieden werden können, wenn Browser HTML von Anfang an streng analysiert hätten, anstatt zu versuchen, die Bedeutung von fehlerhaften Inhalten zu erraten.
Der Browser sollte einfach eine Fehlermeldung angezeigt haben, anstatt zu versuchen, sie unter der Decke zu beheben. Das hätte alle Mistkerle gezwungen, ihr Durcheinander zu reparieren.
quelle
Ich teile Interfaces in mehrere Gruppen ein (füge mehr hinzu, wenn du möchtest):
Die Ausgabe muss immer streng sein.
quelle
Ich denke, HTML und das World Wide Web haben das Robustness-Prinzip in der Praxis umfassend getestet und gezeigt, dass es ein schwerwiegender Fehler ist. Es ist direkt verantwortlich für das verwirrende Durcheinander konkurrierender HTML-Fast-Standards, das das Leben der Webentwickler (und ihrer Benutzer) miserabel macht und mit jeder neuen Version von Internet Explorer schlimmer wird.
Wir wissen seit den 1950er Jahren, wie man Code richtig überprüft. Führen Sie es durch einen strengen Parser und wenn etwas syntaktisch nicht korrekt ist, werfen Sie einen Fehler und brechen Sie ab. Gehen Sie nicht vorbei, sammeln Sie keine 200 Dollar und lassen Sie aus Liebe zu allem, was binär ist , kein Computerprogramm versuchen, die Gedanken des Programmierers zu lesen, wenn er einen Fehler gemacht hat!
HTML und JavaScript haben uns genau gezeigt, was passiert, wenn diese Prinzipien ignoriert werden. Die beste Vorgehensweise ist, aus ihren Fehlern zu lernen und sie nicht zu wiederholen.
quelle
Als Kontrapunkt zu Masons Beispiel war meine Erfahrung mit dem Session Initiation Protocol, dass, während verschiedene Stacks die relevanten RFCs unterschiedlich interpretieren würden (und ich vermute, dass dies mit jedem jemals geschriebenen Standard passiert ), (mäßig) liberal in dem ist, was Sie akzeptieren, was Sie bedeuten kann tatsächlich zwischen zwei Geräten telefonieren. Da es sich bei diesen Geräten im Gegensatz zu Softwarekomponenten auf einem Desktop um übliche physische Dinge handelt, müssen Sie einfach liberal sein, was Sie akzeptieren, oder Ihr Telefon kann kein anderes Telefon einer bestimmten Marke anrufen. Das macht dein Handy nicht gut!
Wenn Sie jedoch eine Bibliothek schreiben, haben Sie wahrscheinlich nicht das Problem, dass mehrere Parteien einen gemeinsamen Standard auf inkompatible Weise interpretieren. In diesem Fall würde ich streng sein, was Sie akzeptieren, weil es Unklarheiten beseitigt.
Die Jargon-Datei enthält auch eine Horrorgeschichte über das "Erraten" der Absicht eines Benutzers.
quelle
Sie haben Recht, die Regel gilt für Protokolle und nicht für die Programmierung. Wenn Sie beim Programmieren einen Tippfehler machen, erhalten Sie beim Kompilieren eine Fehlermeldung (oder beim Ausführen, wenn Sie einer dieser dynamischen Typen sind). Es gibt nichts zu gewinnen, wenn man den Computer für Sie raten lässt. Im Gegensatz zu den gewöhnlichen Leuten sind wir Ingenieure und in der Lage, genau das zu sagen, was ich meine. ;)
Wenn ich eine API entwerfe, würde ich sagen, dass ich nicht dem Robustheitsprinzip folge. Wenn der Entwickler einen Fehler macht, sollte er das sofort herausfinden. Wenn Ihre API Daten aus einer externen Quelle wie einer Datei verwendet, sollten Sie natürlich nachsichtig sein. Der Benutzer Ihrer Bibliothek sollte sich über seine / ihre eigenen Fehler informieren, aber nicht über die anderer.
Abgesehen davon würde ich vermuten, dass "Silent Failure" im TCP-Protokoll zulässig ist, da Sie andernfalls mit Fehlermeldungen bombardiert würden, wenn Leute fehlerhafte Pakete auf Sie werfen würden. Genau dort ist das einfacher DoS-Schutz.
quelle
IMO, Robustheit ist eine Seite eines Designkompromisses und kein "bevorzugtes" Prinzip. Wie viele darauf hingewiesen haben, stinkt nichts so sehr, als vier Stunden lang zu blasen, um herauszufinden, wo Ihr JS schief gelaufen ist. Nur ein einziger Browser hat mit XHTML Strict das Richtige getan. Sie hat die Seite in Stücke gerissen, als ein Teil des bereitgestellten HTML-Codes eine völlige Katastrophe war.
Auf der anderen Seite, wer möchte die Dokumentation für eine Methode nachschlagen, die 20 Argumente verwendet und darauf besteht, dass sie genau in derselben Reihenfolge mit leeren oder Null-Wert-Platzhaltern für die, die Sie überspringen möchten, vorliegen? Die ebenso furchtbare robuste Art, mit dieser Methode umzugehen, wäre, jedes Argument zu überprüfen und zu erraten, welches für was war, basierend auf relativen Positionen und Typen und dann stillschweigend zu scheitern oder zu versuchen, mit bedeutungslosen Argumenten "auszukommen".
Oder Sie können Flexibilität in den Prozess einbauen, indem Sie eine Objekt-Literal / Wörterbuch / Schlüssel-Wert-Paar-Liste übergeben und die Existenz jedes Arguments so behandeln, wie Sie es erreichen. Für den ganz kleinen Perfomance-Kompromiss ist das ein Kuchenszenario und es auch zu essen.
Das Überladen von Args auf intelligente und schnittstellenkonsistente Weise ist eine clevere Art, robust gegenüber Dingen zu sein. Das Gleiche gilt für das Backen von Redundanz in ein System, bei dem angenommen wird, dass die Paketzustellung regelmäßig nicht in einem äußerst komplizierten Netzwerk erfolgt, das sich in einem aufstrebenden Technologiefeld mit einer Vielzahl potenzieller Übertragungsmittel im Besitz und von jedem befindet.
Es ist jedoch niemals ein guter Kompromiss, ein böses Versagen zu tolerieren, insbesondere in einem von Ihnen kontrollierten System. Zum Beispiel musste ich eine Verschnaufpause einlegen, um zu vermeiden, dass ich bei einer anderen Frage, ob JS am oberen oder unteren Rand der Seite platziert werden soll, einen zischenden Anfall bekomme. Einige Leute bestanden darauf, dass es besser sei, JS an die Spitze zu setzen, denn wenn die Seite dann nicht vollständig geladen werden könne, hätten Sie möglicherweise noch einige Funktionen. Halbnutzenseiten sind schlimmer als komplette Büsten. Bestenfalls führen sie zu mehr Besuchern Ihrer Website, wenn Sie zu Recht davon ausgehen, dass Sie inkompetent sind, bevor Sie davon erfahren, als wenn die kaputte Seite einfach auf eine Fehlerseite weitergeleitet wird, wenn die eigene Validierungsprüfung fehlschlägt, gefolgt von einer automatisierten E-Mail an jemand, der etwas dagegen tun kann.
Der Versuch, die 2010-Funktionalität in einem 1999-Browser bereitzustellen, wenn Sie nur eine Seite mit niedrigerer Technologie bereitstellen könnten, ist ein weiteres Beispiel für einen tollkühnen Design-Kompromiss. Die Chancen und das Geld, das ich für die Zeit der Entwickler verschwendet habe, die ich für Fehlerumgehungen aufgewendet habe, nur um abgerundete Ecken für ein Element zu erhalten, das zum Beispiel über einem! @ # $ Ing-Hintergrund mit Farbverlauf schwebt, haben mich völlig umgehauen. Und wofür? Bereitstellung von High-Tech-Seiten mit schlechter Leistung für erprobte Technophobiker, wobei Sie die Auswahlmöglichkeiten für High-End-Browser einschränken.
Damit es die richtige Wahl ist, sollte die Wahl, die Eingabe auf robuste Weise zu handhaben, auf beiden Seiten des Problems kurz- und langfristig das Leben erleichtern.
quelle
Versage niemals leise . Abgesehen davon klingt es nicht nach einer schlechten Idee, zu erraten, was der Benutzer einer API / Bibliothek wollte. Ich würde es aber nicht folgen; Eine strenge Anforderung kann Fehler im aufrufenden Code und / oder Fehlinterpretationen Ihrer API / Bibliothek aufdecken.
Darüber hinaus kommt es, wie bereits erwähnt, darauf an, wie schwer es ist, zu erraten, was der Benutzer erwartet. Wenn es sehr einfach ist, haben Sie zwei Fälle:
In jedem Fall, wenn es nicht 100% offensichtlich und deterministisch ist, dass eine Eingabe in eine andere konvertiert werden sollte, sollten Sie die Konvertierungen aus einer Reihe von bereits erwähnten Gründen nicht durchführen (Verstoß gegen die Kompatibilität beim Refactoring, geringstes Erstaunen der Benutzer).
Im Umgang mit einem Endbenutzer ist der Versuch, seine Eingaben / Vermutungen zu korrigieren, sehr willkommen. Es wird erwartet , dass er ungültige Informationen eingibt. Dieser Fall ist völlig unüblich. Ein anderer Entwickler ist jedoch kein einfacher, nicht technischer Benutzer. Er hat das Fachwissen, um einen Fehler zu verstehen, und der Fehler kann für ihn von Bedeutung sein. Daher stimme ich Ihnen beim Entwerfen strenger APIs zu, während Strenge natürlich mit Klarheit und Einfachheit einhergeht.
Ich würde empfehlen, dass Sie diese Frage von mir lesen , von einem ähnlichen Fall.
quelle