Sollte ich den Rückgabewert eines Methodenaufrufs validieren, auch wenn ich weiß, dass die Methode keine fehlerhaften Eingaben zurückgeben kann?

30

Ich frage mich, ob ich mich gegen den Rückgabewert eines Methodenaufrufs verteidigen soll, indem ich überprüfe, ob er meine Erwartungen erfüllt, auch wenn ich weiß, dass die von mir aufgerufene Methode diese Erwartungen erfüllt.

GEGEBEN

User getUser(Int id)
{
    User temp = new User(id);
    temp.setName("John");

    return temp;
}

SOLL ICH TUN

void myMethod()
{
    User user = getUser(1234);
    System.out.println(user.getName());
}

ODER

void myMethod()
{
    User user = getUser(1234);

    // Validating
    Preconditions.checkNotNull(user, "User can not be null.");
    Preconditions.checkNotNull(user.getName(), "User's name can not be null.");

    System.out.println(user.getName());
}

Ich frage dies auf konzeptioneller Ebene. Wenn ich das Innenleben der Methode kenne, rufe ich auf. Entweder weil ich es geschrieben habe oder weil ich es inspiziert habe. Und die Logik der möglichen Werte, die es zurückgibt, erfüllt meine Voraussetzungen. Ist es "besser" oder "angemessener", die Validierung zu überspringen, oder sollte ich mich immer noch gegen falsche Werte verteidigen, bevor ich mit der Methode fortfahre, die ich gerade implementiere, auch wenn sie immer erfolgreich sein sollte?


Mein Fazit aus allen Antworten (zögern Sie nicht, zu Ihren eigenen zu kommen):

Bestätigen Sie, wann
  • Die Methode hat in der Vergangenheit gezeigt, dass sie sich schlecht verhält
  • Die Methode stammt aus einer nicht vertrauenswürdigen Quelle
  • Die Methode wird von anderen Stellen aus verwendet und gibt die Nachbedingungen nicht explizit an
Behaupten Sie nicht, wenn:
  • Die Methode lebt eng mit Ihrer (siehe gewählte Antwort für Details)
  • Die Methode definiert explizit ihren Vertrag mit so etwas wie einem ordnungsgemäßen Dokument, Typensicherheit, einem Komponententest oder einer Überprüfung nach dem Zustand
  • Die Leistung ist kritisch (in diesem Fall kann ein Debug-Modus als hybrider Ansatz fungieren).
Didier A.
quelle
1
Streben Sie eine Abdeckung von 100% an!
Jared Burrows
9
Warum konzentrieren Sie sich nur auf ein Problem ( Null)? Es ist wahrscheinlich genauso problematisch, wenn der Name ""(nicht null, sondern die leere Zeichenfolge) oder ist "N/A". Entweder können Sie dem Ergebnis vertrauen, oder Sie müssen angemessen paranoid sein.
MSalters
3
In unserer Codebasis haben wir ein Namensschema: getFoo () verspricht, nicht null zurückzugeben, und getFooIfPresent () kann null zurückgeben.
pjc50,
Woher kommt Ihre Vermutung der Code-Vernunft? Gehen Sie davon aus, dass der Wert immer nicht null ist, da er bei der Eingabe überprüft wird, oder aufgrund der Struktur, mit der der Wert abgerufen wird? Und, was noch wichtiger ist, testen Sie jedes mögliche Edge-Case-Szenario? Einschließlich der Möglichkeit eines böswilligen Skripts?
Zibbobz
@MSalters Überprüfen Sie nicht den Wert, wenn es dort ist ;)
Izkata

Antworten:

42

Dies hängt davon ab, wie wahrscheinlich sich getUser und myMethod ändern, und noch wichtiger, wie wahrscheinlich es ist, dass sie sich unabhängig voneinander ändern .

