it-swarm.com.de

Mit @Nonnull kommentierte Parameter auf null prüfen?

Wir haben damit begonnen, FindBugs zu verwenden und unsere Parameter entsprechend mit @Nonnull zu versehen, und es funktioniert hervorragend, frühzeitig auf Fehler hinzuweisen. Bisher haben wir diese Argumente mit Guavas null weiter auf checkNotNull überprüft, aber ich würde es vorziehen, nur an den Rändern nach null zu suchen - Stellen, an denen der Wert eingehen kann ohne auf null geprüft worden zu sein, zB eine SOAP Anfrage.

// service layer accessible from outside
public Person createPerson(@CheckForNull String name) {
    return new Person(Preconditions.checkNotNull(name));
}

...

// internal constructor accessed only by the service layer
public Person(@Nonnull String name) {
    this.name = Preconditions.checkNotNull(name);  // remove this check?
}

Ich verstehe, dass @Nonnullnull -Werte selbst nicht blockiert.

Da FindBugs jedoch darauf hinweist, dass ein Wert von einem nicht markierten Feld in ein markiertes @Nonnull Übertragen wird, können wir uns nicht darauf verlassen, dass es diese Fälle abfängt (was es tut), ohne diese Werte überprüfen zu müssen null überall dort, wo sie im System herumgereicht werden? Bin ich naiv, dem Tool vertrauen und diese ausführlichen Prüfungen vermeiden zu wollen?

Fazit: Obwohl es sicher erscheint, den zweiten null Check unten zu entfernen, ist es eine schlechte Praxis?

Diese Frage ist vielleicht zu ähnlich zu Sollte man nach null suchen, wenn er nicht null erwartet , aber ich frage speziell in Bezug auf die Annotation @Nonnull.

19
David Harkness

Wenn Sie FindBug nicht vertrauen, kann es eine Option sein, eine Zusicherung zu verwenden. Auf diese Weise vermeiden Sie die von User MSalters erwähnten Probleme, haben aber dennoch eine Überprüfung. Natürlich ist dieser Ansatz möglicherweise nicht anwendbar, wenn ein solcher ausfallsicherer Ansatz nicht durchführbar ist, d. H. Sie müssen eine Ausnahme abfangen.

Und um die Frage weiter zu beantworten, ob es eine schlechte Praxis ist. Nun, das ist fraglich, aber ich würde es nicht glauben. Ich betrachte diese FindBug-Annotation als eine Lichtspezifikation, die dem Prinzip des Entwurfs nach Vertrag folgt.

Beim Design by Contract stellen Sie einen Vertrag zwischen einer Methode und ihrem Aufrufer her. Der Vertrag besteht aus Voraussetzungen, die der Aufrufer beim Aufruf der Methode zu erfüllen bereit ist, und einer Nachbedingung, die die Methode nach der Ausführung erfüllt, wenn ihre Voraussetzung erfüllt ist.

Einer der Vorteile dieser Entwicklungsmethode besteht darin, dass Sie einen sogenannten defensiven Programmierstil vermeiden können (bei dem Sie explizit auf alle ungültigen Parameterwerte usw. prüfen). Stattdessen können Sie sich auf den Vertrag verlassen und redundante Überprüfungen vermeiden, um die Leistung und Lesbarkeit zu verbessern.

Verträge können zur Überprüfung der Laufzeitzusicherung verwendet werden, die dem oben genannten Fail-First-Prinzip folgt, bei dem Ihr Programm bei Vertragsbruch fehlschlagen soll, sodass Sie einen Hinweis auf die Fehlerquelle erhalten. (Eine fehlgeschlagene Vorbedingung bedeutet, dass der Aufrufer etwas falsch gemacht hat. Eine fehlgeschlagene Nachbedingung zeigt einen Implementierungsfehler der angegebenen Methode an.)

Darüber hinaus können Verträge für die statische Analyse verwendet werden, um Rückschlüsse auf den Quellcode zu ziehen, ohne ihn tatsächlich auszuführen.

Die Annotation @nonnull kann als Voraussetzung für die statische Analyse durch das Tool FindBugs angesehen werden. Wenn Sie einen Ansatz wie die Überprüfung der Laufzeit-Assertion bevorzugen, d. H. Die Fail-First-Strategie, sollten Sie die Verwendung von Assertion-Anweisungen als integriertes Java in Betracht ziehen. Oder um sich mithilfe einer Spezifikationssprache für Verhaltensschnittstellen wie Java Modeling Language (JML)) an eine ausgefeiltere Spezifikationsstrategie anzupassen.

JML ist eine Erweiterung von Java, in die die Spezifikation eingebettet ist in special Java Kommentare. Ein Vorteil dieses Ansatzes besteht darin, dass Sie eine ausgefeilte Spezifikation verwenden können, auch wenn Sie a verwenden Entwicklungsansatz, bei dem Sie sich nur auf Spezifikationen und nicht auf Implementierungsdetails verlassen und verschiedene Tools verwenden, die die Spezifikation verwenden, z. B. die genannten Tools zur Überprüfung der Laufzeitzusicherung, die automatisierte Generierung von Komponententests oder die Dokumentation.

Wenn Sie meinen Standpunkt teilen, dass @nonnull ein (leichter) Vertrag ist, ist es üblich, keine zusätzlichen Überprüfungen hinzuzufügen, da die ursprüngliche Idee hinter diesem Prinzip darin besteht, defensive Programmierung zu vermeiden.

6
FabianB

Überlegen Sie, warum Sie nicht schreiben

this.name = Preconditions.checkNotNull(name);  // Might be necessary
that.name = Preconditions.checkNotNull(this.name);  // Who knows?

Programmieren ist keine schwarze Magie. Variablen werden nicht plötzlich zu Null. Wenn Sie wissen, dass eine Variable nicht Null ist und Sie wissen, dass sie nicht geändert wurde, überprüfen Sie sie mit nicht.

Wenn Sie dies überprüfen, wird ein Programmierer in Zukunft (möglicherweise Sie) viel Zeit damit verbringen, herauszufinden, warum diese Überprüfung vorhanden ist. Der Scheck muss schließlich aus einem bestimmten Grund vorhanden sein. Was übersehen Sie also?

4
MSalters