AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Dokumentation und Exceptions - Wann muss ich was erwarten?
Thema durchsuchen
Ansicht
Themen-Optionen

Dokumentation und Exceptions - Wann muss ich was erwarten?

Offene Frage von "sahimba"
Ein Thema von Der schöne Günther · begonnen am 6. Jun 2013 · letzter Beitrag vom 6. Jun 2013
Antwort Antwort
Seite 1 von 2  1 2      
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 09:52
Delphi-Version: XE2
Das ist schon das (mindestens) dritte Thema zum Bereich Exceptions, ich werde irgendwie immer noch nicht warm damit, wie Exceptions in der Delphi-Welt generell gehandhabt werden.

Dass auf meine generelle Frage http://www.delphipraxis.net/173885-w...exception.html keine eindeutige Antwort existiert ist natürlich verständlich. Mein jetziges Anliegen ist stark verwandt mit meiner unbeantworteten Frage http://www.delphipraxis.net/174454-u...ns-finden.html :

Ich schaue mir fröhlich von Embarcadero Tutorial: Herstellen einer Verbindung zu einer SQLite-Datenbank (Delphi) an.

Dort finde ich:
Delphi-Quellcode:
try
   // Establish the connection.
   SQLConnection1.Connected := true;
   executeButton.Enabled := true;
   outputMemo.Text := 'Connection established!';
except
   on E: EDatabaseError do
      ShowMessage('Exception raised with message' + E.Message);
end;
Abgesehen davon, dass ich nicht einsehe, warum man die beiden Oberflächen-bezogenen Anweisungen nicht nach dem try-Block ausführen sollte: Woher kann ich wissen, dass ich einen EDatabaseError zu erwarten habe?

Die Dokumentation erzählt weder bei TSQLConnection::Connected noch TCustomConnection::Connected von einer möglichen Exception. Immerhin spricht sie von einer intern aufgerufenen Methode TCustomConnection.DoConnect. Doch auch hier: Kein Sterbenswort.

Und auf Dauer habe ich ehrlich gesagt auch nicht die Zeit, in Methoden wie TSQLConnection.DoConnect zu suchen, was denn hier alles Exceptions nach oben werfen könnte:

Delphi-Quellcode:
procedure TSQLConnection.DoConnect;
var
  ConnectionProps: TDBXProperties;
  Ind: Integer;
  ConnectionFactory: TDBXConnectionFactory;
  LoginParams: TStrings;
  SchemaOverride: string;
  SchemaOverrideList: TStringList;
  Password: string;
  MemoryConnectionFactory: TDBXMemoryConnectionFactory;
