Mein Professor bezieht sich immer wieder auf dieses Java-Beispiel, wenn er von "robustem" Code spricht:
if (var == true) {
...
} else if (var == false) {
...
} else {
...
}
Er behauptet, dass "robuster Code" bedeutet, dass Ihr Programm alle Möglichkeiten berücksichtigt und dass es keinen Fehler gibt - alle Situationen werden vom Code behandelt und führen zu einem gültigen Status, daher das "sonst".
Ich bin jedoch zweifelhaft. Wenn es sich bei der Variablen um einen Booleschen Wert handelt, wozu dient die Überprüfung eines dritten Zustands, wenn ein dritter Zustand logisch unmöglich ist?
"Einen Fehler nicht zu haben" scheint ebenfalls lächerlich; Sogar Google-Anwendungen zeigen dem Benutzer Fehler direkt an, anstatt sie unbemerkt zu verschlucken oder sie als gültigen Status zu betrachten. Und es ist gut - ich mag es zu wissen, wenn etwas schief geht. Und es scheint durchaus die Behauptung zu sein, dass eine Anwendung niemals Fehler enthalten würde.
Was ist nun die eigentliche Definition von "robustem Code"?
quelle
Antworten:
Was ist
Boolean?
mit einemNULL
Zustand, der weder wahr noch falsch ist ? Was soll die Software nun tun? Manche Software muss hochgradig absturzsicher sein, beispielsweise Herzschrittmacher. Haben Sie schon einmal jemanden gesehen, der einer Datenbank eine Spalte hinzufügte, in derBoolean
die aktuellen Daten initialisiert wurdenNULL
? Ich weiß, ich habe es gesehen.Hier sind einige Links, die erläutern, was es bedeutet, in Bezug auf Software robust zu sein:
Wenn Sie denken, dass es hier eine allgemein anerkannte Definition von "robust" gibt, dann viel Glück. Es kann einige Synonyme wie bombensicher oder idiotensicher geben. Der Duct Tape Programmer wäre ein Beispiel für jemanden, der normalerweise robusten Code schreibt, zumindest nach meinem Verständnis der Begriffe.
quelle
Für meine Diskussion kann ein Bool 2 Zustände haben, Wahr oder Falsch. Alles andere entspricht nicht der Programmiersprachenspezifikation. Wenn Ihre Werkzeugkette nicht der Spezifikation entspricht, werden Sie abgespritzt, egal was Sie tun. Wenn ein Entwickler eine Art Bool mit mehr als zwei Zuständen erstellt, ist dies das Letzte, was er jemals in meiner Codebasis tun würde.
Option A.
Option B
Ich behaupte, Option B ist robuster .....
Jeder Trottel kann Ihnen sagen, dass Sie mit unerwarteten Fehlern umgehen sollen. Sie sind in der Regel sehr leicht zu erkennen, wenn Sie an sie denken. Das Beispiel, das Ihr Professor gegeben hat, kann nicht passieren, es ist also ein sehr schlechtes Beispiel.
A ist ohne gewundene Prüfgurte nicht zu testen. Wenn Sie es nicht erstellen können, wie werden Sie es testen? Wenn Sie den Code noch nicht getestet haben, woher wissen Sie, dass er funktioniert? Wenn Sie nicht wissen, dass es funktioniert, schreiben Sie keine robuste Software. Ich denke, sie nennen das immer noch einen Catch22 (Großartiger Film, schau ihn dir mal an).
Option B ist trivial zu testen.
Stellen Sie Ihrem Professor als nächstes die Frage: "Was soll ich dagegen tun, wenn ein Boolescher Wert weder Wahr noch Falsch ist?" Das sollte zu einer sehr interessanten Diskussion führen .....
In den meisten Fällen ist ein Core-Dump angemessen, im schlimmsten Fall stört er den Benutzer oder kostet viel Geld. Was ist, wenn das Modul beispielsweise das Echtzeit-Wiedereintrittsberechnungssystem des Space Shuttles ist? Jede noch so ungenaue Antwort kann nicht schlimmer sein als ein Abbruch, der die Benutzer tötet. Was tun, wenn Sie wissen, dass die Antwort möglicherweise falsch ist? Entscheiden Sie sich für 50/50 oder brechen Sie ab und versuchen Sie es mit einem 100% igen Fehler. Wenn ich ein Besatzungsmitglied wäre, würde ich die 50/50 nehmen.
Option A tötet mich Option B gibt mir eine gleichmäßige Überlebenschance.
Aber warten Sie - es ist eine Simulation des Space-Shuttle-Wiedereintritts - was dann? Abbrechen, damit Sie davon erfahren. Hört sich nach einer guten Idee an? - NICHT - weil Sie mit dem Code testen müssen, den Sie versenden möchten.
Option A ist für die Simulation besser, kann jedoch nicht bereitgestellt werden. Es ist nutzlos, dass Option B der bereitgestellte Code ist, sodass die Simulation dieselbe Leistung erbringt wie die Live-Systeme.
Angenommen, dies war ein berechtigtes Anliegen. Die bessere Lösung wäre, die Fehlerbehandlung von der Anwendungslogik zu isolieren.
Weitere Informationen - Therac-25-Röntgengerät, Ariane-5-Raketen-Fehler und andere (Link enthält viele defekte Links, aber genügend Informationen, die Google helfen wird)
quelle
if (var != true || var != false) {
ein sein&&
sollte.Tatsächlich ist Ihr Code nicht robuster, aber WENIGER robust. Das Finale
else
ist einfach toter Code, den Sie nicht testen können.In kritischer Software wie in Raumfahrzeugen ist toter Code und im Allgemeinen nicht getesteter Code verboten: Wenn ein kosmischer Strahl eine einzige Ereignisstörung hervorruft, die wiederum dazu führt, dass Ihr toter Code aktiviert wird, ist alles möglich. Wenn die SEU einen Teil des robusten Codes aktiviert, bleibt das (unerwartete) Verhalten unter Kontrolle.
quelle
Ich denke, der Professor könnte "Fehler" und "Fehler" verwechseln. Robuster Code sollte auf jeden Fall wenige / keine Fehler enthalten. Robuster Code kann und muss in einer feindlichen Umgebung ein gutes Fehlermanagement aufweisen (sei es Ausnahmebehandlung oder strenge Rückgabestatus-Tests).
Ich stimme zu, dass das Codebeispiel des Professors albern ist, aber nicht so albern wie meins.
quelle
boolean x = something(); if (x) { x = True // make sure it's really true, ... }
Es gibt keine vereinbarte Definition von Robust Code , da diese für viele Programmieraufgaben mehr oder weniger subjektiv ist ...
Das Beispiel, das Ihr Professor gibt, hängt von der Sprache ab:
Boolean
kann a entweder seinTrue
oderFalse
es gibt keine dritte Optionbool
sein kanntrue
,false
oder (leider) kommen aus irgendwelchen dubiosen Besetzung , die es in einem unbekannten Fall setzen ... Das sollte nicht passieren, kann aber als Folge eines vorangegangenen Fehlers.Was Ihr Professor jedoch empfiehlt, verdeckt den Code, indem er in der Mitte des Kernprogramms eine fremde Logik für Ereignisse einführt, die nicht auftreten sollten , und ich werde Sie stattdessen auf die defensive Programmierung hinweisen .
Im Falle einer Universität können Sie diese sogar erweitern, indem Sie eine Design By Contract-Strategie anwenden:
size
Anzahl der Elemente in derdata
Liste)a
wenn sie kleiner als ist10
).Beispiel:
quelle
Der Ansatz Ihres Professors ist völlig falsch.
Eine Funktion oder nur ein Stück Code sollte eine Spezifikation haben, die besagt, was sie tut, und die jede mögliche Eingabe abdecken sollte. Und der Code sollte so geschrieben sein, dass sein Verhalten garantiert der Spezifikation entspricht. In dem Beispiel würde ich die Spezifikation ganz einfach so schreiben:
Dann schreiben Sie die Funktion:
und der Code entspricht der Spezifikation. Ihr Professor sagt also: Was ist, wenn var == 42? Schauen Sie sich die Spezifikation an: Sie besagt, dass die Funktion "das" tun soll. Schauen Sie sich den Code an: Die Funktion macht "das". Die Funktion entspricht der Spezifikation.
Wo der Code Ihres Professors die Dinge völlig unrobust macht, ist die Tatsache, dass bei seinem Ansatz, wenn var weder wahr noch falsch ist, Code ausgeführt wird, der noch nie zuvor aufgerufen wurde und der völlig ungetestet ist, mit absolut unvorhersehbaren Ergebnissen.
quelle
Ich stimme der Aussage von @ gnasher729 zu: Der Ansatz Ihres Professors ist völlig falsch.
Robust bedeutet, dass es bruch- und ausfallsicher ist, da es nur wenige Voraussetzungen erfüllt und entkoppelt ist: Es ist eigenständig, selbsterklärend und tragbar. Dazu gehört auch die Anpassung an sich ändernde Anforderungen. Kurz gesagt, Ihr Code ist dauerhaft .
Dies führt im Allgemeinen zu kurzen Funktionen, die ihre Daten aus vom Aufrufer übergebenen Parametern beziehen, und zur Verwendung öffentlicher Schnittstellen für Verbraucher - abstrakte Methoden, Wrapper, Indirektion, Schnittstellen im COM-Stil usw. - anstelle von Funktionen, die konkreten Implementierungscode enthalten.
quelle
Robuster Code ist einfach Code, der Fehler gut handhabt. Nicht mehr und nicht weniger.
Es gibt viele Arten von Fehlern: falscher Code, unvollständiger Code, unerwartete Werte, unerwartete Zustände, Ausnahmen, Ressourcenerschöpfung, ... Robuster Code verarbeitet diese Probleme gut.
quelle
Ich würde den von Ihnen angegebenen Code als Beispiel für defensive Programmierung betrachten (zumindest, wenn ich den Begriff verwende). Ein Teil der defensiven Programmierung besteht darin, Entscheidungen zu treffen, die Annahmen über das Verhalten des restlichen Systems minimieren. Welche davon ist zum Beispiel besser:
Oder:
(Falls Sie den Unterschied nicht erkennen können, überprüfen Sie den Schleifentest: die erste Verwendung
!=
, die zweite Verwendung<
).In den meisten Fällen verhalten sich die beiden Schleifen jetzt genau gleich. Beim ersten (Vergleich mit
!=
) wird jedoch eine Annahme getroffen,i
die nur einmal pro Iteration inkrementiert wird. Wenn der Wert übersprungen wird, kannsequence.length()
die Schleife über die Grenzen der Sequenz hinaus fortgesetzt werden und einen Fehler verursachen.Sie können daher argumentieren, dass die zweite Implementierung robuster ist: Sie hängt nicht von Annahmen darüber ab, ob sich der Schleifenkörper ändert
i
(Anmerkung: Tatsächlich wird immer noch die Annahme getroffen, dass diesi
niemals negativ ist).Stellen Sie sich vor, die Schleife scannt eine Zeichenfolge und führt eine Textverarbeitung durch, um eine Begründung dafür zu geben, warum Sie diese Annahme möglicherweise nicht treffen möchten. Sie schreiben die Schleife und alles ist in Ordnung. Jetzt ändern sich Ihre Anforderungen und Sie entscheiden, dass Sie Escape-Zeichen in der Textzeichenfolge unterstützen müssen. Ändern Sie daher den Schleifenkörper so, dass bei Erkennung eines Escape-Zeichens (z. B. Backslash)
i
das Zeichen unmittelbar nach dem Escape-Zeichen inkrementell übersprungen wird. Jetzt hat die erste Schleife einen Fehler, da der Schleifenkörper inkrementiert wirdi
und die Schleife über das Ende der Sequenz hinaus fortgesetzt wird, wenn das letzte Zeichen des Texts ein Backslash ist .quelle
Ich persönlich beschreibe einen Code als "robust", der folgende wichtige Attribute hat:
Mit break meine ich, entweder das System in einen instabilen Zustand zu versetzen oder eine UNHANDLED- Ausnahme auszulösen . Sie wissen, manchmal können Sie für ein einfaches Konzept eine komplexe Definition und Erklärung abgeben. Aber ich würde einfache Definitionen bevorzugen. Benutzer sind ziemlich gut darin, robuste Anwendungen zu finden. Wenn der Benutzer Ihrer Anwendung Ihnen viele Anfragen zu Fehlern, zu Statusverlusten, zu nicht intuitiven Workflows usw. sendet, liegt ein Fehler in Ihrer Programmierung vor.
quelle