Wenn Sie irgendwie sicher sind, dass getUser sich in Zukunft nie mehr ändern wird, dann ist es eine Zeitverschwendung, es zu validieren, genauso wie es Zeitverschwendung ist, es zu validieren, idas unmittelbar nach einer i = 3;Anweisung einen Wert von 3 hat . In Wirklichkeit weißt du das nicht. Aber es gibt einige Dinge, die Sie kennen:

  • Leben diese beiden Funktionen "zusammen"? Mit anderen Worten, haben sie die gleichen Leute, die sie pflegen, sind sie Teil derselben Datei und werden daher wahrscheinlich für sich alleine "synchron" bleiben? In diesem Fall ist es wahrscheinlich übertrieben, Validierungsprüfungen hinzuzufügen, da dies lediglich bedeutet, dass jedes Mal, wenn sich die beiden Funktionen ändern oder in eine andere Anzahl von Funktionen umgestaltet werden, mehr Code geändert werden muss (und möglicherweise Fehler auftreten).

  • Ist die Funktion getUser Teil einer dokumentierten API mit einem bestimmten Vertrag und myMethod lediglich ein Client dieser API in einer anderen Codebasis? In diesem Fall können Sie in dieser Dokumentation nachlesen, ob Sie Rückgabewerte validieren (oder Eingabeparameter vorvalidieren!) Oder ob es wirklich sicher ist, blindlings dem Pfad der Freude zu folgen. Wenn die Dokumentation dies nicht deutlich macht, bitten Sie den Betreuer, dies zu beheben.

  • Wenn diese bestimmte Funktion in der Vergangenheit plötzlich und unerwartet ihr Verhalten geändert hat und Ihren Code beschädigt hat, haben Sie das Recht, paranoid zu sein. Bugs neigen dazu, sich zu häufen.

Beachten Sie, dass alle oben genannten Punkte auch dann zutreffen, wenn Sie der ursprüngliche Autor beider Funktionen sind. Wir wissen nicht, ob von diesen beiden Funktionen erwartet wird, dass sie für den Rest ihres Lebens "zusammenleben", oder ob sie langsam in separate Module zerfallen, oder ob Sie sich mit einem Fehler in älteren Versionen irgendwie in den Fuß geschossen haben Versionen von getUser. Aber Sie können wahrscheinlich eine ziemlich gute Vermutung anstellen.

Ixrec
quelle
2
Außerdem: Wenn Sie später eine Änderung getUservornehmen würden, damit diese Null zurückgibt, würde die explizite Prüfung Ihnen Informationen liefern, die Sie mit "NullPointerException" und der Zeilennummer nicht erhalten konnten?
user253751
Anscheinend gibt es zwei Dinge, die Sie überprüfen können: (1) Die Methode funktioniert ordnungsgemäß, da sie keine Fehler aufweist. (2) Dass die Methode Ihren Vertrag respektiert. Ich sehe, dass die Bestätigung für Nummer 1 übertrieben ist. Sie sollten stattdessen Tests haben, die # 1 durchführen. Deshalb würde ich i = 3 nicht validieren. Also meine Frage bezieht sich auf # 2. Ich mag deine Antwort dafür, aber gleichzeitig ist es eine Antwort, die dein Urteilsvermögen nutzt. Haben Sie ein anderes Problem, das sich aus der expliziten Validierung Ihrer Verträge ergibt, als ein wenig Zeit mit dem Verfassen der Erklärung zu verschwenden?
Didier A.
Das einzige andere "Problem" ist, dass wenn Ihre Interpretation des Vertrages falsch ist oder falsch wird, Sie die gesamte Validierung ändern müssen. Das gilt aber auch für alle anderen Codes.
Ixrec
1
Kann nicht gegen die Menge gehen. Diese Antwort ist definitiv die richtige, um das Thema meiner Frage abzudecken. Ich möchte hinzufügen, dass Sie nach dem Lesen aller Antworten, insbesondere von @MikeNakis, Ihre Voraussetzungen zumindest im Debug-Modus geltend machen sollten, wenn Sie einen der beiden letzten Punkte von Ixrec haben. Wenn Sie mit dem ersten Aufzählungspunkt konfrontiert sind, ist es wahrscheinlich übertrieben, Ihre Voraussetzungen durchzusetzen. Schließlich sollten Sie bei einem ausdrücklichen Vertrag wie einem ordnungsgemäßen Dokument, einer Typprüfung, einem Komponententest oder einer Zustandsüberprüfung nicht Ihre Voraussetzungen geltend machen, das wäre übertrieben.
Didier A.
22

