Einzelnen Beitrag anzeigen

Furtbichler
(Gast)

n/a Beiträge
 
#9

AW: Try - except - finally

  Alt 30. Sep 2013, 10:14
Da wird man wohl diese Sprachunschönheit akzeptieren müssen und doppelt aufbauen
Das ist Geschmackssache. In C# gehts auch nicht und das ist auch OK so (imho). Die Abstraktionsniveaus passen bei 'try-finally' und 'try..except' sowieso nicht, ergo ist es eh ein Designflaw, das in eine Methode zu packen, aber das mal nur nebenbei.

Ist ein except nicht irgendwie ein finally.
Wenn Du es 'falsch' angehst: Ja.
Das 'Try-Except' benötigst Du, um etwaige Ausnahmen/Fehler zu kapseln und das Abstraktionsniveau anzuheben. Allgemein sieht das so aus:
Delphi-Quellcode:
procedure TMyClass.Action();
begin
  try
    DoSomething();
  except
    on e:ESomethingException do
      raise new EActionException.Create (TranslateExpectedException(e));
    on e:Exception do
      raise new EActionException.Create (TranslateUnexpectedExpectedException(e));
  end
end;
D.h. Du fängst die Exceptions ab und übersetzt sie so, das der Aufrufer der Methode 'Action' etwas damit anfangen kann. Z.B. kapselst Du Fehlermeldungen beim Verbindungsaufbau der DB (TCP-, Named-Pipe-, Server-, Hardware-, Login- Fehler in eine abstraktere 'EActionFailed'- Exception. Denn den Aufrufer interessiert es nicht, was da hinter der Fassade vor sich geht und ob es eine EADOException, EOracleException, ETCPException, EIdException etc. ist.

Allgemein gesehen transformierst Du die Exception und reichst sie durch. In Sonderfällen, wenn z.B. die Exception einfach eine Ausnahme von der Regel ist, oder wenn die Exception 'repariert' werden kann, würdest Du die Exception nicht weiterreichen bzw. transformieren.

Damit ist klar, das dein Gleichsetzen nur in Ausnahmefällen zutreffen würde. Aus Gründen der Übersichtlichkeit würde ich jedoch *immer* ein explizites 'try-finally' umsetzen. Dann ist einfach sonnenklar, das es sich um einen resourcenschutzblock handelt.

Delphi-Quellcode:
Procedure TMyClass.Action(); // Public !
Begin
  Try
    InnerAction();
  Except
    on e:ESomethingException do
      raise new EActionException.Create (TranslateExpectedException(e));
    on e:Exception do
      raise new EActionException.Create (TranslateUnexpectedExpectedException(e));
  end
end;

Procedure TMyClass.InnerAction(); // private oder protected !!
begin
  Stuff.Acquire();
  try
    DoSomething(Stuff);
  Finally
    Stuff.Release();
  End
End;
Nun kann man in 'Action' entscheiden, ob man reparieren kann, oder nicht.
Es geht natürlich auch umgekehrt:

Delphi-Quellcode:
Procedure TMyClass.Action(); // Public !
Begin
  Stuff.Acquire();
  Try
    InnerAction(Stuff);
  Finally
    Stuff.Release();
  End
end;

Procedure TMyClass.InnerAction(Stuff : TStuff); // private oder protected !!
begin
  try
    DoSomething(Stuff);
  Except
    on e:ESomethingException do
      raise new EActionException.Create (TranslateExpectedException(e));
    on e:Exception do
      raise new EActionException.Create (TranslateUnexpectedExpectedException(e));
  end
End;
Meist wird man die erste Variante ('Unit of Work') verwenden. Bei der zweiten Variante ist ja nicht sichergestellt, das 'Stuff' korrekt initialisiert ist (das müsste ggf. sichergestellt werden). Allerdings könnte die 2. Variante bei Reparaturversuchen sinnvoll sein. Kommt immer auf den Fall an.
  Mit Zitat antworten Zitat