PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Java] Exception verwenden?


Monger
2006-06-28, 22:16:16
Hallo ihr Programmier-Gurus! :D

Bisher habe ich unter Java die Exceptions sträflich vernachlässigt. Ich überarbeite gerade einen alten Code, und bin dabei auf folgende Frage gestoßen:


Ich habe bisher eine Methode, die über den Rückgabewert nur angibt, ob sie korrekt durchgelaufen ist oder nicht, also "true" für gut, und "false" für schlecht.
Jetzt ist es so, dass ich diese Methode gerne static machen würde, weil eigentlich das Objekt dieser Klasse überflüssig ist. Die Methode füllt aber verschiedene Attribute ab, die ja jetzt logischerweise irgendwo bleiben müssen. Mir fallen jetzt auf Anhieb folgende Möglichkeiten ein:

1) eine eigene Klasse schreiben, in die ich alle Attribute reinstopfe (auch die Meldung, obs geklappt hat oder nicht), solch ein Objekt zurückgeben, und in der aufrufenden Methode wieder auseinander packen.

2) die meisten Attribute als Referenz in den Methodenaufruf packen, ein bestimmtes Attribut als Rückgabewert formulieren (geht nicht anders, es sei denn ich verwende das Sentinel Pattern), und eine eigene Exception werfen, wenn's nicht geklappt haben sollte.


Jetzt meine Frage: Gibt es grundsätzliche Bedenken gegen einen der beiden Ansätze? Sind Exceptions für solche Art von Rückgaben überhaupt geeignet, oder mißbrauche ich da das Exception Konzept? Sind Ausnahmebehandlungen rechenintensiv? Weil es kann durchaus sein, dass dann innerhalb kurzer Zeit ein paar hundert Exceptions geworfen werden.

Abe Ghiran
2006-06-29, 10:11:15
Was spricht denn gegen eine Kombination aus beidem? Also eine Instanz einer Klasse, die alle Attribute enthält, als Rückgabewert und eine Exception werfen wenn es nicht geklappt hat?
Und wie kommst du darauf, daß die Exception so häufig geworfen werden könnte? Das wäre natürlich unschön, denn das soll ja die Ausnahme und nicht die Regel sein. Kannst du mal ein bißchen beschreiben, was du da genau machst?
Ich würde zwar generell Exceptions bevorzugen, wenn die Methode aber aus welchen Gründen auch immer häufig fehl schlagen kann, fände ich die Kombination boolscher Rückgabewert als Statusflag + eine Containerklasse für die Attribute als Referenz an die Methode übergeben besser.
Oder wäre es eventuell eine Möglichkeit, den Code dieser Methode in die aufrufende Funktion zu verlagern? Du sagst ja selbst, daß die Klasse zu der die Methode gehört im Prinzip überflüssig geworden ist.
Um den Overhead von Exception handling würde ich mir dagegen erst mal keine Gedanken machen (Premature optimization...).

Grüße, Jan

Monger
2006-06-29, 10:30:57
Im Prinzip nehme ich eine Reihe von Objekten, vertausche sie durch Permutation, analysiere die Zusammensetzung, und gebe das erste richtige Ergebnis zurück.

Wenn ich jetzt alle Kombinationsmöglichkeiten durchgehen muss, und jedesmal wenn es nicht geklappt hat eine Exception geworfen wird, können das schnell ein paar hundert werden.

Ich hab an andererer Stelle schon recht kräftig optimiert, so dass bei weitem nicht alle Kombinationsmöglichkeiten wirklich durchlaufen werden müssen. Performancemäßig spürt man inzwischen (glücklicherweise, das war mal ganz anders) gar nichts mehr.


Mir gehts auch eher ums Prinzip: wann sollte man Exceptions verwenden, wann nicht? Momentan gebe ich regelmäßig null zurück, wenn aus irgendeinem Grunde kein gültiges Objekt gefunden werden kann, und prüfe dann halt beim Aufruf auf null.
Nachdem ich mich ein bißchen in Exceptions reingelesen habe, habe ich den Verdacht, dass das unsauberer Code ist, aber ich bin nach wie vor sehr verunsichert:

Wann ist es angebracht, auf Exceptions aufzubauen, und wann nicht? Die Exceptions von denen ich hier rede, würde der Benutzer übrigens nie zu Gesicht bekommen, sondern die würden intern abgefangen.

