Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wann werfe ich welche Exception? (https://www.delphipraxis.net/173885-wann-werfe-ich-welche-exception.html)

Der schöne Günther 22. Mär 2013 09:14

Delphi-Version: XE2

Wann werfe ich welche Exception?
 
Hallo-

Gibt eine Liste an Best Practices wann welche Exception geworfen werden sollte? In den Weiten des Internets finde ich manchmal Listen mit Exception-Typen die es in meinem XE2 schon garnicht mehr gibt oder umbenannt wurden...

Konkretes Beispiel: Ich möchte etwas mittels
Delphi-Quellcode:
WriteFile
auf die serielle Schnittstelle schreiben. Gibt diese Windows-Methode false zurück, möchte ich eine Exception werfen. Liege ich damit
Delphi-Quellcode:
EWriteError
richtig?

Und wenn ich im Urlaub bin, sollte wahrscheinlich direkt beim Start
Delphi-Quellcode:
EProgrammerNotFound
geworfen werden...

DeddyH 22. Mär 2013 09:43

AW: Wann werfe ich welche Exception?
 
Zitat:

EWriteError ist die Exception-Klasse für fehlgeschlagene Versuche, Daten in einen Stream zu schreiben.
Je nachdem, wie Du schreiben möchtest, könnte das schon der richtige Typ sein. Im Zweifelsfall kannst Du Dir aber auch eigene Exceptions ableiten und dann diese benutzen.

Sir Rufo 22. Mär 2013 10:41

AW: Wann werfe ich welche Exception?
 
Das hängt von deinem Programmfluss selber ab und ob du diese Ausnahme (Exception) behandeln kannst/willst.

Nicht jede Exception bedeutet zwingend, dass alles für die Katz ist.

Hier mal ein kleines Beispiel:
Delphi-Quellcode:
program ExceptionTest;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  ECalcError = class( Exception );

procedure LogCalc( a, b, r : Integer );
begin
  Write( a, ' div ', b, ' = ' );
  if a div b <> r
  then
    raise ECalcError.CreateFmt( '%d div %d <> %d', [a, b, r] );
  Writeln( r );
end;

procedure TestRun;
var
  LIdx : Integer;
begin
  try

    for LIdx := 1 to 10 do
      begin
        try

          LogCalc( Random( 10 ), Random( 10 ), Random( 2 ) );

        except
          on E : ECalcError do
            begin
              Writeln( 'Das war wohl nix (', E.Message, ')' );
            end;
        end;
      end;

  except
    Writeln( 'Fehler' );
    raise;
  end;

end;

begin
  try

    Randomize;
    TestRun;

  except
    on E : Exception do
      begin
        Writeln( E.ClassName, ': ', E.Message );
      end;
  end;

  ReadLn;

end.
Beispiel-Lauf:
Code:
6 div 4 = 1
5 div 9 = Das war wohl nix (5 div 9 <> 1)
0 div 5 = 0
6 div 6 = 1
8 div 1 = Das war wohl nix (8 div 1 <> 0)
9 div 4 = Das war wohl nix (9 div 4 <> 1)
2 div 0 = Fehler
EDivByZero: Division durch Null

Der schöne Günther 22. Mär 2013 11:03

AW: Wann werfe ich welche Exception?
 
Hallo, das ist mir mehr oder weniger klar. :)

Ich möchte meine Methoden nur so gestalten, dass sie Exceptions werfen, die jemand anderes auch erwarten würde. Delphi-Methoden müssen ja leider (im Gegensatz zu Java) nicht zwingend kenntlich machen, was sie werfen können.

Ich frage mal so: Werde ich drumherum kommen, mir zu allen in
Delphi-Quellcode:
System.SysUtils
definierten Exception die aktuelle Hilfe anzuschauen, versuchen es mir zu merken und weiterhin unsicher sein?

Sir Rufo 22. Mär 2013 11:10

AW: Wann werfe ich welche Exception?
 
Hmmm, also wenn dein Code nicht weiterkommt, weil da etwas aufgetaucht ist, was so nicht sein soll/darf, dann gibt man eine Rückmeldung.

Entweder man hat eine
Delphi-Quellcode:
function
, die als Result diese Rückmeldung liefert oder man wirft eine Exception.

Am besten ist es, für eigene Klassen/Frameworks auch eigene Exception-Klassen zu definieren und in der Dokumentation zu vermerken, wann diese Exceptions geschmissen werden.

BTW: Eine Exception ist eine Ausnahme, erwartet wird sowas idR nicht ;)

sx2008 22. Mär 2013 11:51

AW: Wann werfe ich welche Exception?
 
Es kommt auch auf die Grösse des Projekts an.
Bei kleineren Projekten kann man ohne weiteres Exceptions direkt so auslösen:
Delphi-Quellcode:
raise Exception.Create('Fehler beim Laden der Konfiguration');
Da die Anzahl der raise - Anweisungen relativ klein ist, weiss man schon anhand des Fehlertextes wo man suchen muss.

Bei grossen und sehr grossen Anwendungen gibt es so viele Stellen im Sourcecode an denen eine Exception ausgelöst wird, dass man unmöglich alle im Kopf haben kann.
Dann ist es sehr hilfreich wenn man eigene Exception-Klassen einführt (z.B. EImportError, EXmlError, ...).
Diese Exception-Klassen leitet man meist direkt von der Klasse Exception ab, da die anderen in SysUtils definierten Klassen nur recht selten passen.

Bei richtig grossen Anwendungen wird man die (nichtabgefangene) Exception nicht nur anzeigen, sondern man wird
Delphi-Quellcode:
Classname
und
Delphi-Quellcode:
Message
der Exception in eine Logdatei schreiben.
Hier zahlt es sich dann aus, wenn man je nach "Bereich" oder Fehlerart eine eigene Exceptionklasse hat und so gleich weiss wo man suchen muss.

Lemmy 6. Jun 2013 12:03

AW: Wann werfe ich welche Exception?
 
Hallo,

schau dir mal folgende beiden Dokumente an, vielleicht helfen die dir weiter

http://www.nickhodges.com/post/On-th...erarchies.aspx
http://conferences.embarcadero.com/article/32156

Grüße

Der schöne Günther 6. Jun 2013 12:06

AW: Wann werfe ich welche Exception?
 
Danke, vor allem ersteres ist genau, was ich meinte :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:26 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz