Zur Philosophie von Exceptions

Status
Nicht offen für weitere Antworten.

marasek

Aktives Mitglied
Ich bin immer etwas erstaunt, wie in Java das Thema Fehlerbehandlung gehandhabt wird - dies mal erläutert am Beispiel von ClassLoader.getRessource() (des üblichen). Wenn es eine Ressource nicht gibt, erhält man anstelle einer url null. Wenn man nun nicht in eine NPE rennen will, weil ein Torfkopf eine Datei im Deployment vergessen hat, geht man z. B. wie folgt vor:

Java:
public void test() {
	URL pic;
	String resname;
	resname = "images/guffy.png";
	pic = this.getClass().getClassLoader().getResource(resname);
	if(pic==null) {
		throw new Error("could not load "+resname);
	} 
}

Mein Vorgehen mit Exceptions war bislang immer anders. Eine Exception wird dann geworfen, wenn eine Methode/Funktion nicht das ausführen kann, was ich von ihr verlange. Im Beispiel würde also getResource eine Exception werfen. Flankierend dazu habe ich immer eine Methode "has..." geschrieben, in dem Fall hasResource().

Das eröffnet mir zwei Möglichkeiten:
a. wenn die fehlende Ressource die Ausführung des Programms sinnlos macht, rufe ich getResource ohne Prüfung auf und kann mir die zusätzliche Fehlerbehandlung sparen, da sie von getResource erledigt wird. Im Fehlerfall sehe ich sofort, was schief gelaufen ist.
b. wenn eine Ressource optional ist, dann kann ich mit hasResource auf ihre Existenz prüfen, bevor ich sie hole, oder try...catch, wobei ich ersteres "sprechender" finde.

