| 

.NET C# Java Javascript Exception

3
Ich schreibe gerade eine Server-Basis-Klasse, von der dann jede andere Serverklasse abgeleitet werden soll - deswegen ist die Server-Basis-Klasse auch abstrakt.

Dabei weiß ich nun nicht, ob ich, damit der Code "weiter oben" beim Aufrufer sauberer wird - man vermeidet das gecatche -, Exceptions direkt beim Auftreten behandeln oder sie lieber weitergeben soll, damit der Aufrufer seine eigene Fehler-Nachricht ausgeben kann.

Beispiel des direkten Behandelns:
protected void waitForClientHavingConnected()
{
try
{
client = server.accept();
}
catch (IOException e)
{
System.out.println("Die Verbindung zum Client konnte nicht angenommen werden.");
e.printStackTrace();
}

clientHasConnected = true;
}

Der Vorteil hierbei ist, dass beim Aufrufer jetzt alles sauber ist. Dafür aber wird er immer nur bei Fehlern "Die Verbindung zum Client konnte nicht angenommen werden." lesen können, nicht aber seine eigene Fehler-Meldung oder vielleicht sogar Behandlung.


Beispiel des Weitergebens:
protected void waitForClientHavingConnected() throws IOException
{
client = server.accept();
clientHasConnected = true;
}

Andererseits hat diese Variante den Vorteil, dass ich die Behandlung beim Aufrufer anpassen und eine andere Fehler-Meldung ausgeben kann, aber sie verschleiert den Code extrem.

Sollte ich die Exceptions lieber weitergeben oder sofort behandeln?
21.01.2010
Griever 109 1 2
6 Antworten
1
Also eine feste Regel gibt es nicht, aber eine "Best-Practice": Das Deklarieren von Exceptions im Methodenkopf führt dazu, dass auch aufrufende Methoden die Exceptions weiterdeklarieren. Das resultiert nicht nur in einer gewissen Unübersichtlichkeit (steigt mit Exceptionanzahl), sondern insbesondere auch darin, dass bei Codeänderung die Signaturen aller aufrufenden Methode geändert werden müssen.
Die Lösung sind Runtime-Exceptions, die nicht deklariert werden müssen. Natürlich sollten sie sowohl in dem Methodenkommentar ausführlich dokumentiert werden, als auch mit einer sinnvollen Error-Message versehen sein, sodass ein Aufrufer, der sonst keine Ahnung vom System hat, eine Idee bekommt, was schiefgelaufen ist und wie er das gelöst bekommt.
25.01.2010
LastFreeNickname 316 1 7
Da die EDIT-Funktion nicht funktioniert, nochmal eine Klarstellung: Die Exceptions sollten immer als Runtime-Exceptions weitergeworfen werden. Also:
try{
//...
} catch(IOException e){
// error handling
throw new RuntimeException(e);
}
LastFreeNickname 27.01.2010
1
Du kannst aber auch ein out Parameter benutzen, die Behandlung dabei intern halten, die Nachrichten aber weiterleiten, z.B.:

protected void waitForClientHavingConnected(string outMsg)
{
try
{
client = server.accept();
outMsg = "Alles super.";
}
catch (IOException e)
{
outMsg = "Die Verbindung zum Client konnte nicht angenommen werden.";
// weitere Behandlung hier...
}

clientHasConnected = true;
}


Der Aufruf muss dann so aussehen:

string outMsg;
waitForClientHavingConnected(out outMsg)

Eine andere Variante ware ein Re-Throw. Behandlung intern wie oben, am Ende aber:

throw new Exception("Die Verbindung zum Client konnte nicht angenommen werden.");


Hoffe, es hilft.
22.01.2010
Cosmo 41 2
Auf welche Sprache beziehst du dich? In der Frage ist Java angegeben und da gibt es keine out-Parameter, deshalb funktioniert der angegebene Code da so nicht.
LastFreeNickname 25.01.2010
1
Also meiner Meinung, solltest du jede Exception weitergeben. Du kannst dir natürlich überlegen, ob es Sinn die Exceptions, die geworfen werden in eine eigene Exception-Klasse zu packen.

Warum nun immer werfen?! Grundsätzlich solltest du davon ausgehen, dass die Klassen, die du schreibst wiederverwendest. Nun kann es natürlich sein dass Projekt 1 mit der Exception nichts anfangen kann und die Verarbeitung abbricht. Projekt 2 jedoch schon (baut die Connection neu auf). Da solltest du jetzt auch die Problematik erkennen, wenn du die Exception intern innerhlab der Klasse verarbeitest. Dann hast du bei einer Neuverwendung nämlich keinerleit Einfluss mehr auf das Exception-Handling und musst die Klasse anpassen, was man in der Regel vermeiden sollte.

Um es kurz zusammenzufassen. Ich würde Exceptions entweder so lange wie mgölcih weitergeben. Und sie erst an der Stelle auffangen, wo ich mir sicher sein kann, dass ich die Informationen aus der Exception verarbeiten kann.
24.01.2010
1
Mein Thema...

1. Exceptions, die man behandeln kann oder möchte ---> catchen und behandeln, eventuell weiterwerfen, falls man das Programm an der Stelle nicht komplett in einen konsistenten Zustand zurückzuversetzen kann. (z.B. Rollback bei Transaktionen, die DB ist dann konsistent, aber das Programm???)

2. Exceptions, die man nicht behandeln kann, aber der Aufrufer:
a) innerhalb einer Schicht --> weiterleiten über Signatur, bis man sie behandeln kann, sonst b)
b) Schichtenübergreifend --> in eigene Exception umwandeln und werfen

3. Exceptions, die man nicht behandeln kann oder möchte, der Aufrufer aber auch nicht behandeln kann --> in RuntimeException packen und werfen

4. Programmsituationen, die ein sinnvolles Weiterarbeiten nicht möglich machen --> eine eigene Exception erzeugen und in der Signatur proklamieren.
Eine übliche Situation ist es, wenn man null zurückgeben müsste. (Nur so nebenbei: Nie null übergeben und nie null zurückgeben. Das erspart eine Menge Arbeit und Unsicherheit... Dir und deinem Aufrufer...)

5. Wenn ich weiß, dass eine RuntimeException auftauchen kann, und ich genau diese behandeln möchte oder kann, dann catchen und behandeln.

6. Jede Schicht definiert ihre eigenen sichtbaren Exceptions.

"können" bedeutet: sinnvolle Verarbeitung, ohne dass ein Aufrufer noch irgendetwas machen oder beachten muss, d.h. das Programm wird wieder in einen konsistenten Zustand gebracht.
"möchten" bedeutet: bewusste Entscheidung, die sich auf den Programmablauf begründet.
"catchen und behandeln" bedeutet: Logging alleine ist keine ausreichende Behandlung...
"Schicht": Ähnlich dem ISO-OSI-Referenzmodell in der Netzwerktechnik 1:1 anwendbar auf die Softwareentwicklung
09.02.2011
oopexpert 455 1 8
0
Das Erste gefällt mir nicht so gut, da ich dabei immer extra Variablen und Parameter bereitstellen müsste.

Bei der zweiten Variante müsste ich doch auf beiden Seiten catchen (einmal die IOException und auf der anderen Seite die selbst neugeworfene Exception), oder?
23.01.2010
Griever 109 1 2
0
7. Repacking in eigene Exception, falls man an der aktuellen Stelle mehr Informationen über den Kontext hat, als die abgefange Exception. Diese Information in adäquate Exception packen und werfen. --> Ursachenhierarchie

Tut mir Leid, aber das grundsätzliche Packen in eine RuntimeException empfehle ich nicht. Alle dem aktuell behandelten Thema verwandten Ausnahme sind als sichtbare Exceptions zu deklarieren.
09.02.2011
oopexpert 455 1 8

Stelle deine Java-Frage jetzt!