Hi, was ist eigentlich besser an "try - catch", bei Prüfung von Ausnahmebehandlungen bei User-Eingaben, als an einem "if - else"?
try-catch kann ohne Probleme auf hoehere Codeebenen weiter geleitet werden. Du musst dafuer nicht in jeder aufrufenden Funktion eine Behandlung des Problems einbauen, sondern kannst es direkt auf der obersten Aufrufebene behandeln. if-else erwartet dagegen mehr Schreibarbeit und Verwaltung beim Aufruf.
Der Lesbarkeit des Codes zuliebe sollten Exceptions m.M.n. hauptsächlich zur Behandlung von Ausnahmesituationen eingesetzt werden, nicht aber zur Steuerung des allgemeinen Kontrollflusses. Ein User, der Unfug eingibt, ist keine Ausnahmesituation, sondern zu erwarten. Behandeln Programmierer derartige Situationen (wie auch das Ausfallen des Netzwerks o.ä.) wie einen Ausnahmezustand, merkt man das dem resultierenden Programm oft an seiner mangelnden Robustheit an. ;-)
Stimme setjmp voll zu: Ausnahme <-> erwartetes Verhalten. Aber Deine Frage müsste eigentlich "Throw oder if-then-else" lauten. Das try-catch findet ja eine Ebene weiter 'oben' statt. Ausnahmebehandlungen sind teuer, deshalb sollten sie nicht für alles eingesetzt werden, nur für "alles, was das Programm an der Stelle nicht lösen kann". Beispiel: Dein Parser, der einen Dateiinhalt verarbeitet (Stream) bekommt eine I/O Exception. Die wird er wohl weiterwerfen, da er nix mit Dateifehlerhandling zu tun hat und auch nichts Sinnvolles tun kann. (Okok, den Parser komplett von IO/Streams zu befreien wäre noch sauberer). Manch einer fängt auch gern mal alle Exception und schreibt dann im besten Fall noch einen Fehler ins Log, das ist aber nicht Sinn von Exceptions...
Tobias K. schrieb: > Ausnahmebehandlungen sind teuer, deshalb sollten sie nicht für alles > eingesetzt werden, nur für "alles, was das Programm an der Stelle nicht > lösen kann". Da unterliegst Du einem allgemeinen Irrtum. Nicht die Behandlung von Ausnahmen ist per se teuer, sondern das Erzeugen der Exception-Objekte kostet richtig viel Zeit. Gruß Markus
Markus Volz schrieb: > Tobias K. schrieb: >> Ausnahmebehandlungen sind teuer, deshalb sollten sie nicht für alles >> eingesetzt werden, nur für "alles, was das Programm an der Stelle nicht >> lösen kann". > > Da unterliegst Du einem allgemeinen Irrtum. Nicht die Behandlung von > Ausnahmen ist per se teuer, sondern das Erzeugen der Exception-Objekte > kostet richtig viel Zeit. Habt ihr da mal Zahlen, was ist denn "richtig teuer" und "kostet richtig viel Zeit"? Eine Exception ist genau das was das Wort sagt. Eine nicht normale Bedingung, die eben auch nicht normal verarbeitet werden kann. In den meisten Fällen führt so eine Bedingung zum Abbruch dessen was das Programm gerade tut, oder es ist sogar ein fataler Programmierfehler, und genau so sollten Exceptions benutzt werden. Beispiele I/O Error, DB Error, Division durch Zero, Null Pointer Exception, Cast Exception, Konvertierfehler (String in Zahl), ... Und in den Fällen ist die Performance genau wie bei benutzereingaben das allerletzte was wichtig ist. Tobias K. schrieb: > Manch einer fängt auch gern mal alle Exception und schreibt dann im > besten Fall noch einen Fehler ins Log, das ist aber nicht Sinn von > Exceptions... Was willst du sonst tun, wenn die Datei nicht da ist, die Datenbank einen Fehler wirft, der Parser sagt das XML ist fehlerhaft? Ein Back office Programm oder ein Daemon kann schlecht den User fragen.
:
Bearbeitet durch User
Udo Schmitt schrieb: > Eine Exception ist genau das was das Wort sagt. Eine nicht normale > Bedingung, die eben auch nicht normal verarbeitet werden kann. In den > meisten Fällen führt so eine Bedingung zum Abbruch dessen was das > Programm gerade tut, oder es ist sogar ein fataler Programmierfehler, > und genau so sollten Exceptions benutzt werden. Wuerde ich auch so sagen. Steht im Flussdiagramm nicht, dass der Benutzer mehrfach abgefragt werden soll (bis es ein richtiges Ergebnis gibt), dann ist es eine Ausnahme im Ablauf, die entsprechend behandelt werden sollte.
Udo Schmitt schrieb: > Habt ihr da mal Zahlen, was ist denn "richtig teuer" und "kostet richtig > viel Zeit"? Ich habe das unter C# mal mit einem Profiler angeschaut und festgestellt, dass das erstmalige Erzeugen einer Exception tatsächlich im Bereich einiger hundert Millisekunden gedauert hat. Die betreffende Assembly war zu diesem Zeitpunkt bereits geladen. Wenn man sich vor Augen hält, was eine aktuelle CPU im 500 ms so alles erledigen kann, auch unter .NET, wird einem die Tragweite von 100 ms für das Erzeugen einer Exception erst richtig klar. So ein Test hängt natürlich stark von den Begleitumständen ab, zeigt aber, dass es ratsam ist, das Erzeugen von Exceptions im normalen Programmfluss zu vermeiden und möglichst viele Fälle durch die Programmlogik zu erledigen. Grüße Markus
Markus Volz schrieb: > Ich habe das unter C# mal mit einem Profiler angeschaut und > festgestellt, dass das erstmalige Erzeugen einer Exception tatsächlich > im Bereich einiger hundert Millisekunden gedauert hat. Sorry aber das glaube ich nicht. Ich glaube dir gerne daß der Profiler mehrere 100ms angezeigt hat, aber das ist definitiv nicht das Erzeugen der Exception. Das war eher der Versuch der API Funktion oder was auch immer ein Problem noch zu lösen bevor eine Exception erzeugt wird, z.B. durch warten und wiederholen. Was war das für eine Excetion? File IO oder TCP/IP oder Datenbank würde passen, einfach weil da auf externe Peripherie gewartet wird bis zu einem Timeoput. Versuch mal eine Konvertierexception (z.B. nichtnumerischer String in Integer konvertieren) in einer Schleife zu programmieren, da wirst du sehen, daß du zumindest 100000 oder gar Millionen von Exceptions pro Sekunde erzeugen und wieder fangen kannst.
>Versuch mal eine Konvertierexception (z.B. nichtnumerischer String in >Integer konvertieren) in einer Schleife zu programmieren, da wirst du >sehen, daß du zumindest 100000 oder gar Millionen von Exceptions pro >Sekunde erzeugen und wieder fangen kannst. Weil die "branch predection" anspringt... Gruß Jonas
Udo Schmitt schrieb: > Habt ihr da mal Zahlen, was ist denn "richtig teuer" und "kostet richtig > viel Zeit"? Ich habe mal unter C# schön gesehen, was Try/Catch verursacht. (bei falscher Verwendung) Leider gelang mir eine Abfrage auf eine Datenbank nicht so, wie ich es wollte - ich brauchte aber schnell eine Lösung, die funktioniert. Also habe ich einfach iterativ auf die Datenbank zugegriffen und jedesmal, wenn die Abfrage (wurde dynamisch als string erzeugt) schief ging, hab ich das mit dem catch gefangen und nichts getan. Das hat zumindest mal funktionell das gewünschte Ergebnis gebracht. Also ca:
1 | for(int i = 0; i < nCount; i++) |
2 | {
|
3 | try
|
4 | {
|
5 | // Datenbankabfrage ausführen
|
6 | }
|
7 | catch
|
8 | {
|
9 | // nichts tun und weiter in for - Schleife
|
10 | }
|
11 | }
|
Diese Schleife wurde 50 mal durchlaufen und davon bin ich ca 45 mal im Catch gelandet. Das ganze hat 3-5 Sekunden gedauert - trotz dass die DB (Access) lokal am Rechner lief. Dieselbe Abfrage hat dann in den nächsten Tage, als ich eine saubere Lösung fand, naja - praktisch nichts mehr gedauert :)
Tobias K. schrieb: > wie sah denn die saubere Lösung aus? > > Grüße,tk Prinzipiell geht es darum, dass eine Tabelle wie eine Matrix betrachtet wird. Die Spalten stellen Werte dar, zu denen Zeilenwerte aus Spalte 1 gehören. Also eine Zuordnungsmatrix. (steht im Feld ein "x", ist die Zuordnung gültig) Werte A B C D . . . Wert1 x x Wert2 x x x Wert3 . . . Ich hole mir dann die entsprechende Zeile, indem ich die erste Spalte dort selektiere, wo der Wert dem Suchwert entspricht. (z.B. Wert2) Dann suche ich iterativ alle Spalten durch, ob am entsprechenden Index ein "x" steht - dies sind dann die in dem Fall gültigen Einträge. Zuerst hatte ich die Werte A,B,.. als Spaltennamen (Liste war aus MSExcel importiert) und führte iterativ über alle Spaltennamen einen SELECT aus, der halt, da immer nur eine Spalte gesucht war, zu 95% ins catch krachte. Ich hoffe, das ist so halbwegs verständlich. :)
:
Bearbeitet durch User
Daniel V. schrieb: > Ich hoffe, das ist so halbwegs verständlich. :) Ein wenig unklar ist, warum du in SQL-Exceptions läufst, statt nur ein leeres Ergebnis zurückzubekommen. Das hört sich irgendwie nach ungünstigem DB-Aufbau an.
bluppdidupp schrieb: > Daniel V. schrieb: >> Ich hoffe, das ist so halbwegs verständlich. :) > > Ein wenig unklar ist, warum du in SQL-Exceptions läufst, statt nur ein > leeres Ergebnis zurückzubekommen. Das hört sich irgendwie nach > ungünstigem DB-Aufbau an. genau das war der Fall ( siehe letzte Zeile aus meinem letzten Post: Zuerst hatte ich die Werte A,B,.. als Spaltennamen (Liste war aus MSExcel importiert) und führte iterativ über alle Spaltennamen einen SELECT aus, der halt, da immer nur eine Spalte gesucht war, zu 95% ins catch krachte.) Ich habe dann die Spaltennamen wieder, wie es Access default mäßig macht, mit Laufzähler erhöht (Field1....Fieldn) und die Namen, die ich zuerst hatte, in die erste Zeile geschoben. Dann hat's hingehauen. Es sollte auch angemerkt werden, dass das mein erstes Porjekt war, bei dem ich eine Datenbank verwendet habe. Würde ich jetzt nochmal beginnen, wäre da einiges anders :)
Udo Schmitt schrieb: > Habt ihr da mal Zahlen, was ist denn "richtig teuer" und "kostet richtig > viel Zeit"? Hier ist ein Artikel von jemand der entsprechende Messungen gemacht hat, allerdings für C++ und in Bezug auf Game Engines. http://www.gamearchitect.net/Articles/ExceptionsAndErrorCodes.html Die Quintessenz: Ja, Exceptions sind "teurer" als eine if-else-Fehlerbehandlung, aber das fällt wirklich nur bei High-Performance-Anwendungen ins Gewicht und nicht bei alltäglichen Programmieraufgaben.
...bleiben aber trotzdem "Ausnahmen". Wenn ich was mit "if" prüfen kann, dann erwarte ich das ja schon als Möglichkeit. Was hier im Thread ein wenig in den Hintergrund gerückt ist: Exceptions beinhalten eine genaue Fehlerbeschreibung, den Stacktrace und ich kann sie weiterwerfen oder neu verpacken, je nach dem, was ich an der Stelle machen kann. Wie oft hab ich schon Frickel-Magic-Numbers als returnvalues gesehen :rolleyes: Trotzdem ersetzen Exceptions keine Fehlerantizipation ( z.B. mit if), sind also eigentlich nicht vergleichbar (oder gar "besser"), um mal auf den TE einzugehen, sondern halt für einen anderen Zweck gedacht. Ganz banal: if und try ergänzen sich. tk
@Daniel es ist noch kein Meister vom Himmel gefallen ;) Tipp: lass die Spalten auf jeden Fall stabil und Speicher alles in die gleiche Tabelle. Das gefällt einem richtigen DBMS (nicht Access) besser und ist dann auch mindestens so performant und genauso flexibel. Konkret: zwei Spalten für die "Koordinate", dritte für den Wert. Je nach DBMS kannst Du auf sowas direkt so arbeiten, wie mit der von Dir genannten. tk
Tobias K. schrieb: > Konkret: zwei Spalten für die "Koordinate", dritte für den Wert. Je nach > DBMS kannst Du auf sowas direkt so arbeiten, wie mit der von Dir > genannten. Danke für den Tipp. Die Anforderung ergab sich, hätte ich ja gleich detaillierter beschreiben können, daraus, dass ich Ersatzteile Maschinen zuordne. Natürlich können verschiedene Ersatzteile verschiedenen Maschinen zugeordnet werden - aber eben nur einigen von vielen. Eine Tabelle, die hunderte Ersatzteile ca 50 Maschinen zuordnet, wäre ein immenser Einpflegungsaufwand mit zwei "Koordinatenspalten" (wenn ich dich richtig verstehe) gewesen und dem wollte ich entfliehen, da es die eine Matrix in Excel schon gab.....
Ah. verstehe - diese Anforderungen aus der Officewelt kenne ich nur zu gut. OT: Hier wäre mein Ansatz ein Excel-Makro, das die Koordinaten ermittelt und den Wert dazu. Damit trennst du dann Repräsentation/Eingabe und Speicherung. Grüsse, tk
Tobias K. schrieb: > Trotzdem ersetzen Exceptions keine Fehlerantizipation ( z.B. mit if), > sind also eigentlich nicht vergleichbar (oder gar "besser"), um mal auf > den TE einzugehen, sondern halt für einen anderen Zweck gedacht. Naja. Zumindest in C++ kann man dank RAII so programmieren, dass Funktionen Exception-sicher (d.h. Exceptions verursachen keinen ungültigen Zustand) sind, ohne eine Unmenge try-catch oder if-else einzubauen, sondern oft lediglich durch "richtige" Anordnung der Anweisungen und ein paar temporäre Variablen mehr. Wird zB bei den Containern der stdlib so gemacht; wenn die eine Funktion (zB Copy-Constructor) eines enthaltenen Elements aufrufen und die eine Exception wirft, ist der Container danach immer noch in einem konsistenten Zustand und kann "sauber" zerstört werden. Typischerweise hat man nur sehr wenige try-catch-Blöcke, die sich dann hauptsächlich auf der höchsten Ebene - dort wo man den Benutzer benachrichtigen kann - befinden. Das erlaubt einen übersichtlichen Code der nicht völlig in der Fehlerbehandlung versinkt wie das bei exceptionlosem C-Code gerne mal ist.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.