Die Antwort von Ixrec ist gut, aber ich werde einen anderen Ansatz verfolgen, weil ich der Meinung bin, dass es sich lohnt, darüber nachzudenken. Zum Zweck dieser Diskussion werde ich über Behauptungen sprechen, da dies der Name ist, unter dem Sie Preconditions.checkNotNull()traditionell bekannt sind.

Was ich vorschlagen möchte, ist, dass Programmierer häufig den Grad überschätzen, um den sie sicher sind, dass sich etwas auf eine bestimmte Weise verhält, und die Konsequenzen unterschätzen, wenn sich etwas nicht auf diese Weise verhält. Außerdem erkennen Programmierer die Aussagekraft von Behauptungen häufig nicht als Dokumentation. In der Folge behaupten Programmierer meiner Erfahrung nach die Dinge weitaus seltener, als sie sollten.

Mein Motto ist:

Die Frage, die Sie sich immer stellen sollten, lautet nicht "Soll ich das behaupten?" aber "gibt es etwas, das ich vergessen habe zu behaupten?"

Wenn Sie sich absolut sicher sind , dass sich etwas auf eine bestimmte Weise verhält , werden Sie natürlich nicht behaupten, dass es sich tatsächlich so verhalten hat, und das ist größtenteils vernünftig. Es ist nicht wirklich möglich, Software zu schreiben, wenn Sie nichts vertrauen können.

Aber auch von dieser Regel gibt es Ausnahmen. Seltsamerweise gibt es eine Art von Situation, in der es durchaus wünschenswert ist, int i = 3;mit einer Behauptung zu folgen , idie tatsächlich innerhalb eines bestimmten Bereichs liegt. Dies ist die Situation, in der ies wahrscheinlich ist, dass jemand, der verschiedene Was-wäre-wenn-Szenarien ausprobiert, Änderungen vornimmt, und der folgende Code davon abhängt, idass ein Wert innerhalb eines bestimmten Bereichs liegt der akzeptable Bereich ist. Das int i = 3; assert i >= 0 && i < 5;mag zunächst unsinnig erscheinen, aber wenn Sie darüber nachdenken, erfahren Sie, dass Sie damit spielen ikönnen und in welchem ​​Bereich Sie bleiben müssen. Eine Behauptung ist die beste Art der Dokumentation, weiles wird von der Maschine erzwungen , ist also eine perfekte Garantie, und es wird zusammen mit dem Code überarbeitet , so dass es immer relevant bleibt.

Ihr getUser(int id)Beispiel ist kein sehr entfernter konzeptueller Verwandter des assign-constant-and-assert-in-rangeBeispiels. Sie sehen per definitionem, dass Fehler auftreten, wenn Dinge ein Verhalten aufweisen, das sich von dem Verhalten unterscheidet, das wir erwartet haben. Es stimmt, wir können nicht alles behaupten, daher wird es manchmal zu einem Debugging kommen. In der Branche ist es jedoch allgemein bekannt, dass die Kosten umso geringer sind, je schneller wir einen Fehler erkennen. Die Fragen, die Sie stellen sollten, lauten nicht nur, wie sicher Sie sind, dass getUser()niemals Null zurückgegeben wird (und niemals ein Benutzer mit einem Nullnamen zurückgegeben wird), sondern auch, welche Arten von schlechten Dingen mit dem Rest des Codes passieren, wenn er in ausgeführt wird Tatsache, eines Tages etwas Unerwartetes zurückzugeben, und wie einfach es ist, schnell auf den Rest des Codes zu schauen, um genau zu wissen, was von ihm erwartet wurde getUser().

Wenn das unerwartete Verhalten dazu führen würde, dass Ihre Datenbank beschädigt wird, sollten Sie dies möglicherweise auch dann bestätigen, wenn Sie zu 101% sicher sind, dass dies nicht der Fall ist. Wenn ein nullBenutzername Tausende von Zeilen weiter unten und Milliarden von Taktzyklen später einen seltsamen, kryptischen und nicht nachvollziehbaren Fehler verursachen würde, ist es vielleicht am besten, so früh wie möglich zu versagen.

Obwohl ich der Antwort von Ixrec nicht widerspreche, würde ich vorschlagen, dass Sie die Tatsache ernsthaft in Betracht ziehen, dass Behauptungen nichts kosten, sodass wirklich nichts verloren geht, nur gewonnen werden kann, indem Sie sie großzügig verwenden.

Mike Nakis
quelle
2
Ja. Behaupte es. Ich bin hergekommen, um mehr oder weniger diese Antwort zu geben. ++
RubberDuck
2
@SteveJessop Ich würde das korrigieren ... && sureness < 1).
Mike Nakis
2
@MikeNakis: Das ist immer ein Albtraum beim Schreiben von Unit-Tests, der Rückgabewert, der von der Schnittstelle zugelassen, aber nicht aus Eingaben generiert werden kann ;-) Wenn Sie zu 101% sicher sind, dass Sie Recht haben, liegen Sie definitiv falsch !
Steve Jessop
2
+1 für Hinweise auf Dinge, die ich in meiner Antwort völlig vergessen habe.
Ixrec
1
@DavidZ Das stimmt, meine Frage ging von einer Laufzeitvalidierung aus. Aber zu sagen, dass Sie der Methode beim Debuggen nicht vertrauen und dass Sie der Methode beim Prod nicht vertrauen, ist möglicherweise eine gute Sichtweise auf das Thema. Ein Assert im C-Stil könnte daher eine gute Möglichkeit sein, mit dieser Situation umzugehen.
Didier A.
8

Ein definitives Nein.

Ein Anrufer sollte niemals prüfen, ob die von ihm aufgerufene Funktion seinem Vertrag entspricht. Der Grund ist einfach: Es gibt möglicherweise sehr viele Anrufer, und es ist aus konzeptioneller Sicht unpraktisch und möglicherweise sogar falsch, die Logik zur Überprüfung der Ergebnisse anderer Funktionen für jeden einzelnen Anrufer zu duplizieren.

Wenn irgendwelche Prüfungen durchgeführt werden sollen, sollte jede Funktion ihre eigenen Nachbedingungen prüfen. Die Nachbedingungen geben Ihnen die Gewissheit, dass Sie die Funktion korrekt implementiert haben und die Benutzer sich auf den Vertrag Ihrer Funktion verlassen können.

Wenn eine bestimmte Funktion niemals null zurückgeben soll, sollte dies dokumentiert werden und Teil des Vertrags dieser Funktion werden. Dies ist der Punkt dieser Verträge: Bieten Sie Benutzern einige Invarianten, auf die sie sich verlassen können, damit sie beim Schreiben ihrer eigenen Funktionen weniger Hürden überwinden müssen.

Paul
quelle
Ich stimme dem allgemeinen Gefühl zu, aber es gibt Umstände, in denen es definitiv Sinn macht, Rückgabewerte zu validieren. Wenn Sie beispielsweise einen externen Webdienst anrufen, möchten Sie manchmal zumindest das Format der Antwort (xsd usw.)
überprüfen
Anscheinend befürworten Sie einen Design-by-Contract-Stil gegenüber einem defensiven Programmierstil. Ich denke, das ist eine großartige Antwort. Wenn die Methode einen strengen Vertrag hätte, könnte ich ihm vertrauen. In meinem Fall nicht, aber ich könnte es ändern, um dies zu tun. Sag doch, ich könnte nicht? Würden Sie argumentieren, dass ich der Umsetzung vertrauen sollte? Auch wenn es in seinem Dokument nicht explizit angibt, dass es nicht null zurückgibt oder tatsächlich eine Überprüfung nach dem Zustand durchführt?
Didier A.
Meiner Meinung nach sollten Sie nach bestem Wissen und Gewichten verschiedene Aspekte berücksichtigen, wie viel Vertrauen Sie dem Autor entgegenbringen, um das Richtige zu tun, wie wahrscheinlich es ist, dass sich die Benutzeroberfläche der Funktion ändert und wie eng Ihre zeitlichen Einschränkungen sind. Abgesehen davon hat der Autor einer Funktion meistens eine ziemlich klare Vorstellung davon, wie der Vertrag der Funktion aussehen sollte, auch wenn er dies nicht dokumentiert. Aus diesem Grund sollten Sie den Autoren zunächst anvertrauen, das Richtige zu tun, und erst dann defensiv werden, wenn Sie wissen, dass die Funktion nicht gut geschrieben ist.
Paul
Ich finde, dass es mir hilft, die Arbeit schneller zu erledigen, wenn ich zuerst darauf vertraue, dass andere das Richtige tun. Davon abgesehen sind die Anwendungen, die ich schreibe, einfach zu reparieren, wenn ein Problem auftritt. Jemand, der mit sicherheitskritischerer Software arbeitet, könnte meinen, ich sei zu nachsichtig und bevorzuge einen defensiveren Ansatz.
Paul
5

