![]() |
Falsche Verwendung von try...except...end
Viele Programmierer verwenden try...except...end auf eine falsche Weise.
Es gibt mindestens 5 "Sünden", die man begehen kann:
Delphi-Quellcode:
Wenn man obige Sünden nicht begeht, wird man belohnt:
// 1. Sünde
// jede Exception wird komplett verschluckt // Niemand wird je erfahren, warum das Programm nicht funktioniert !!! // dass die Exception.Message in der Delphi IDE angezeigt wird zählt nicht, // denn nach Murphy treten Fehler grundsätzlich beim Endbenutzer auf try MachWas; except end; // 2. Sünde // Exceptions werden abgefangen und als Returncode umgesetzt // niemand wird je erfahren, warum eine Funktion einen Fehlercode liefert try MachWas; except Result := 1; // oder auch Result := False; end; // 3. Sünde // Exception wird abgefangen und mit ShowMessage eine Meldung präsentiert // niemand wird je die wahre Ursache erfahren // in einer Schleife können tausende Meldungen produziert werden try MachWas; except ShowMessage('es ist Fehler in MachWas aufgetreten'); // ShowMessage('Es ist ein Fehler aufgetreten !'; // geht's noch genauer ?? Exit; end; // 3. Sünde B // Manchmal führt die Meldung des Programmierers total in die falsche Richtung try liste.LoadFromFile('C:\autoexec.bat'); liste.Add(...) .... liste.SaveToFile('C:\autoexec.bat'); except // die Meldung kann völlig falsch sein. // eine Exception an dieser Stelle bedeutet nicht, dass die AUTOEXEC.BAT nicht vorhanden ist // dann lieber eine nichtssagende Fehlermeldung, als eine Falsche ShowMessage('C:\AUTOEXEC.BAT nicht gefunden !'); Exit; end; // 4. Sünde // Exception wird abgefangen und die Meldung mit ShowMessage präsentiert // die orginale Exception-Class geht verloren (ein Exception-Objekt kann auch mehr Informationen // tragen als nur eine Message (siehe EOleException); die Infos sind verloren) // in einer Schleife können tausende Meldungen produziert werden // es wird zwar jetzt die richtige Meldung angezeigt, aber wenn man mit Exit zurückkehrt // hätte man das try...except gleich weglassen können try MachWas; except on E:Exception do begin ShowMessage(E.Message); Exit; end; end; // 5. Sünde // try...except wird verwendet, um eine Resource (Speicher, Handles,...) zu schützen // Resourcen werden mit einem Resourceschlutzblock (try...finally) geschützt und nicht // mit einem falsch verstandenem try...except // in folgendem Beispiel wird try..except falsch verwendet sl:=TStringList.create; sl.add('[autorun]'); sl.add('OPEN='+app); sl.add('ICON='+icon); if copy(destfile, length(destfile)-4, 4)<>'.inf' then destfile:=destfile+'.inf'; try sl.SaveToFile(destfile); except result:=false; end; sl.free; // Richtig wäre sl:=TStringList.create; // Resource belegen try // direkt danach folgt das try sl.add('[autorun]'); sl.add('OPEN='+app); sl.add('ICON='+icon); if copy(destfile, length(destfile)-4, 4)<>'.inf' then destfile:=destfile+'.inf'; sl.SaveToFile(destfile); finally sl.Free; // die Resource wird immer freigegeben, egal was passiert end; man kann z.B. Exceptions, die bis an die Oberfläche kommen automatisch in einer Log-Datei speichern oder man kann dem Benutzer zusätzlich einen Hilfe-Button (natürlich kontextsensitiv) anbieten. ![]() Man könnte die Exception-Infos auch per Email zum Programmierer schicken lassen. ("Bug-Report" per EMail) Richtige Verwendung von try...except...end
Delphi-Quellcode:
// in folgendem Beispiel werden Daten aus einer Query gelesen
// Fehler werdem in einem Memo protokolliert und der Lesevorgang geht weiter // es werden keine Informationen unterdrückt, sondern die Fehlermeldungen werden protokolliert while not Query1.Eof do begin try MachWas(Query1); except on E:Exception do begin MemoLog.Lines.Add('Fehler in MachWas'); MemoLog.Lines.Add(E.ClassName+':'+E.Message); MemoLog.Lines.Add('Record: ' +IntToStr(Query1.RecNo); end; Query1.Next; // nächster Datensatz end; end; // in folgendem Beispiel wird eine Exception abgefangen mit Informationen angereichert // und erneut ausgelöst try MachWas(x, y, color); except on E:Exception do // Eception abfangen begin // mit *nützlichen Informationen* anreichern // die Meldung wird mehrzeilig durch #13#10 E.Message := Format('Fehler in MachWas(%d, %d, %d)'#13#10, [x, y, color]) + E.Message; Raise; // Erneut auslösen ! end; end; // Manchmal möchte man wirklich jede Exception unterdrücken try anzahl := StrToInt(EditAnzahl.Text); except anzahl := 1; end; // hier empfiehlt es sich die Exception zu vermeiden if EditAnzahl.Text = '' then anzahl := 1 else begin anzahl := StrToInt(EditAnzahl.Text); end; // Es gibt natürlich noch elegantere Lösungen (StrToIntDefault kann sich jeder selber bauen) anzahl := StrToIntDefault(EditAnzahl.Text, 1); |
Re: Falsche Verwendung von try...except...end
2. ist nicht per se eine Suende.
Besonders in DLLs kann es unbedingt notwendig sein Exceptions zu unterdruecken. Das Beispiel schert sich natuerlich nicht um eine genaue Aufschluesselung der Ursache, aber das muss ja nicht immer noetig sein. (immer diese Shreipfeler) |
Re: Falsche Verwendung von try...except...end
Zitat:
Es gibt noch eine weitere Ausnahme: Programmcode, der von Aussen über eine Automatisierungsschnittstelle aufgerufen wird, muss spezielle Vorkehrungen treffen und darf auch ShowMessage zum Anzeigen benutzen, falls der Client die Exception nicht anzeigen kann. |
Re: Falsche Verwendung von try...except...end
Zitat:
Diese Verwendung sollte keinerlei Auswirkungen auf den Schutz haben, sondern vielmehr einen Funktionswert zurückgeben... Wenn du dich schon beschweren willst, dann schreib wenigstens die ganze Funktion auf!
Delphi-Quellcode:
Natürlich hätte man das Ganze durch try...finally schützen können, aber das hielt ich in dem Fall nicht für nötig! Und im Fall einer Wertezuweisung in einer Funktion ist das hier ebenso falsch, weil eine Sicherung NIE GEPLANT war...
function TForm1.CreateAutorunFile(app, icon, destfile: String): boolean;
var sl: TStringList; begin result:=true; //im Grunde erfolgreich sl:=TStringList.create; //TStringlist erstellen sl.add('[autorun]'); //Zeilen schreiben sl.add('OPEN='+app); //-"- sl.add('ICON='+icon); //-"- if copy(destfile, length(destfile)-4, 4)<>'.inf' then destfile:=destfile+'.inf'; //im Zweifelsfall Endung anhängen try sl.SaveToFile(destfile); //Speicherversuch except result:=false; //Gescheitert? Dann false zurückgeben end; sl.free; //Ressource wieder freigeben end;
Delphi-Quellcode:
EDIT: Wir werden uns das mal merken und machen uns dann über dich lustig... Natürlich auch, wenn du mal vollkommen recht haben solltest! Aber diesmal: :kotz: :lol:
sl:=TStringList.create; // Resource belegen
try // direkt danach folgt das try sl.add('[autorun]'); sl.add('OPEN='+app); sl.add('ICON='+icon); if copy(destfile, length(destfile)-4, 4)<>'.inf' then destfile:=destfile+'.inf'; sl.SaveToFile(destfile); finally sl.Free; // die Resource wird immer freigegeben, egal was passiert end; |
Re: Falsche Verwendung von try...except...end
es gibt da noch 'ne Sünde:
Man verwendet die try-except Konstruktion in einer Schleife. Bei einer Schleife, die sehr oft durchlaufen wird, verschlingt das Rechenzeit. |
Re: Falsche Verwendung von try...except...end
Hi all,
bei Delphi is mir mit als erstes aufgefallen, dass man except und finally nicht miteinander verwenden kann. In Java bsw. können folgende Blöcke gebildet werden:
Code:
try
{ ... } except { ... } finally { ... } Da ich auf Exceptions reagieren möchte (log diese in ne Datei), setze ich finally so gut wie gar nicht ein. Jetzt hab ich in dem Beispiel allerdings gelesen, dass mein Ansatz eigentlich falsch ist.
Delphi-Quellcode:
Frag mich nun folgendes:
TRY
... sl:=TStringList.create; // Resource belegen ... EXCEPT on E:Exception do begin Loggen end; END; s1.Free 1. In obigen Beispiel wird doch s1 auch IMMER freigegeben oder hab ich da nen Denkfehler?. 2. Was passiert eigentlich wenn s1 nicht freigegeben wird? Wird nur unnötig Speicher belegt bis das Programm endet? cu Terminator |
Re: Falsche Verwendung von try...except...end
ich finde das erste nicht als Todsünde - Es gibt programme die sind für Leute die 0 Ahnung haben. Wenn diese User bei einem Musikprogramm alle Dateien im Ordner markieren und dem programm hinzufügen wäre es unzumutbar 20 Fehlermeldungen zu bringen weil eventuell Textdateien & Cover mit auf das Programm gedroppt wurden. Oder wenn man beim Start des programmes alle dateien aus einem dump läd und eine wechseldatenträger nicht gefunden wird kann ich nicht bei 20 000 Dateien dem Nutzer jedesmal eine Meldung bringen das die Datei nicht gefunden wurde. Da ist es nutzerfreundlicher wenn die datei einfach nicht geadded wird
|
Re: Falsche Verwendung von try...except...end
Zitat:
Hat der Entwickler 0 Ahnung, muss zwangsläufig der Anwender Ahnung haben. In solchen Fällen versuche ich nicht einfach blind ein .jpg per Mediaplayer abzuspielen, sondern ich (als Entwickler) schaue vorher, was ich denn da für Dateien kriege (Notfalls anhand des Dateinamens). Dann gibt's keine Exceptions und ich kann selber entscheiden ob ich für jede Datei eine Meldung anzeige oder nur für die erste oder überhaupt nicht (letzteres wäre bei sowas wohl das sinnvollste). Zitat:
Die Liste der Sünden gilt für Entwickler mit Grips, für Anfänger sind das garantiert keine Sünden, ganz einfach weil die's nicht besser wissen und nicht die nötige Erfahrung haben. |
Re: Falsche Verwendung von try...except...end
Ich fand des Tut ganz okay :thumb: hat mir das Exceptionhandling etwas näher gebracht :mrgreen: (Exceptions? Brauch ich net :zwinker: )
|
Re: Falsche Verwendung von try...except...end
Ich fand das Tut auch ganz toll, denn ich bin auch so ein Schlumi, der gern mal was in einen solchen Block packt, aber nichts damit anfängt. Ich denke, das ich da demnächst mehr darauf achten werde und das war auch sicher einer der Denkansätze für das Einbringen eines solchen Threads.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:27 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz