Viele Programmierer verwenden
try...except...end auf eine falsche Weise.
Es gibt mindestens 5
"Sünden", die man begehen kann:
Delphi-Quellcode:
// 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;
Wenn man obige Sünden nicht begeht, wird man belohnt:
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.
Exceptions mit Help-Button anzeigen
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);