Ist es empfehlenswert, eine unnötige Ausnahmebehandlung zu implementieren, falls ein anderer Teil des Codes nicht korrekt codiert ist?
Einfaches Beispiel
Eine einfache, damit ich nicht alle verliere :).
Angenommen, ich schreibe eine App, in der die Informationen einer Person (Name, Adresse usw.) angezeigt werden und die Daten aus einer Datenbank extrahiert werden. Angenommen, ich bin derjenige, der den UI-Teil codiert, und ein anderer schreibt den DB-Abfragecode.
Stellen Sie sich nun vor, dass die Spezifikationen Ihrer App besagen, dass die Person, die die Abfrage codiert, dies erledigen sollte, indem sie für das fehlende Feld "NA" zurückgibt, wenn die Informationen der Person unvollständig sind (sagen wir, der Name fehlt in der Datenbank).
Was ist, wenn die Abfrage schlecht codiert ist und diesen Fall nicht behandelt? Was passiert, wenn der Typ, der die Abfrage geschrieben hat, ein unvollständiges Ergebnis verarbeitet und wenn Sie versuchen, die Informationen anzuzeigen, stürzt alles ab, weil Ihr Code nicht für die Anzeige leerer Inhalte vorbereitet ist?
Dieses Beispiel ist sehr einfach. Ich glaube, die meisten von Ihnen werden sagen: "Es ist nicht Ihr Problem, Sie sind nicht für diesen Absturz verantwortlich." Aber es ist immer noch Ihr Teil des Codes, der abstürzt.
Ein anderes Beispiel
Nehmen wir an, ich bin derjenige, der die Anfrage schreibt. In den Spezifikationen wird nicht dasselbe wie oben angegeben, aber der Typ, der die Abfrage "Einfügen" schreibt, sollte sicherstellen, dass alle Felder ausgefüllt sind, wenn eine Person zur Datenbank hinzugefügt wird, um das Einfügen unvollständiger Informationen zu vermeiden. Sollte ich meine "Auswahl" -Abfrage schützen, um sicherzustellen, dass ich dem Benutzer vollständige Informationen gebe?
Die Fragen
Was ist, wenn in den Spezifikationen nicht ausdrücklich steht, dass "dieser Typ für die Bewältigung dieser Situation verantwortlich ist"? Was ist, wenn eine dritte Person eine andere Abfrage implementiert (ähnlich der ersten, jedoch in einer anderen Datenbank) und Ihren UI-Code verwendet, um sie anzuzeigen, diesen Fall jedoch in seinem Code nicht behandelt?
Sollte ich das Notwendige tun, um einen möglichen Absturz zu verhindern, auch wenn ich nicht derjenige bin, der den schlechten Fall behandeln soll?
Ich suche keine Antwort wie "(s) er ist derjenige, der für den Absturz verantwortlich ist", da ich hier keinen Konflikt löse, würde ich gerne wissen, ob ich meinen Code vor Situationen schützen soll, für die ich nicht verantwortlich bin zu handhaben? Hier würde ein einfaches "wenn leer, etwas tun" ausreichen.
Diese Frage befasst sich im Allgemeinen mit der redundanten Ausnahmebehandlung. Ich frage es, weil ich, wenn ich alleine an einem Projekt arbeite, 2-3 mal eine ähnliche Ausnahmebehandlung in aufeinanderfolgenden Funktionen programmieren kann, "nur für den Fall", dass ich etwas falsch gemacht habe und einen schlechten Fall durchkommen lasse.
Antworten:
Worüber Sie hier sprechen, sind Vertrauensgrenzen . Vertrauen Sie der Grenze zwischen Ihrer Anwendung und der Datenbank? Vertraut die Datenbank darauf, dass die Daten aus der Anwendung immer vorab validiert werden?
Diese Entscheidung muss in jeder Bewerbung getroffen werden, und es gibt keine richtigen und falschen Antworten. Ich neige dazu, zu viele Grenzen als Vertrauensgrenze zu bezeichnen. Andere Entwickler vertrauen gerne darauf, dass APIs von Drittanbietern immer das tun, was Sie von ihnen erwarten.
quelle
Das Robustheitsprinzip "Sei konservativ in dem, was du sendest, sei liberal in dem, was du akzeptierst" ist das, was du suchst. Es ist ein gutes Prinzip - BEARBEITEN: Solange seine Anwendung keine schwerwiegenden Fehler verbirgt -, stimme ich @pdr zu, dass es immer von der Situation abhängt, ob Sie es anwenden sollten oder nicht.
quelle
Es hängt davon ab, was Sie testen. Nehmen wir jedoch an, dass der Umfang Ihres Tests nur Ihr eigener Code ist. In diesem Fall sollten Sie Folgendes testen:
Zu diesem Zweck können Sie nicht die Komponente Ihres Kollegen verwenden. Verwenden Sie stattdessen die Option "Verspotten" , ersetzen Sie den Rest der Anwendung durch "gefälschte" Module, die Sie über das Testframework steuern können. Wie genau Sie dies tun, hängt von der Art und Weise ab, wie die Module miteinander kommunizieren. Es kann ausreichen, die Methoden Ihres Moduls nur mit hartcodierten Argumenten aufzurufen, und es kann so komplex werden, als würde ein ganzes Framework geschrieben, das die öffentlichen Schnittstellen der anderen Module mit der Testumgebung verbindet.
Dies ist jedoch nur der Einzeltestfall. Sie möchten auch Integrationstests, bei denen Sie alle Module gemeinsam testen. Wiederum möchten Sie sowohl den glücklichen Fall als auch die Fehler testen.
In Ihrem Fall "Basic Example" schreiben Sie eine Mock-Klasse, die die Datenbankebene simuliert, um Ihren Code auf Unit-Tests zu testen. Ihre Mock-Klasse geht jedoch nicht wirklich in die Datenbank: Sie laden sie nur mit erwarteten Eingaben und festen Ausgaben vor. Im Pseudocode:
Und so testen Sie, ob Felder fehlen, die korrekt gemeldet werden :
Jetzt wird es interessant. Was ist, wenn sich die echte DB-Klasse schlecht benimmt? Zum Beispiel könnte es aus unklaren Gründen eine Ausnahme auslösen. Wir wissen nicht, ob dies der Fall ist, aber wir möchten, dass unser eigener Code ordnungsgemäß damit umgeht. Kein Problem, wir müssen nur unsere MockDB zu einer Ausnahme machen, indem wir z. B. eine Methode wie die folgende hinzufügen:
Und dann sieht unser Testfall so aus:
Dies sind Ihre Unit-Tests. Für den Integrationstest verwenden Sie nicht die MockDB-Klasse. Stattdessen verketten Sie beide tatsächlichen Klassen miteinander. Sie brauchen noch Geräte; Beispielsweise sollten Sie die Testdatenbank auf einen bekannten Status initialisieren, bevor Sie den Test ausführen.
Was die Zuständigkeiten betrifft: Ihr Code sollte erwarten, dass der Rest der Codebasis gemäß der Spezifikation implementiert wird, aber er sollte auch darauf vorbereitet sein, die Dinge ordnungsgemäß zu handhaben, wenn der Rest versagt. Sie sind nicht dafür verantwortlich, anderen Code als Ihren eigenen zu testen, aber Sie sind dafür verantwortlich, dass Ihr Code widerstandsfähig gegen fehlerhaftes Verhalten des Codes auf der anderen Seite ist, und Sie sind auch dafür verantwortlich, die Widerstandsfähigkeit Ihres Codes zu testen. Das ist, was der dritte Test oben tut.
quelle
Es gibt drei Hauptprinzipien, die ich zu programmieren versuche:
TROCKEN
KUSS
YAGNI
All dies führt dazu, dass Sie das Risiko eingehen, Validierungscode zu schreiben, der an anderer Stelle dupliziert wird. Wenn sich die Validierungsregeln ändern, müssen diese an mehreren Stellen aktualisiert werden.
Natürlich könnten Sie irgendwann in der Zukunft Ihre Datenbank neu plattformen (es passiert). In diesem Fall könnte es vorteilhaft sein, den Code an mehr als einer Stelle zu haben. Aber ... Sie programmieren für etwas, das möglicherweise nicht passiert.
Jeder zusätzliche Code (auch wenn er sich nie ändert) ist mit einem Mehraufwand verbunden, da er geschrieben, gelesen, gespeichert und getestet werden muss.
Wenn all das oben Gesagte zutrifft, wäre es nicht angebracht, überhaupt keine Validierung durchzuführen. Um einen vollständigen Namen in der Anwendung anzuzeigen, benötigen Sie einige grundlegende Daten - auch wenn Sie die Daten selbst nicht validieren.
quelle
In den Wörtern des Laien.
Es gibt keine "Datenbank" oder "Anwendung" .
Nochmal:
quelle