Wenn null ein gültiger Rückgabewert der getUser-Methode ist, sollte Ihr Code dies mit einem If und nicht mit einer Exception behandeln - dies ist kein Ausnahmefall.

Wenn null kein gültiger Rückgabewert der getUser-Methode ist, liegt ein Fehler in getUser vor - die getUser-Methode sollte eine Ausnahme auslösen oder auf andere Weise behoben werden.

Wenn die getUser-Methode Teil einer externen Bibliothek ist oder auf andere Weise nicht geändert werden kann und Sie möchten, dass im Falle einer Null-Rückgabe Ausnahmen ausgelöst werden, brechen Sie die Klasse und die Methode zusammen, um die Prüfungen durchzuführen und die Ausnahme für jede Instanz von auszulösen Der Aufruf von getUser ist in Ihrem Code konsistent.

MatthewC
quelle
Null ist kein gültiger Rückgabewert von getUser. Bei der Überprüfung von getUser habe ich festgestellt, dass die Implementierung niemals null zurückgeben würde. Meine Frage ist, sollte ich meiner Inspektion vertrauen und meine Methode nicht überprüfen lassen, oder sollte ich an meiner Inspektion zweifeln und trotzdem eine Überprüfung haben. Es ist auch möglich, dass sich die Methode in Zukunft ändert und meine Erwartungen, nicht null zurückzugeben, verletzt.
Didier A.
Und was ist, wenn getUser oder user.getName geändert werden, um Ausnahmen auszulösen? Sie sollten eine Überprüfung durchführen lassen, jedoch nicht als Teil der Methode, die den Benutzer verwendet. Packen Sie die Methode getUser - und sogar die Klasse User - ein, um Ihre Verträge durchzusetzen, wenn Sie über zukünftige Änderungen des getUser-Codes besorgt sind. Erstellen Sie außerdem Komponententests, um Ihre Annahmen zum Verhalten der Klasse zu überprüfen.
MatthewC
@didibus Um Ihre Antwort zu paraphrasieren ... Ein Smiley-Emoticon ist kein gültiger Rückgabewert von getUser. Bei der Überprüfung von getUser stellte ich fest, dass die Implementierung niemals ein Smiley-Emoticon zurückgeben würde . Meine Frage ist, sollte ich meiner Inspektion vertrauen und meine Methode nicht überprüfen lassen, oder sollte ich an meiner Inspektion zweifeln und trotzdem eine Überprüfung haben. Es ist auch möglich, dass sich die Methode in Zukunft ändert und meine Erwartungen, kein Smiley-Emoticon zurückzugeben, übertrifft . Es ist nicht die Aufgabe des Aufrufers, zu bestätigen, dass die aufgerufene Funktion ihren Vertrag erfüllt.
Vince O'Sullivan
@ VinceO'Sullivan Anscheinend steht der "Vertrag" im Mittelpunkt des Problems. Und dass es sich bei meiner Frage um implizite Verträge im Vergleich zu expliziten handelt. Eine Methode, die int zurückgibt. Ich behaupte nicht, dass ich keine Zeichenfolge erhalte. Aber wenn ich nur positive Informationen haben möchte, sollte ich das tun? Es ist nur implizit, dass die Methode kein negatives int zurückgibt, da ich es überprüft habe. Aus der Unterschrift oder der Dokumentation geht nicht hervor, dass dies nicht der Fall ist.
Didier A.
1
Es spielt keine Rolle, ob der Vertrag implizit oder explizit ist. Es ist nicht die Aufgabe des aufrufenden Codes, zu überprüfen, ob die aufgerufene Methode bei Angabe gültiger Daten gültige Daten zurückgibt. In Ihrem Beispiel wissen Sie, dass negative Eingaben keine falschen Antworten sind, aber wissen Sie, ob positive Eingaben richtig sind? Wie viele Tests brauchen Sie wirklich, um zu beweisen, dass die Methode funktioniert? Der einzig richtige Weg ist anzunehmen, dass die Methode korrekt ist.
Vince O'Sullivan
5

Ich würde argumentieren, dass die Prämisse Ihrer Frage nicht stimmt: Warum sollte man zunächst eine Nullreferenz verwenden?

Das Null-Objektmuster ist eine Möglichkeit, Objekte zurückzugeben, die im Wesentlichen nichts bewirken: Geben Sie anstelle von Null für Ihren Benutzer ein Objekt zurück, das "kein Benutzer" darstellt.

Dieser Benutzer ist inaktiv, hat einen leeren Namen und andere Werte ungleich Null, die "hier nichts" angeben. Der Hauptvorteil besteht darin, dass Sie nicht verunreinigen müssen, wenn Ihr Programm Nullprüfungen, Protokollierungen usw. durchführt. Sie verwenden nur Ihre Objekte.

Warum sollte sich ein Algorithmus um einen Nullwert kümmern? Die Schritte sollten gleich sein. Es ist genauso einfach und viel klarer, ein Null-Objekt zu haben, das Null, eine leere Zeichenfolge usw. zurückgibt.

Hier ist ein Beispiel für die Codeüberprüfung auf Null:

User u = getUser();
String displayName = "";
if (u != null) {
  displayName = u.getName();
}
return displayName;

Hier ist ein Beispiel für Code, der ein Null-Objekt verwendet:

return getUser().getName();

Was ist klarer? Ich glaube der zweite ist.


Während die Frage markiert ist , ist es erwähnenswert, dass das Null- Objektmuster in C ++ bei der Verwendung von Referenzen wirklich nützlich ist. Java-Referenzen ähneln eher C ++ - Zeigern und lassen null zu. C ++ Referenzen können nicht enthalten nullptr. Wenn man etwas analog zu einer Nullreferenz in C ++ haben möchte, ist das Nullobjektmuster der einzige Weg, den ich kenne, um dies zu erreichen.

Gemeinschaft
quelle
Null ist nur das Beispiel dessen, was ich behaupte. Es könnte sehr gut sein, dass ich einen nicht leeren Namen brauche. Meine Frage würde immer noch zutreffen. Würden Sie das bestätigen? Oder es könnte etwas sein, das ein int zurückgibt, und ich kann kein negatives int haben, oder es muss in einem bestimmten Bereich liegen. Stellen Sie sich das nicht als Null-Problem vor.
Didier A.
1
Warum würde eine Methode einen falschen Wert zurückgeben? Dies sollte nur an der Grenze Ihrer Anwendung überprüft werden: Schnittstellen zum Benutzer und zu anderen Systemen. Ansonsten haben wir Ausnahmen.
Stellen Sie sich vor, ich hätte: int i = getCount; float x = 100 / i; Wenn ich weiß, dass getCount nicht 0 zurückgibt, weil ich die Methode entweder geschrieben oder überprüft habe, sollte ich die Prüfung auf 0 überspringen?
Didier A.
@didibus: Sie können die Prüfung überspringen, ob getCount() Dokumente garantieren, dass sie jetzt nicht 0 zurückgeben, und dies wird auch in Zukunft nicht der Fall sein, es sei denn, jemand entscheidet sich für eine grundlegende Änderung und versucht, alles zu aktualisieren, was dies erfordert die neue Schnittstelle. Zu sehen, was der Code derzeit tut, ist keine Hilfe, aber wenn Sie Code überprüfen möchten, ist der zu überprüfende Code der Komponententest getCount(). Wenn sie testen, dass keine 0 zurückgegeben wird, wissen Sie, dass jede künftige Änderung, die 0 zurückgibt, als eine brechende Änderung angesehen wird, da die Tests fehlschlagen.
Steve Jessop
Mir ist nicht klar, dass Nullobjekte besser sind als Nullen. Eine Null-Ente mag quaken, aber es ist keine Ente - tatsächlich ist es semantisch das Gegenteil einer Ente. Wenn Sie ein Null-Objekt einführen, muss jeder Code, der diese Klasse verwendet, möglicherweise prüfen, ob eines seiner Objekte das Null-Objekt ist - z. B. haben Sie ein Null-Objekt in einer Menge, wie viele Dinge haben Sie? Dies scheint mir eine Möglichkeit zu sein, Fehler aufzuschieben und Fehler zu verschleiern. Der verlinkte Artikel warnt ausdrücklich vor der Verwendung von Nullobjekten, "nur um Nullprüfungen zu vermeiden und den Code lesbarer zu machen".
Sdenham
1