Java:
public void test() {
	URL pic;
	URL optional;
	String resname;
	//wenn dieses bild nicht da ist, kann das programm nicht weiter ausgeführt werden
	pic = this.getClass().getClassLoader().getResource("images/mandatory.png");
	//dieses Bild ist optional.
	if(this.getClass().getClassLoader().hasResource("images/optional.png") {
		this.getClass().getClassLoader().getResource("images/optional.png");
	}
}

Das habe ich unter PHP sehr konsequent durchgezogen, was sich recht positiv auf die Stabilität und Wartbarkeit der Programme ausgewirkt hat. Unter Java wird mir dieser Ansatz gründlich versalzen.

Die Frage, die mich beschäftigt, ist: was ist die an dieser Stelle hinter Java stehende Philosophie, da es offenkundig nicht die meinige ist? Ich möchte die andere Seite erst verstehen, eh ich mich für etwas entscheide.
 

tfa

Top Contributor
Dieses Beispiel ist sicherlich nicht repräsentativ für das Exception-Konzept in Java. Diese spezielle Methode liefert halt null zurück, wenn die Ressource nicht existiert. Die Designer der Java-API haben das eben so (warum auch immer) entworfen und dokumentiert. Eine Exception zu werfen, wäre eine andere Möglichkeit gewesen.

Ich nehme mal an, dein Code-Beispiel sollte eigentlich so aussehen:

Java:
    URL pic=null;
    URL optional=null;
    String resname;
    //wenn dieses bild nicht da ist, kann das programm nicht weiter ausgeführt werden
    pic = this.getClass().getClassLoader().getResource("images/mandatory.png");
    //dieses Bild ist optional.
    if(this.getClass().getClassLoader().hasResource("images/optional.png") {
        optional=this.getClass().getClassLoader().getResource("images/optional.png");
    }

Die optionale Ressource wäre in diesem Fall null, wenn nicht vorhanden.

Was würde passieren, wenn du den Test weglässt?

Java:
    URL pic=null;
    URL optional=null;
    String resname;
    //wenn dieses bild nicht da ist, kann das programm nicht weiter ausgeführt werden
    pic = this.getClass().getClassLoader().getResource("images/mandatory.png");
    //dieses Bild ist optional.
    optional=this.getClass().getClassLoader().getResource("images/optional.png");

Richtig. Genau das gleiche. optional == null

Der Nachteil bei deinem Test ist, dass zweimal nach der Ressource gesucht werden muss statt einmal. Außerdem erzeugst du so mehr Code.
 

marasek

Aktives Mitglied
Dieses Beispiel ist sicherlich nicht repräsentativ für das Exception-Konzept in Java. Diese spezielle Methode liefert halt null zurück, wenn die Ressource nicht existiert. Die Designer der Java-API haben das eben so (warum auch immer) entworfen und dokumentiert. Eine Exception zu werfen, wäre eine andere Möglichkeit gewesen.

Naja, dieses Verhalten gibt es noch an anderen Stellen (z. B. HashMap). Und CheckedException ermuntert einen nicht gerade dazu, Exceptions zu werfen.

Was würde passieren, wenn du den Test weglässt?

Java:
    URL pic=null;
    URL optional=null;
    String resname;
    //wenn dieses bild nicht da ist, kann das programm nicht weiter ausgeführt werden
    pic = this.getClass().getClassLoader().getResource("images/mandatory.png");
    //dieses Bild ist optional.
    optional=this.getClass().getClassLoader().getResource("images/optional.png");

Richtig. Genau das gleiche. optional == null

Der Nachteil bei deinem Test ist, dass zweimal nach der Ressource gesucht werden muss statt einmal. Außerdem erzeugst du so mehr Code.

Schon, aber mandatory.png bleibt dann unchecked. Wenn ich eine aussagekräftige Fehlermeldung haben will, muss ich sie selber bauen - ich erzeuge eher so mehr Code.

Was den Performanceverlust anbelangt, gebe ich Dir recht, er betrifft aber nur die Fälle, in denen ich eine Optionalität habe.
 
M

maki

Gast
Wenn ich eine aussagekräftige Fehlermeldung haben will, muss ich sie selber bauen - ich erzeuge eher so mehr Code.
Dieser Fehler wäre ein Programmierfehler bzw. ein Buildfehler.
Würde da nix gegen eine NullPointerException haben, denn die ist immer ein zeichen für Programmierfehler.
Man sollte nicht zuviel Zeit inverstieren Programmierfehler in einer schönen Form zu Präsentieren, inverstier die Zeit lieber in Unittests & sauberen Code, denn diese finden & erschweren Programmierfehler.
 

marasek

Aktives Mitglied
Dieser Fehler wäre ein Programmierfehler bzw. ein Buildfehler.
Würde da nix gegen eine NullPointerException haben, denn die ist immer ein zeichen für Programmierfehler.
Man sollte nicht zuviel Zeit inverstieren Programmierfehler in einer schönen Form zu Präsentieren, inverstier die Zeit lieber in Unittests & sauberen Code, denn diese finden & erschweren Programmierfehler.

Warum nicht? Buildfehler kommen vor, dann will ich sie schnell identifizieren können. Auch bei einem Unittest will ich eine aussagekräftige Fehlermeldung haben.
 

Wildcard

Top Contributor
Eine NPE ist doch sehr aussagekräftig, du siehst sofort wo er herkam.
Eine andere Möglichkeit ist mit asserts zu arbeiten zB in privaten Methoden, oder für Fehlerzustände die im regulären Betrieb so nicht auftreten.
 
M

maki

Gast
Warum nicht? Buildfehler kommen vor, dann will ich sie schnell identifizieren können. Auch bei einem Unittest will ich eine aussagekräftige Fehlermeldung haben.
IMHO sollten Programmierfehler nicht "schön" bearbeitet werden, sondern ziemlich hart aufschlagen.
Hab schon erlebt dass man mehr Energie in die Behandlung der Exceptions gesteckt hat anstatt den Fehler einfach zu beseitigen ;)

Wenn die Ressourcen fehlen, könnte man noch eine MissingResourceException schmeissen, aber imho ist eine NPE vollkommen ausreichend, sollte sowieso beim Integrationstest auffalllen.

Wieso sollten Buildfehler eigentlich vorkommen? ???:L
Sollten eigentlich nie vorkommen...
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben