[Java/Exceptions] Exceptionstruktur

TommyMo

Erfahrenes Mitglied
Hi Leute!

Ich möchte in meiner Anwendung das Exceptionkonzept - natürlich, was sonst - verwenden, und für gewisse Fehler eigene Exceptions bauen. Durch OO kein Problem.

Habt ihr Tipps wie man so eine Exceptionstruktur aufbaut, oder gibt es gewisse Dinge die ein MUSS für gutes Exceptionmanagement sind?

Wäre für hilfreiches Know How ziemilch dankbar :p

Gruß
TOM
 
Also es gibt da denke ich 2 Gesichtspunkte. Der eine ist welche anwendungseigene Exceptions man vorsieht und ob es sich dabei um gecheckte oder ungecheckte Exceptions handeln soll. Dieser Punkt ist sehr Anwendungsabhängig und es mag da versciedene Philosophien geben. Der 2. Aspekt betrifft wie man das Exceptionhandling selbst gestaltet. Es gibt zwar einerseits die Empfehlung möglichst jede gecheckte Excpetion in der Signatur vorzusehen und für so ziemlich jeden Try Block alle Excetions explizit zu catchen, vermutlich aus Dokumentatorischen Grünen) aber ich halte dieses nicht für so sonderlich sinnvoll, denn es bläht den Code nur unnötig auf und die Wahrscheinlichkeit redundanter codierung is herzlich gewiss.
Ich habe für meine Programme einen sogenannten Exceptionhandler mir einfallen lassen. der zu Beginn der Anwendung, wenn das Defaultverhalten nicht ausreichen sollte mit weiterem Leben gefüllt werden kann. Dieser Exceptionhandler ist imgrunde eine Art Dekorater oder auch Fasade. Er kann einen speziell geprägten Exceptionhandler aufnehmen und delegiert die Exceptionabhandlung an diesen. in den catch-Blöcken selbst versuche ich so fern es technisch zulässig ist, nur noch die Exception mit ExceptionHandler.handleException(exception) ; weiterzu geben. Catchen wie gesagt tuh ich dann damit sehr algemein und habe keine Unzahl an diesen catch-Böcken für ein try.

der ExceptionHandler (im folgenden MExceptionHandler genannt) ist folgendermaßen aufgebaut:
Interface ExceptionHanlderLike hat eine Methodensignatur...
handleException (Throwable e);

Die Fasade MExceptionHandler implementiert dieses Interface und hat als interne Klasse eine Defaultimplementierung (Ausgabe des Trace-Stacks)
Sie stellt zusätzlich die Methode setHandler(ExceptionHandlerLike); bereit.

in einer Anwendung wird eine neue EceptionenHandler-Klasse implementiert die das obige Interface mit Leben füllt und dabei Anhand des Typs des ankommenden Throwable fachlich entsprechend reagiert, z.B. ein Log schreibt und/oder einen Informationsdialog aufpoppt ...

fertig ist die Laube.


Takidoso
 
Super! Danke dir! Hört sich sehr gut an. Das Konzept hab ich im Großen und Ganzen verstanden denke ich. Ich muss mir das jetzt nach dem Mittagessen noch genauer ansehn, aber Fragen werden sicher auftauchen. Be prepared! :p

Gruß
TOM
 
Hallo!

Man sollte es mit eigenen ExceptionHierarchien nicht uebertreiben...
Ausnahmen, die rein technischen Ursprungs sind und bei deren Auftreten man sowieso keine vernünftigen Gegenmaßnahmen einleiten kann sollten Unchecked Exceptions sein. ... Von der Idee einen eigenen zentralen Exception-Handler abzulegen halte ich nicht viel. Dazu muss man ja fuer "jede" im System vorkommende Ausnahme erstmal einen passenden ExceptionHandler erstellen und bei deinem globalen ExceptionHandler registrieren. Warum diese Indirektion? Der Code zur Behandlung einer Ausnahmesituation in einem speziellen Kontext ist oftmals sehr spezifisch und weil er dass ist passt er eben oftmals nur an dieser Stelle und ist nicht beliebig oft wiederzu verwenden (was eine eigenen ExceptionHandler rechtfertigen würde.)

Die Klasse Thread (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html) hat ein Konstrukt (UncaughtExceptionHandler) um Ausnahmen abzufangen die bisher von keiner anderen Behandlungs-Instanz behandelt wurde.

setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) registriert man nun einen solchen UncaughtExceptionHandler bei einem Thread so wird bei dem Auftreten einer unbehandelten Ausnahme die Methode:
uncaughtException(....)
aufgerufen. Dort kann man dann in einheitlicher Weise (passend zu den Aufgaben dieses Threads) auf unbehandelte Ausnahmen reagieren.

Gruss Tom
 
Ich danke euch mal für die Vorschläge!

Bin mir immer noch nicht sicher wie ichs machen werde. Sind auf jedenfall gute Denkanstöße! Gracias :)

TOM
 
Thomas Darimont hat gesagt.:
Hallo!

Man sollte es mit eigenen ExceptionHierarchien nicht uebertreiben...
Ausnahmen, die rein technischen Ursprungs sind und bei deren Auftreten man sowieso keine vernünftigen Gegenmaßnahmen einleiten kann sollten Unchecked Exceptions sein. ... Von der Idee einen eigenen zentralen Exception-Handler abzulegen halte ich nicht viel. Dazu muss man ja fuer "jede" im System vorkommende Ausnahme erstmal einen passenden ExceptionHandler erstellen und bei deinem globalen ExceptionHandler registrieren. Warum diese Indirektion? Der Code zur Behandlung einer Ausnahmesituation in einem speziellen Kontext ist oftmals sehr spezifisch und weil er dass ist passt er eben oftmals nur an dieser Stelle und ist nicht beliebig oft wiederzu verwenden (was eine eigenen ExceptionHandler rechtfertigen würde.)
Ja da scheiden sich vermutlich die Geister... :-)
Also zunächst mal ist es so, dass eine Ausnahme zu 95 % immer eines bedeutet:
Abbruch der fachlichen Funktionalität.
Die Frage ist wie reagiert man darauf. Allgemein ist es so ziemlich immer das gleiche...
Fehler irgendwo protokolieren (z.b. trace-Stack in ein log) Wenn es sich um eine anwendung mit GUI handelt Meldung and den User (z.B. mittels Pop-up-Dialog)
eventuell Daten in einen definierten konsistenten Zustand bringen (kommt meist bei DB-Anwendungen zum tragen und kann aus meiner Sicht als etwas spezielles angesehen werden).

Meist handelt es sich also um nur wenige Zeilen code, die sich aber recht häufig wiederholen können, und wenn man dann mal auf die Idee kommen sollte z.B. den Loglevel zu ändern bei der gelogged werden soll oder ein anderer Netterer Dialog etc ist man dann n mal am ändern. Auch wenn es mit Find/Replace einigermaßen zügich gehen könnte, jenach Größe der Anwendung, ist es aus meiner Sicht vertane Zeit, wenn man doch nur eigentlich ein bissle zentral ändern braucht. Nach meinen Erfahrungen erschlägt man mit so einem Handler 98% aller Fälle. Er selbst nimmt ganz allgemein Throwable an insofern muss man nicht großartiges anderes tun nur weil es sich mal um eine andere Exception-klasse handelt.

Natürlich gibt es auch Ausnahmen. Diese kann man ja mit ganz normalem Catch-Blöcken abhandeln und wenn es dennoch eine Default-Routine wie loggen und Benutzer bescheid geben angestoßen werden kann man ja durch aus das eine tun ohne das andere zu lassen, in anderen Worten in diesem spezialisierten catch-block zusätzlich, wenn geünscht den algemeinen Exceptionhandler aufrufen.
Eine typische Problematik ist, wie oben schon erwähnt eine rollback für einen schreigenden DB-zugriff. Aus meiner Erfahrung sollte man das rollback zusätzlich im catch-Block vor dem MExceptionhandler.handelException(ex) aufrufen. mal ganz abgesehen von einem finally-block der die Connection entweder schließt oder zurück in den Pool bringt.