begin
  ConnectionProps := nil;
  LoginParams := TStringList.Create;
  MemoryConnectionFactory := nil;
  try
    if LoadParamsOnConnect then
    begin
      ConnectionFactory := TDBXConnectionFactory.GetConnectionFactory;
      TDBXConnectionFactory.Lock;
      try
        ConnectionProps := ConnectionFactory.GetConnectionProperties(ConnectionName);
        ConnectionProps := ConnectionProps.Clone;
      finally
        TDBXConnectionFactory.Unlock;
      end;
    end else
    begin
      ConnectionProps := TDBXProperties.Create;
      try
        ConnectionFactory := TDBXConnectionFactory.GetConnectionFactory;
      except
        MemoryConnectionFactory := TDBXMemoryConnectionFactory.Create;
        ConnectionFactory := MemoryConnectionFactory;
        ConnectionFactory.Open;
      end;
      ConnectionProps.AddProperties(FParams);
      if ConnectionProps.Properties.IndexOfName(TDBXPropertyNames.DriverName) = -1 then
        ConnectionProps.Add(TDBXPropertyNames.DriverName, DriverName);
    end;
    CheckLoginParams;
    ConnectionState := csStateConnecting;

    GetLoginParams(LoginParams);
    if LoginParams.Values[TDBXPropertyNames.Database] <> ConnectionProps[TDBXPropertyNames.Database] then
    begin
      ConnectionProps[TDBXPropertyNames.Database] := LoginParams.Values[TDBXPropertyNames.Database];
    end;

    SetCursor(HourGlassCursor);

    ConnectionProps.Add('UNLICENSED_DRIVERS', IntToStr(GDAL)); // Do not translate.

    FLoginUsername := LoginParams.Values[TDBXPropertyNames.UserName];
    if FLoginUserName <> 'then
      ConnectionProps[TDBXPropertyNames.UserName] := FLoginUsername;
    Password := LoginParams.Values[TDBXPropertyNames.Password];
    if Password <> 'then
      ConnectionProps[TDBXPropertyNames.Password] := Password;
    ConnectionProps.SetComponentOwner(self);
    ConnectionProps.Events.Events[sValidatePeerCertificate] := TEventPointer(ValidatePeerCertificate);

    ConnectionFactory.Lock;
    try
      FDBXConnection := ConnectionFactory.GetConnection(ConnectionProps);
    finally
      ConnectionFactory.Unlock;
    end;

    for Ind := 0 to FMonitorUsers.Count -1 do
      FMonitorUsers[Ind].UpdateTraceCallBack;

    SetCursor(HourGlassCursor);

    RegisterTraceCallback(True);

    FDefaultSchema := '';

    if (FDBXConnection.ProductName = 'BlackfishSQL') then {Do not localize}
    begin
      FDefaultSchema := 'DEFAULT_SCHEMA'; { Do not localize }
    end;

    SchemaOverride := ConnectionProps[TDBXPropertyNames.SchemaOverride];

    if (SchemaOverride = '') and LoadParamsOnConnect then
    begin
      TDBXConnectionFactory.Lock;
      try
        SchemaOverride := ConnectionFactory.GetDriverProperties(ConnectionProps[TDBXPropertyNames.DriverName])
                          [TDBXPropertyNames.SchemaOverride];
      finally
        TDBXConnectionFactory.Unlock;
      end;
    end;

    if SchemaOverride <> 'then
    begin
      SchemaOverrideList := TStringList.Create;
      try
        SchemaOverrideList.Delimiter := '.';
        SchemaOverrideList.DelimitedText := SchemaOverride;
        if SchemaOverrideList.Count = 2 then
        begin
          if (SchemaOverrideList[0] = '%') or (SchemaOverrideList[0] = FLoginUsername) then
            FDefaultSchema := SchemaOverrideList[1];
        end;
      finally
        SchemaOverrideList.Free;
      end;
    end;

    ConnectionOptions;

    ConnectionState := csStateOpen;
  finally
    FreeAndNil(MemoryConnectionFactory); // If allocated, free it.
    SetCursor(DefaultCursor);
    LoginParams.Free;
    ConnectionProps.Free;
    if ConnectionState = csStateConnecting then // an exception occurred
    begin
      ConnectionState := csStateClosed;
      if Assigned(FDBXConnection) then
        FreeAndNil(FDBXConnection)
    end;
  end;
end;

Deshalb: Irgendwoher muss die Doku ja die Weisheit nehmen, dass irgendwoher ein EDatabaseError kommen kann. Ich bin zu dumm, das zu sehen. Bitte helft mir.
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.366 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 11:14
Abgesehen davon, dass ich nicht einsehe, warum man die beiden Oberflächen-bezogenen Anweisungen nicht nach dem try-Block ausführen sollte: Woher kann ich wissen, dass ich einen EDatabaseError zu erwarten habe?
....
Deshalb: Irgendwoher muss die Doku ja die Weisheit nehmen, dass irgendwoher ein EDatabaseError kommen kann. Ich bin zu dumm, das zu sehen. Bitte helft mir.

ist doch ganz einfach: Du weißt das aus der Dokumentation - in diesem Fall aus dem entsprechenden Codebeispiel.

Der Doku-Schreiber weiß, dass da ein EDatabaseError aufschlagen kann (so lange er keinen Fehler gemacht hat) vom Entwickler, der die betreffende Bibliothek geschrieben hat, und der sollte das eigentlich wissen.

was denn hier alles Exceptions nach oben werfen könnte:
das ist eigentlich Aufgabe der Dokumentation, das zu beschreiben...

Grüße
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 11:20
Ein "So basteln Sie sich eine XYZ-Anwendung"-Tutorial das ich zufällig über Google gefunden habe ist doch keine Dokumentation , auch wenn es von Embarcadero stammt. Finde ich.

Würde es in der Doku angesprochen werden, würde ich das noch vielleich gelten lassen. Aber das steht einfach nur so im Raum. Woher weiß ich, was noch für Arten von Fehlern nach oben geworfen werden können? Ich möchte nicht dort enden, aus Unwissenheit grundsätzlich Exceptions zu essen, nur weil Embarcadero nichts vernünftig dokumentiert hat (falls das denn der Fall sein sollte)...
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#4

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 11:37
Wichtig scheint mir das nur wenn Du auf verschiedene Exceptions unterschiedlich reagieren willst, was dann ja voraussetzt dass Du weist was Du wie behandeln will. Den Rest kannst Du ja über den else Zweig abfackeln.