SgtTynis
2006-06-29, 11:25:20
Exceptions sind fuer das erkennen und "verwalten" fehlerhafter, unnormaler Programmablaeufe gedacht und sollten kein Ersatz fuer Rueckgabewerte darstellen die im vorgesehen Programmablauf passieren.
Beispielweise sei mal eine IOException genommen. Laest sich eine Datei nicht oeffnen, so wird eine solche ausgeloest, da es den nicht vorgesehen Programmablauf darstellt. Dagegen sollte eine Methode FileExists keine Exception ausloesen wenn die erfragte Datei nicht vorhanden ist, sonders dies via Rueckgabewert bekannt geben, da hier ein nichtvorhandensein der Datei Teil der normalen Funktionalitaet darstellt. So zumindest mein Verstaendnis von Exceptions.

Abe Ghiran
2006-06-29, 11:27:14
Monger[/POST]']
Mir gehts auch eher ums Prinzip: wann sollte man Exceptions verwenden, wann nicht? Momentan gebe ich regelmäßig null zurück, wenn aus irgendeinem Grunde kein gültiges Objekt gefunden werden kann, und prüfe dann halt beim Aufruf auf null.
Nachdem ich mich ein bißchen in Exceptions reingelesen habe, habe ich den Verdacht, dass das unsauberer Code ist, aber ich bin nach wie vor sehr verunsichert:

Wann ist es angebracht, auf Exceptions aufzubauen, und wann nicht? Die Exceptions von denen ich hier rede, würde der Benutzer übrigens nie zu Gesicht bekommen, sondern die würden intern abgefangen.

Ich verwende Exceptions selber immer dann, wenn es wirklich eine Ausnahme ist. Also ich erwarte, daß die Methode eigentlich problemlos durchlaufen würde aber in einigen esoterischen Fällen klappt es dann doch nicht, z.B. bei Zugriffen ins Dateisystem, wenn die Datei nicht da ist oder beschädigt ist z.B.
Oder ich hatte mal ein Spiel mit Netzwerkinterface, wo ich übers Netz eine Spielsituation empfangen habe (als ascii Zeichen kodiert) für die ich dann einen Zug berechnen wollte. Aus der Ascii Darstellung wird dann per Konstruktor ein Playfield Objekt erzeugt und der Konstruktor schmeißt eine Exception, wenn es keine gültige Spielsituation ist. Das sollte nicht gerade die Regel sein, kommt aber bei Studenten, die gerade das Programmierpraktikum absolvieren vor und dann sollte die Musterlösung das behandeln können :).
Dann hat man mit Exception handling den normalen im Code sauber von der Fehlersituation getrennt und das ist ja Sinn der Sache.

Bei Fällen die ich für wirklich extrem unwahrscheinlich halte, werfe ich dann auch mal RuntimeExceptions, die ich beim Aufrufer nicht unbedingt fange. Das beendet dann zwar hart das Programm aber was solls, spielt bei meinen kleinen Programmen für den Hausgebrauch keine große Rolle.
In der Regel verfahre ich so auch, wenn mir Exception handling von der Api aufgezwungen wird, ich mir aber sicher bin, daß das nie vorkommen wird. Z.B. ClassNotFoundException bei Deserialisierung, fangen (oder weiter schmeißen) muß ich die Exception ja. Einen leeren catch block finde ich dann auch extrem häßlich, also wird die Exception im catch block in eine neue RuntimeException verpackt und diese weiter geworfen. Das sollte nie vorkommen aber wenn es doch mal passiert, kriege ich es mit.

null zurück zu geben finde ich in deiner Situation durchaus ok, denn das ist ja nicht wirklich ein Fehler, wenn keine gültige Permutation gefunden wurde. Allerdings würde ich dafür noch eine schöne Konstante vergeben:

private static final ObjectTyp NO_OBJECT_FOUND = null;

o.ä., das macht sich im Code meiner Meinung nach besser:

ObjectTyp result = bla();
if(result == NO_OBJECT_FOUND){
....
} else {
}


Grüße, Jan