Interessant, aber aus meiner sich nachvollziehbar, ist die SQL-Exception, obgleich doch ziemlich technisch eine gechekte Ausnahme. Ist ja klar, man kann sich prima und schnell verschreiben im DB-statement, außerdem sind maßnahmen wie connection schließen oder freigeben ziemlich zwingend. Gut ist es also wenn man vom Compiler dann gewarnt wird das man vermutlich was vergessen hat.

Nebenbei erwähnt die Thematik AOP (Aspekt-Orientiertes-Programmieren) wird furchtbar gerne für Logging und Exceptionhandling angeführt. Aber das sind techniken, die aus meienr sicht eher noch in den Kinderschuhen stecken und auch ziemlich gewöhnungsbedürftig sind. wenn ich AOP richtig verstehe übernimmt es mittels einer Art-Precomplier das suchen und ersetzen im Sourcecode bezüglich immer wiederkehrender Aspekte wie z.B. Logging und Exceptionhandling, aber dies ist sicher einer anderes Thema für einen neuen Thread

Takidoso
 
Hallo!

Ja da scheiden sich vermutlich die Geister...
Also zunächst mal ist es so, dass eine Ausnahme zu 95 % immer eines bedeutet:
Abbruch der fachlichen Funktionalität.
...So so, und eine NoSuchItemException oder eine StockIsEmptyException ziehen keine weitere
fachliche Logik nach sich? (Ob das die 5% sind haengt von der Implementierung deiner Business Logic ab) ;)

Die Frage ist wie reagiert man darauf. Allgemein ist es so ziemlich immer das gleiche...
Fehler irgendwo protokolieren (z.b. trace-Stack in ein log) Wenn es sich um eine anwendung mit GUI handelt Meldung and den User (z.B. mittels Pop-up-Dialog)
eventuell Daten in einen definierten konsistenten Zustand bringen (kommt meist bei DB-Anwendungen zum tragen und kann aus meiner Sicht als etwas spezielles angesehen werden).
Ob man das so Verallgemeinern kann...? Das obligatorische Logging des Fehlers macht ja in der Regel
durchaus Sinn, manchmal muss man jedoch auch andere Systeme ueber den Fehler informieren, Transaktionen
zurueckrollen, die Datenbankverbindung neu Aufbauen, Session Daten auf dem FileSystem persistieren etc.
Schon klar, dass solche Standardaktionen wie logging leicht zu zentralisieren sind, dass ist jedoch nur die
halbe Miete ;)

Eine typische Problematik ist, wie oben schon erwähnt eine rollback für einen schreigenden DB-zugriff.
Aus meiner Erfahrung sollte man das rollback zusätzlich im catch-Block vor dem
MExceptionhandler.handelException(ex) aufrufen. mal ganz abgesehen von einem finally-block der die
Connection entweder schließt oder zurück in den Pool bringt.
Gibts bei der Arbeit mit JDBC nicht das ungeschriebene Gesetz, dass eine Connection die eine Exception
hervorgebracht hat direkt wegzuwerfen (zu schliessen) und NICHT wieder neu zu verwenden ist?

Nebenbei erwähnt die Thematik AOP (Aspekt-Orientiertes-Programmieren) wird furchtbar gerne für Logging und
Exceptionhandling angeführt. Aber das sind techniken, die aus meienr sicht eher noch in den Kinderschuhen
stecken und auch ziemlich gewöhnungsbedürftig sind. wenn ich AOP richtig verstehe übernimmt es mittels
einer Art-Precomplier das suchen und ersetzen im Sourcecode bezüglich immer wiederkehrender Aspekte wie
z.B. Logging und Exceptionhandling, aber dies ist sicher einer anderes Thema für einen neuen Thread
Na ja, ich wuerde sagen AOP steckt alles andere als noch in den Kinderschuhen (die Technik gibts uebringens
schon seit mehr als 6 Jahren...) AOP ist extrem nuetzlich und vereinfacht und beschleunigt die Entwicklung
von Software-System ungemein und hilft einige Unzulaenglichkeiten der OOP auszumerzen... Weiterhin ist fuer
AOP kein Precompiler notwendig. Dafuer gibts schon genuegend entsprechende Konzepte (Modifizierter Compiler
(CompileTime Weaving), Modifizierter ClassLoader (LoadTime Weaving), Dynamic Proxies (JDK Proxies, CGLib Proxies...)
(Runtime Weaving) etc.) Meine Meinung ist, dass Entwickler die heutzutage die Moeglichkeiten von AOP ignorieren oder
verniedlichen die Zeichen der Zeit noch nicht erkannt haben. AOP wird in Zukunft eine entscheidende Rolle bei der
Entwicklung von Software spielen (und tut es auch schon jetzt ;-).
Ich empfehle jedem Entwickler der halbwegs professionell rueberkommen will sich auf jeden Fall ernsthaft mit
AOP auseinander zu setzen.
...also an deiner Stelle wuerde ich mir AOP auf jeden Fall nochmal anschauen...
Es gibt Zahlreiche Frameworks (AspektJ, JBoss AOP, Spring AOP) mit denen sich AOP ganz einfach verwenden laesst.
Insbesondere das Springframework macht exzessiv Gebrauch von den schicken Moeglichkeiten von AOP.
(Und jetzt gehts erst richtig rund, nachdem der AspectJ Head Adrian Coyler von IBM zu Interface 21 gewechselt ist ;)

@takidoso, ist natuerlich nicht boes gemeint :)

Gruss Tom
 
Mit AOP in den Kinderschuhen meinte ich lediglich, dass es bisher noch nicht so arg verwendet wird, zumindest wenn man sich Stellenanzeigen durchliest. Und bisher habe ich es in der Praxis zumindest in den Firmen wo ich tätig war noch nie angetroffen. Ansonsten hast Du natürlich recht AOP ist etwas was sicherlich eine große Zukunft haben wird.

bezüglich ungeschriebenen Gesetz in JDBC .... also das ist mir noch nicht bekannt gewesen, und ich vermute mal wenn man ein Connectionpooling verwendet, ich muss zugeben darin keinerlei praktische Erfahrung zu haben, würde das Connectionpooling-framework alle notwendigkeiten übernehmen, zumindest hätte ich es mal so in meiner Phantasie mal so angenommen bzw erwarten.

Aber wie gesagt ... es kommt vermutlich immer auf die Komplexität an und auf die Konzeption eines Systems. Es gibt auch Discusionen darüber mit Exceptionhandling möglichst keinen großartigen fachlichen Programmfluß zu veranstalten.

Und wenn igendwas nicht im Stock ist .... also für mich wäre das lediglich ein abbrechen der Unterfunktionalität und eine Meldung an den User sofern das damit gemeint ist, dass etwas Bestelltes gerade nicht vorrätig sei.

Takidoso
 
Hallo!

Mit AOP in den Kinderschuhen meinte ich lediglich, dass es bisher noch nicht so arg verwendet wird, zumindest wenn man sich Stellenanzeigen durchliest. Und bisher habe ich es in der Praxis zumindest in den Firmen wo ich tätig war noch nie angetroffen. Ansonsten hast Du natürlich recht AOP ist etwas was sicherlich eine große Zukunft haben wird.
Ich weis von einigen (grossen) Firmen dass es mittlerweile recht exzessiv verwendet wird ;-)


Aber wie gesagt ... es kommt vermutlich immer auf die Komplexität an und auf die Konzeption eines Systems. Es gibt auch Discusionen darüber mit Exceptionhandling möglichst keinen großartigen fachlichen Programmfluß zu veranstalten.
Schon klar. Ich denke, dass damit aber eher gemeint ist, dass man fachliche Logik nicht durch technische
Ausnahmen steuern lassen sollte... und nicht überhaupt keine Exceptions für Anwendungslogik zu verwenden. Ich schaue mir bei solchen Fragen immer Code (Beispielanwendungen) von "richtig" guten Entwicklern an ... Martin Fowler, den Spring Jungs, JBoss Team, ein paar lokale Java Gurus und natürlich Mr. Java Specialist Heinz Kabutz, etc. ich denke man lernt am meisten wenn man solchen Experten "virtuell" über die Schulter schaut.

Und wenn igendwas nicht im Stock ist .... also für mich wäre das lediglich ein abbrechen der Unterfunktionalität und eine Meldung an den User sofern das damit gemeint ist, dass etwas Bestelltes gerade nicht vorrätig sei.
Na ja, neben einer Meldung an den User könnte ein entsprechendes System beispielsweise in einem anderen
Lager nachschauen oder etwa ein Fremdsystem kontaktieren und die Bestellung dort vornehmen, oder die
Bestellung vorvermerken etc. Wie gesagt dass kann man dann je nach System beliebig Ausbauen.

Gruss Tom
 
Thomas Darimont hat gesagt.:
Hallo!


Ich weis von einigen (grossen) Firmen dass es mittlerweile recht exzessiv verwendet wird ;-)
Sicher wird es irgendwo genutzt, sonst wäre es sicher sinnlos so etwas zu entwickeln. aber Es ist halt noch lange nicht bei allen angekommen. Ich denke es verhält sich mit AOP ähnlich, wenn auch sicherlich schneller, wie mit der Objektorientierung, die gibt es schließlich auch schon seit dne 70'ern. Ende der 80 griff sie dann mehr um sich, und Mitte der 90 wollten alle objektorientiert Entwickeln auch wenn in manchen Betieben leider das Prozedurale noch nicht wirklich gelebt wurde. (Ich rede da natürlich aus eigener subjektiver Erfahrung und hatte es damals vorrangig mit Assemblerprogrammierung für Anwendungsentwicklung zu tun) Von den 4 Betrieben in denen ich gearbeitet habe waren 3 davon mit Java-Entwicklung behaftet AOP wurde noch nicht einmal in den Mund genommen.

Thomas Darimont hat gesagt.:
Schon klar. Ich denke, dass damit aber eher gemeint ist, dass man fachliche Logik nicht durch technische
Ausnahmen steuern lassen sollte... und nicht überhaupt keine Exceptions für Anwendungslogik zu verwenden. Ich schaue mir bei solchen Fragen immer Code (Beispielanwendungen) von "richtig" guten Entwicklern an ... Martin Fowler, den Spring Jungs, JBoss Team, ein paar lokale Java Gurus und natürlich Mr. Java Specialist Heinz Kabutz, etc. ich denke man lernt am meisten wenn man solchen Experten "virtuell" über die Schulter schaut.


Na ja, neben einer Meldung an den User könnte ein entsprechendes System beispielsweise in einem anderen
Lager nachschauen oder etwa ein Fremdsystem kontaktieren und die Bestellung dort vornehmen, oder die
Bestellung vorvermerken etc. Wie gesagt dass kann man dann je nach System beliebig Ausbauen.

Gruss Tom

Beispielcode anzuschauen kann auf jedenfall nicht schaden, das stimmt! Jedoch halte ich es mit dem Einsatz von Exceptions so, dass es für mich wirklich nur Ausnahmen sind. Sinn solcher ist nämlich vorrangig den eigetnlich fachlichen Code verständlicher und kürzer zu halten und nicht, wie es früher ohne Exceptionhandling, mittels Returncode rückgabe und vielen Fallunterscheidungen auch auf technisches zu reagieren.
Wenn man aber nun dazu neigt Geschäftslogik mit Exceptions zu steuern, ist das nicht nur ausführungstechnisch etwas langsamer sondern macht den Code für Dritte auch nicht sonderlich lesbarer.
Anderseits ist es sicher letztlich nur eine Stilfrage bzw Gewöhnungssache.

Takidoso
 
Zurück