Im Allgemeinen würde ich sagen, dass dies hauptsächlich von den folgenden drei Aspekten abhängt:

  1. Robustheit: Kann die aufrufende Methode mit dem nullWert umgehen ? Wenn ein nullWert zu a führen könnteRuntimeException einer Überprüfung führen würde ich eine Überprüfung empfehlen - es sei denn, die Komplexität ist gering und aufgerufene / aufrufende Methoden werden vom selben Autor erstellt und nullnicht erwartet (z. B. beide privateim selben Paket).

  2. Verantwortung für den Code: Wenn Entwickler A für den Code verantwortlich ist getUser() Methode verantwortlich ist und Entwickler B sie verwendet (z. B. als Teil einer Bibliothek), würde ich dringend empfehlen, ihren Wert zu validieren. Nur weil Entwickler B möglicherweise nichts über eine Änderung weiß, die zu einem potenziellen nullRückgabewert führt.

  3. Komplexität: Je höher die Gesamtkomplexität des Programms oder der Umgebung ist, desto mehr würde ich empfehlen, den Rückgabewert zu validieren. Auch wenn Sie sich sicher sind, kann es nicht seinnull im Kontext der aufrufenden Methode heute sein , müssen Sie möglicherweise Änderungen getUser()für einen anderen Anwendungsfall vornehmen. Wenn einige Monate oder Jahre vergangen sind und einige tausend Codezeilen hinzugefügt wurden, kann dies eine ziemliche Falle sein.

Außerdem würde ich empfehlen, mögliche nullRückgabewerte in einem JavaDoc-Kommentar zu dokumentieren . Aufgrund der Hervorhebung von JavaDoc-Beschreibungen in den meisten IDEs kann dies eine hilfreiche Warnung für jeden Benutzer sein getUser().

/** Returns ....
  * @param: id id of the user
  * @return: a User instance related to the id;
  *          null, if no user with identifier id exists
 **/
User getUser(Int id)
{
    ...
}
André
quelle
-1

Das musst du definitiv nicht.

Wenn Sie beispielsweise bereits wissen, dass eine Rückgabe niemals null sein kann - warum sollten Sie eine Nullprüfung hinzufügen? Das Hinzufügen eines Null-Checks wird nichts kaputt machen, aber es ist nur überflüssig. Und besser nicht redundante Logik codieren, solange Sie dies vermeiden können.

Yellen
quelle
1
Ich weiß es, aber nur, weil ich die Implementierung der anderen Methode überprüft oder geschrieben habe. Der Vertrag der Methode besagt nicht ausdrücklich, dass dies nicht möglich ist. So könnte es sich zum Beispiel in Zukunft ändern. Oder es könnte einen Fehler geben, der dazu führt, dass eine Null zurückgegeben wird, selbst wenn dies nicht versucht wird.
Didier A.