Delphi-Quellcode:
procedure Tuwas(const s:String);
var
   i:Integer;
begin
  try
    i := StrToInt(s);
    Showmessage(FloatToStr(1/i));
  except
    ON E:Exception do
    begin
      if E is EZeroDivide then Showmessage('Divison durch 0')
      else Raise; // oder was auch sonst hier vorzusehen wäre
    end;
  end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
  TuWas('0');
  TuWas('Nase');
end;
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.366 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 11:50
Ein "So basteln Sie sich eine XYZ-Anwendung"-Tutorial das ich zufällig über Google gefunden habe ist doch keine Dokumentation , auch wenn es von Embarcadero stammt. Finde ich.
Kannst Du blöd finden oder nicht, ändert aber nichts daran, dass es die offizielle Doku ist.


Ich möchte nicht dort enden, aus Unwissenheit grundsätzlich Exceptions zu essen, nur weil Embarcadero nichts vernünftig dokumentiert hat (falls das denn der Fall sein sollte)...
wo isst Du Exceptions? Du reagierst auf EDatabaseError und der Rest wird an die gui geworfen (ist zumindest bei Delphi 7 so und wird auch hoffentlich in XEx nicht anders sein)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 11:53
Wichtig scheint mir das nur wenn Du auf verschiedene Exceptions unterschiedlich reagieren willst
Vollkommen richtig.

Ich möchte ja nur überhaupt wissen, dass da etwas kommen kann! Meine Beschwerde ist bislang nur:
"Zufällig sah ich in diesem zusammenhangslosen Tutorial, dass diese Methode eine Exception werfen kann. Das steht weder in der Doku, noch ist es in der Implementation ersichtlich. Das darf nicht sein, Embarcadero!"
Weiterhin die Hoffnung, dass die Beschwerde unbegründet ist.


Kannst Du blöd finden oder nicht, ändert aber nichts daran, dass es die offizielle Doku ist.
Meinetwegen. Aber selbst das ist nicht vollständig. Das Teil kann genauso gut eine TDBXError-Exception werfen. Und die ist mit dem EDataBaseError nicht verwandt. Die fängt der Kerl in seinem Tutorial auch nicht. Und in der Doku vermerkt ist es natürlich auch nicht.

Geändert von Der schöne Günther ( 6. Jun 2013 um 11:58 Uhr)
  Mit Zitat antworten Zitat
sahimba

Registriert seit: 14. Nov 2011
Ort: Berlin, Hauptstadt der DDR
137 Beiträge
 
Delphi 10 Seattle Professional
 
#7

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 11:58
Witzigerweise kann das Ding auch noch ganz andere Exceptions werfen. Und die fängt der Tutorialersteller nicht.
Man "sollte" imho auch nur jene Exceptions behandeln, auf welche man auch wirklich (sinnvoll) reagieren kann. Im Zweifel lässt man sie eben ganz nach oben bubbeln.

Wobei es immer Ausnahmen von der Regel gibt und auch selten, ganz selten, ein Exceptionhandler sinnvoll sein kann, welcher wirklich alles schluckt. An dem Thema entzündeten sich fraglos schon Religionskriege.
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 12:02
Im Zweifel lässt man sie eben ganz nach oben bubbeln.
Ja, das ist der springende Punkt. Die Delphi-Welt ist für mich immer noch relativ neu, das scheint sich ja wirklich eine gängige Methode zu sein. Da möchte ich auch nichts gegen sagen, aber in meinem Projekt ist das absolut keine Option. Es darf nicht sein, dass irgendwo vielleicht doch noch bis an den Benutzer irgendeine Systemmeldung "Datenbanktreiber versagt beim Zugriff auf XYZ: Fehlercode 723" durchgereicht wird.
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.366 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 12:11

Dass auf meine generelle Frage http://www.delphipraxis.net/173885-w...exception.html keine eindeutige Antwort existiert ist natürlich verständlich.
ich habe dir da 2 Links angehängt, vielleicht helfen die dir weiter, oder ggf. kennst Du die schon.