Monger
2006-06-29, 11:38:39
OK, überzeugt. Ich hab jetzt mir auch ein paar Artikel durchgelesen, die genau das selbe sagen. Exceptions sollte man nur dann werfen, wenn eine seltene Situation auftritt, mit der die Methode selbst nicht zurechtkommen kann.

So wie ich das überblicken kann, gibt es dann wirklich sehr, SEHR wenige Fälle wo Exceptions wirklich Sinn machen.

Ich hab gestern den entsprechenden Ansatz schon gemacht, und werde jetzt auch so weitermachen, sprich: keine Exception, dafür ein komplexer Rückgabetyp.

Danke für eure Kommentare.

Shink
2006-06-29, 14:00:23
Sehe ich auch so, aber offensichtlich ist das nicht ganz was sich Sun darunter vorstellt.

Z.B.:
int foo=Integer.parseInt("12 ");

wirft eine Exception - klar, int kann ja nicht null sein - die leitet sich allerdings nichtmal von Exception ab und fällt somit bei den meisten Anwendern durch, wenn sie nicht explizit abgefangen wird.

Abe Ghiran[/POST]']Ich verwende Exceptions selber immer dann, wenn es wirklich eine Ausnahme ist. Also ich erwarte, daß die Methode eigentlich problemlos durchlaufen würde aber in einigen esoterischen Fällen klappt es dann doch nicht, z.B. bei Zugriffen ins Dateisystem, wenn die Datei nicht da ist oder beschädigt ist z.B.
Oder ich hatte mal ein Spiel mit Netzwerkinterface, wo ich übers Netz eine Spielsituation empfangen habe (als ascii Zeichen kodiert) für die ich dann einen Zug berechnen wollte. Aus der Ascii Darstellung wird dann per Konstruktor ein Playfield Objekt erzeugt und der Konstruktor schmeißt eine Exception, wenn es keine gültige Spielsituation ist. Das sollte nicht gerade die Regel sein, kommt aber bei Studenten, die gerade das Programmierpraktikum absolvieren vor und dann sollte die Musterlösung das behandeln können :).
Dann hat man mit Exception handling den normalen im Code sauber von der Fehlersituation getrennt und das ist ja Sinn der Sache.

Bei Fällen die ich für wirklich extrem unwahrscheinlich halte, werfe ich dann auch mal RuntimeExceptions, die ich beim Aufrufer nicht unbedingt fange. Das beendet dann zwar hart das Programm aber was solls, spielt bei meinen kleinen Programmen für den Hausgebrauch keine große Rolle.
In der Regel verfahre ich so auch, wenn mir Exception handling von der Api aufgezwungen wird, ich mir aber sicher bin, daß das nie vorkommen wird. Z.B. ClassNotFoundException bei Deserialisierung, fangen (oder weiter schmeißen) muß ich die Exception ja. Einen leeren catch block finde ich dann auch extrem häßlich, also wird die Exception im catch block in eine neue RuntimeException verpackt und diese weiter geworfen. Das sollte nie vorkommen aber wenn es doch mal passiert, kriege ich es mit.

null zurück zu geben finde ich in deiner Situation durchaus ok, denn das ist ja nicht wirklich ein Fehler, wenn keine gültige Permutation gefunden wurde. Allerdings würde ich dafür noch eine schöne Konstante vergeben:

private static final ObjectTyp NO_OBJECT_FOUND = null;

o.ä., das macht sich im Code meiner Meinung nach besser:

ObjectTyp result = bla();
if(result == NO_OBJECT_FOUND){
....
} else {
}


Grüße, Jan

HajottV
2006-06-29, 14:29:02
Shink[/POST]']Sehe ich auch so, aber offensichtlich ist das nicht ganz was sich Sun darunter vorstellt.

Z.B.:
int foo=Integer.parseInt("12 ");

wirft eine Exception - klar, int kann ja nicht null sein - die leitet sich allerdings nichtmal von Exception ab und fällt somit bei den meisten Anwendern durch, wenn sie nicht explizit abgefangen wird.

Quatsch.

NumberFormatException => IllegalArgumentException => RuntimeException => Exception

gruß

Jörg

Shink
2006-06-29, 15:56:51
HajottV[/POST]']Quatsch.

NumberFormatException => IllegalArgumentException => RuntimeException => Exception

gruß

Jörg
Hmm, RuntimeException=>Exception hätt ich jetzt nicht erwartet aber stimmt.