Ich habe eine Weile über dieses Problem nachgedacht und wäre gespannt auf Meinungen anderer Entwickler.
Ich neige zu einem sehr defensiven Programmierstil. Mein typischer Block oder meine typische Methode sieht folgendermaßen aus:
T foo(par1, par2, par3, ...)
{
// Check that all parameters are correct, return undefined (null)
// or throw exception if this is not the case.
// Compute and (possibly) return result.
}
Außerdem überprüfe ich während der Berechnung alle Zeiger, bevor ich sie dereferenziere. Meine Idee ist, dass, wenn es einen Fehler gibt und irgendwo ein NULL-Zeiger erscheinen sollte, mein Programm dies gut handhaben und sich einfach weigern sollte, die Berechnung fortzusetzen. Natürlich kann es über das Problem mit einer Fehlermeldung im Protokoll oder einem anderen Mechanismus informieren.
Um es abstrakter auszudrücken, ist mein Ansatz
if all input is OK --> compute result
else --> do not compute result, notify problem
Andere Entwickler, darunter einige meiner Kollegen, verfolgen eine andere Strategie. ZB prüfen sie keine Zeiger. Sie gehen davon aus, dass ein Teil des Codes korrekt eingegeben werden sollte und dass er nicht dafür verantwortlich sein sollte, was passiert, wenn die Eingabe falsch ist. Wenn eine NULL-Zeiger-Ausnahme das Programm zum Absturz bringt, kann ein Fehler beim Testen leichter gefunden werden und es besteht eine höhere Wahrscheinlichkeit, dass er behoben wird.
Meine Antwort darauf lautet normalerweise: Aber was ist, wenn der Fehler beim Testen nicht gefunden wird und angezeigt wird, wenn das Produkt bereits vom Kunden verwendet wird? Was ist ein bevorzugter Weg, damit sich der Fehler manifestiert? Sollte es ein Programm sein, das eine bestimmte Aktion nicht ausführt, aber trotzdem weiterarbeiten kann, oder ein Programm, das abstürzt und neu gestartet werden muss?
Zusammenfassend
Welchen der beiden Ansätze zum Umgang mit falschen Eingaben würden Sie empfehlen?
Inconsistent input --> no action + notification
oder
Inconsistent input --> undefined behaviour or crash
Bearbeiten
Danke für die Antworten und Vorschläge. Ich bin auch ein Fan von Design nach Vertrag. Aber selbst wenn ich der Person vertraue, die den Code geschrieben hat, der meine Methoden aufruft (vielleicht bin es ich selbst), kann es immer noch Fehler geben, die zu falschen Eingaben führen. Daher gehe ich davon aus, dass eine Methode niemals die richtige Eingabe erhält.
Außerdem würde ich einen Mechanismus verwenden, um das Problem abzufangen und darüber zu benachrichtigen. Auf einem Entwicklungssystem würde es zB einen Dialog öffnen, um den Benutzer zu benachrichtigen. In einem Produktionssystem würde es nur einige Informationen in das Protokoll schreiben. Ich glaube nicht, dass zusätzliche Überprüfungen zu Leistungsproblemen führen können. Ich bin mir nicht sicher, ob Behauptungen ausreichen, wenn sie in einem Produktionssystem ausgeschaltet sind: Vielleicht tritt eine Situation in der Produktion auf, die während des Testens nicht aufgetreten ist.
Wie auch immer, ich war wirklich überrascht, dass viele Leute den umgekehrten Ansatz verfolgen: Sie lassen die Anwendung "absichtlich" abstürzen, weil sie behaupten, dass dies das Auffinden von Fehlern während des Testens erleichtert.