Im Zweifel lässt man sie eben ganz nach oben bubbeln.
Ja, das ist der springende Punkt. Die Delphi-Welt ist für mich immer noch relativ neu, das scheint sich ja wirklich eine gängige Methode zu sein.
Was ist denn die Alternative? Du reagierst auf Exceptions wenn:
1. du sicher stellen musst, dass gewisse Anweisungen immer bearbeitet werden (try-finally)
2. bei erwarteten Fehlern (Datei nicht gefunden, Passwort nicht eingegeben) ein alternativer Programmzweig aufgerufen wird, der dem Anwender die Möglichkeit bietet zu reagieren oder um den Fehler zu loggen und für eine spätere Korrektur vorzumerken
...
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#10

AW: Dokumentation und Exceptions - Wann muss ich was erwarten?

  Alt 6. Jun 2013, 12:20
Also ein Code wie dieser macht überhaupt keinen Sinn:
Delphi-Quellcode:
try
   // Establish the connection.
   SQLConnection1.Connected := true;
   executeButton.Enabled := true;
   outputMemo.Text := 'Connection established!';
except
   on E: EDatabaseError do
      ShowMessage('Exception raised with message' + E.Message);
end;
1. Problem:
der Programmfaden läuft weiter obwohl das Öffnen der Datenbank erfolglos was.
In der Folge wird es im weiteren Verlauf zu einer weiteren Exception kommen.
2. Problem:
das Abfangen der Exception und das ShowMessage vernichtet wichtige Informationen zur Fehlersuche.
Es geht z.B. die genaue Exception-Klasse verloren.
Die Fehlermeldung "Exception raised with message" ist absolut Aussagelos, es steckt keine nützliche Information drin.
3. Problem:
durch das Abfangen der Exception, geht die Möglichkeit verloren die Exception automatisch in eine Logdatei zu schreiben.

Wie macht man es dann richtig?

1. Regel:
Exceptions nur dann abfangen, wenn man irgendwas zur Verbesserung beitragen kann.
Die Idee man könnte eine Exception durch abfangen irgendwie "reparieren" ist sowieso in 99% aller Fälle falsch.
Was man allerdings tun kann ist dem Benutzer möglichst gute Informationen zu geben was die Ursache b etrifft und wie er das Problem beheben kann.
Delphi-Quellcode:
try
   // Establish the connection.
   SQLConnection1.Connected := true;
   executeButton.Enabled := true;
   outputMemo.Text := 'Connection established!';
except
   on E: Exception do
   begin
      // dem Benutzer und dem Programmierer eine aussagekräftige Meldung geben
      // allgemeine Beschreibung zu Beginn der Meldung
      E.Message := 'Fehler beim Öffnen der Datenbank'#13#10+
         E.Message + #13#10 +
         // Details für Programmierer am Ende der Message
         SQLConnection1.ConnectionString;

      // um den Benutzer optimal zu unterstützen kann man den HelpContext setzen
      E.HelpContext := HELPCONTEXT_CONNECTION_FAILED;

      raise; // Exception neu auslösen, Exceptionklasse bleibt erhalten
   end;
end;
2. Regel:
nicht Exceptions abfangen und irgendwas mit ShowMessage anzeigen.
Showessage hat in dem Code nicht verloren.
Stellt dir vor die Exception tritt in einer Schleife mit >100 Durchläufen auf.
Ständig popt die gleiche Meldung auf; man kann das Programm nur noch abschiesen
3. Regel:
Man sollte raise wesentlich öfters verwenden als try...except .
In dem man eigene Exception-Klassen deklariert und diese dann raised kann man besondern in großen Programmen die Fehlerursache genauer lokalisiert.
4. Regel:
Das Prinzip der Informationanreicherung schachteln
Delphi-Quellcode:
procedure TDataModule.CalcTaxInternal(IdCompany:Integer);
begin
  // jede Menge komplizierter Code zur Steuerberechnung
  ...
end;

procedure TDataModule.CalcTax(IdCompany:Integer);
begin
  try
     CalcTaxInternal(IdCompany);
  except
   on E: Exception do
   begin
      E.Message := 'Fehler bei Steuerberechnung für Firma '+IntToStr(IdCompany)#13#10+
         E.Message:
      E.HelpContext := HELPCONTEXT_TAX_CALC_ERROR;
      raise; // Exception neu auslösen, Exceptionklasse bleibt erhalten
   end;
end;
Selbst bei einer Zugriffsverletzung innerhalb von CalcTaxInternal() bekommt der Benutzer und der Programmierer so eine gute Info wo das Problem ist.
Die eigentliche Steuerberechnung bleibt völlig frei von störenden try ... except .
fork me on Github

Geändert von sx2008 ( 6. Jun 2013 um 12:22 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:29 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