<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.aspnetzone.de/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Architektur' and 'Exception Handling'</title><link>http://www.aspnetzone.de/search/SearchResults.aspx?o=DateDescending&amp;tag=Architektur,Exception+Handling&amp;orTags=0</link><description>Search results matching tags 'Architektur' and 'Exception Handling'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61120.2)</generator><item><title>Best Practices: Fehlerbehandlung</title><link>http://www.aspnetzone.de/blogs/juergengutsch/archive/2010/08/19/best-practices-fehlerbehandlung.aspx</link><pubDate>Thu, 19 Aug 2010 08:42:00 GMT</pubDate><guid isPermaLink="false">ce930855-ae9b-4fa4-8077-06a76071cc6a:218527</guid><dc:creator>Jürgen Gutsch</dc:creator><description>&lt;P&gt;In der Vergangenheit habe ich in vielen Projekten, vielen Anwendungen und auch hier im Forum immer wieder die gleichen Fehler bei der Fehlerbehandlung gesehen, was mich dazu veranlasst diesen Beitrag hier zu schreiben.&lt;/P&gt;
&lt;P&gt;Im Grunde ist es immer folgender Fehler der beim Try&amp;amp;Catch gemacht wird:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;{ &lt;br /&gt;    [&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;do&lt;/span&gt; some errors] &lt;br /&gt;} &lt;br /&gt;Catch (Exception ex) &lt;br /&gt;{ &lt;br /&gt;    log.Error(“Meine super duper Fehlermeldung”); &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; ex; &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Das ist dann keine Fehlerbehandlung, sondern eher Fehler verstecken!&lt;/P&gt;
&lt;P&gt;Oftmals wird dieses Konstrukt (“Fehlerbehandlung” mochte ich es nicht nennen) in jeder Methode genutzt die aufgerufen wird. Das hat dann den Effekt, dass dieses Konstrukt logisch wie folgt verschachtelt wird:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;{ &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;    { &lt;br /&gt;        &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;       { &lt;br /&gt;            &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;           { &lt;br /&gt;                [&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;do&lt;/span&gt; some errors] &lt;br /&gt;          } &lt;br /&gt;           Catch (Exception ex) &lt;br /&gt;            { &lt;br /&gt;                log.Error(“Meine erste super duper Fehlermeldung”); &lt;br /&gt;                &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; ex; &lt;br /&gt;           } &lt;br /&gt;       } &lt;br /&gt;        Catch (Exception ex) &lt;br /&gt;        { &lt;br /&gt;            log.Error(“Meine zweite super duper Fehlermeldung”); &lt;br /&gt;           &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; ex; &lt;br /&gt;       } &lt;br /&gt;    } &lt;br /&gt;    Catch (Exception ex) &lt;br /&gt;    { &lt;br /&gt;       log.Error(“Meine dritte super duper Fehlermeldung”); &lt;br /&gt;        &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; ex; &lt;br /&gt;    } &lt;br /&gt;} &lt;br /&gt;Catch (Exception ex) &lt;br /&gt;{ &lt;br /&gt;    log.Error(“Meine vierte super duper Fehlermeldung”); &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; ex; &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Oftmals wird wenigstens die aktuelle Exception dem Logger übergeben:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;Catch (Exception ex) &lt;br /&gt;{ &lt;br /&gt;    log.Error(“Meine vierte super duper Fehlermeldung”, ex); &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; ex; &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Aber auch das ist nur die halbe Miete.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Was soll da falsch sein ?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Schauen wir uns nochmal das erst Stück Code an. Angenommen es passiert ein Fehler und das Programm, springt in den Catch-Teil. Jetzt geht der Unsinn los:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Es wird eine Unsinnige Fehlermeldung ausgegeben! &lt;BR&gt;Warum? &lt;BR&gt;Falls die Meldung noch relevant sein sollte, enthält sie keine weiteren Informationen zu der eigentlichen Exception. Im Normalfall wurde der Code allerdings im Laufe der projektphase immer wieder geändert, was zur Folge hat, das die Nachricht längst nicht mehr stimmt oder es gibt inzwischen mehrere mögliche Fehlerquellen. 
&lt;LI&gt;throw ex ist der nächste grobe Fehler: es wird zwar die selbe Exception noch einmal geworfen, mit der selben Fehlermeldung, allerdings wird der immens Wichtige StackTrace abgeschnitten (“breaking the stack”). Der StackTrace beginnt ab der Methode in der throw ex aufgerufen wird. Sollte der Fehler in einer aufgerufenen Komponente auftauchen, kann das nicht mehr ermittelt werden. Es wird immer so aussehen, als wäre der Fehler in der aktuelle Methode aufgetreten, und zwar genau dort, wo thro ex aufgerufen worden ist. Genauso wie der StackTrace geht auch die InnerEception verloren (Danke an &lt;A href="http://aspnetzone.de/blogs/peterbucher/default.aspx"&gt;Peter&lt;/A&gt; für den Hinweis.)
&lt;LI&gt;Selbst wenn die Exception an den Logger übergeben wird ist die Fehlerbehandlung unvollständig, denn es wird nur ein unvollständiger StackTrace gelogt. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Im Falle der verschachtelten Try&amp;amp;Catches sieht das so aus, dass 1. keine relevanten Fehlerinformationen geloggt werden und 2. jedes Mal der StackTrace bei jedem Catch von neuem beginnt.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Diese Fehlerbehandlung ist somit keine, sondern eine Selbsttäuschung.&lt;/STRONG&gt; &lt;/P&gt;
&lt;P&gt;Das wird man spätestens dann merken, wenn man als Entwickler vom Support die Meldung über einen Fehler bekommt und dann das Log-File analysieren muss. Ich wette das viele Fehler nicht per Log-File gefunden werden können.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Was ist zu tun?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Im ersten Schritt sollten alle throw ex Aufrufe durch ein einfaches throw ersetzt werden. Das führt dazu, dass die aufgetretene Exception genau so wie sie ist, nach “oben” weitergeleitet wird. Dann sollte das Logging angepasst werden: Bei einem einfachen Try&amp;amp;Catch sollte das Logging – wenn möglich – so geändert werden, dass die Exception an den Logger übergeben wird (Die meisten Logger sollten das Unterstützen):&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;{ &lt;br /&gt;    [&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;do&lt;/span&gt; some errors] &lt;br /&gt;} &lt;br /&gt;Catch (Exception ex) &lt;br /&gt;{ &lt;br /&gt;    log.Error(ex); &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt;; &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Im Fall der Verschachtelten Try&amp;amp;Catches wird nun noch an jeder Stelle in das Log geschrieben. Das ist nicht sinnvoll, das dadurch das Log sehr groß werden kann und die Informationen mehrfach im Log vorhanden sind. Es sollte also nur an einer Stelle geloggt werden und zwar am besten ganz oben, beim letzten Try&amp;amp;Catch. &lt;/P&gt;
&lt;P&gt;In ASP.NET kann das sogar in der global.asax bei Application_Error gemacht werden.&lt;/P&gt;
&lt;P&gt;Die verschachtelten TryCatches sehen dann logisch wie folgt aus:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;{ &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;    { &lt;br /&gt;        &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;       { &lt;br /&gt;           &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;try&lt;/span&gt; &lt;br /&gt;           { &lt;br /&gt;                [&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;do&lt;/span&gt; some errors] &lt;br /&gt;           } &lt;br /&gt;           Catch (Exception ex) &lt;br /&gt;           { &lt;br /&gt;                &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt;; &lt;br /&gt;           } &lt;br /&gt;        } &lt;br /&gt;        Catch (Exception ex) &lt;br /&gt;        { &lt;br /&gt;           &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt;; &lt;br /&gt;        } &lt;br /&gt;    } &lt;br /&gt;    Catch (Exception ex) &lt;br /&gt;    { &lt;br /&gt;        &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt;; &lt;br /&gt;    } &lt;br /&gt;} &lt;br /&gt;Catch (Exception ex) &lt;br /&gt;{ &lt;br /&gt;    log.Error(ex); &lt;br /&gt;    HandleTheException(); &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Im letzten Catch wird dann die eigentliche Fehlerbehandlung gemacht: Es wird dem Benutzer eine sinnvolle Meldung ausgegeben (Nicht die Fehlermeldung, mit der kann der Benutzer nichts anfangen!)&lt;/P&gt;
&lt;P&gt;Nach diesem Refactoring, sollte man sich&amp;nbsp; fragen welche Try&amp;amp;Catches dann noch Sinn machen, wen nichts anderes Passiert, als die Exceptions durchzureichen. Ich bin ganz sicher, dass man einige nun Entfernen könnte.&lt;/P&gt;
&lt;P&gt;Generell sollte man nicht grundlos alle möglichen Fehler abfangen, sondern in erster Linie Fehler vermeiden. Natürlich gibt es Stellen, bei denen man Fehler nicht Verhindern kann, das ist immer dann der Fall, wenn man aus seiner Anwendung raus auf etwas zugreift: Datenbank und Dateizugriffe, Web- und Webservice-Zugriffe, COM, etc.&lt;/P&gt;
&lt;P&gt;Auf diese Art hat man nun schon mal eine relativ saubere Fehlerbehandlung. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Aber es geht immer noch besser:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;An Stellen, an denen mögliche Fehler nicht verhindert werden können, können diese abgefangen und mit einer eigenen Exception nach “oben” weitergeben werden. Die ursprüngliche Exception wird dabei als InnerException mitgegeben:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;Catch (Exception ex) &lt;br /&gt;{ &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;throw&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;new&lt;/span&gt; MyVeryOwnHttpException(ex) &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;So kann man in der Darstellungsschicht individuell auf die Fehler reagieren und dem Benutzer einen entsprechenden Hinweis geben:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 14px;font-weight: normal;"&gt;Catch (MyVeryOwnHttpException ex) &lt;br /&gt;{ &lt;br /&gt;    log.Error(ex.InnerException); &lt;br /&gt;    HandleTheVeryOwnHttpException(“Die Verbindung zum Server konnte nicht hergestellt werden.\n Bitte prüfen Sie ob Sie mit dem Internet Verbunden sind.\nUnd so weiter und so fort”, ex); &lt;br /&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Man kann so spezielle Arten von Ausnahmen zusammenfassen und entsprechend drauf reagieren. Es ist dem Anwender in der Regel egal, was der genaue Fehler ist. Ob das jetzt ein Verbindungsfehler ist oder der Server einen Fehler zurückgibt ist egal. Wichtig ist, dass in diesem Fall die Anwendung nicht mit dem Server kommunizieren kann.&lt;/P&gt;
&lt;P&gt;In der Log-File steht auf jeden Fall der konkrete Fehler mit dem kompletten StackTrace und die Fehlersuche wird dadurch wesentlich vereinfacht.&lt;/P&gt;
&lt;DIV style="TEXT-ALIGN:left;PADDING-BOTTOM:4px;MARGIN:0px;PADDING-LEFT:4px;PADDING-RIGHT:4px;PADDING-TOP:4px;" class=wlWriterHeaderFooter&gt;&lt;A href="http://dotnet-kicks.de/kick/?url=http://www.aspnetzone.de/blogs/juergengutsch/archive/2010/08/19/best-practices-fehlerbehandlung.aspx"&gt;&lt;IMG border=0 alt="DotNetKicks-DE Image" src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http://www.aspnetzone.de/blogs/juergengutsch/archive/2010/08/19/best-practices-fehlerbehandlung.aspx&amp;amp;bgcolor=3169AD&amp;amp;fgcolor=FFFFFF&amp;amp;border=000000&amp;amp;cbgcolor=D4E1ED&amp;amp;cfgcolor=000000"&gt;&lt;/A&gt;&lt;/DIV&gt;</description></item></channel></rss>