Fehlerbehandlung - Grundsatzfragen

13/01/2010 - 23:25 von Josef Poetzl | Report spam
Hallo!

Es ist mal wieder Zeit, meine Standard-Code-Elemente in Frage zu
stellen. :-))
Eines dieser Elemente ist die Fehlerbehandlung, zu der ich ein paar
Grundsatzfragen stellen möchten.
Die nachfolgenden Beispiele sollen nur das Prinzip skizzieren. Ich
verzichte dabei bewusst auf eine Hilfsfunktion, die die
Fehlerbehandlung übernimmt. Auch das Einbinden einer Fehlerbehandlung
mittels Klasse will ich weg lassen und nur die Grundgedanken
hervorheben.

Folgende Ausgangslage:

| Sub Start()
| call Proc1()
| msgbox "start abgeschlossen"
| end sub
|
| Sub Proc1()
| call Proc2()
| msgbox "Proc1 abgeschlossen"
| end sub
|
| Sub Proc2()
| dim x as long
| x = 1 / 0
| msgbox "Proc2 abgeschlossen"
| end sub

Anm.: "1 / 0" steht in diesem Beispiel symbolisch für einen
unerwarteten Fehler, der nicht behoben werden kann.
Also bitte nicht an Fehler wie fehlende DB-Properties denken, die in
der Fehlerbehandlung ergànzt werden damit anschließend der Code normal
fortgesetzt werden kann.


Varianten:

A) Überall eine Fehlerbehandlung, die den Fehler aufhebt

| Sub Start()
|
| On Error GoTo ErrHandler
|
| Call Proc1
| MsgBox "Start abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| MsgBox "Fehler " & Err.Number & ": " & Err.Description
| Resume ExitHere
|
| End Sub
|
| Sub Proc1()
|
| On Error GoTo ErrHandler
|
| Call Proc2
| MsgBox "Proc1 abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| MsgBox "Fehler " & Err.Number & ": " & Err.Description
| Resume ExitHere
|
| End Sub
|
| Sub Proc2()
|
| On Error GoTo ErrHandler
|
| Dim X As Long
| X = 1 / 0
| MsgBox "Proc2 abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| MsgBox "Fehler " & Err.Number & ": " & Err.Description
| Resume ExitHere
|
| End Sub

=> Damit kommt es nach dem Aufruf von Start() zu den Meldungen:
* Fehler 11: Division durch Null
* Proc1 abgeschlossen
* Start abgeschlossen

Diese Variante kann somit dazu führen, dass Code normal weiterlàuft,
obwohl es zu einem Fehler kam.
Damit das nicht passiert, könnte man die Fehlerbehandlung nur in
Start() lassen.

B) Nur in der ersten Prozedur die Fehlerbehandlung einbauen

| Sub Start()
|
| On Error GoTo ErrHandler
|
| Call Proc1
| MsgBox "Start abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| MsgBox "Fehler " & Err.Number & ": " & Err.Description
| Resume ExitHere
|
| End Sub
|
| Sub Proc1()
|
| Call Proc2
| MsgBox "Proc1 abgeschlossen"
|
| End Sub
|
| Sub Proc2()
|
| Dim X As Long
| X = 1 / 0
| MsgBox "Proc2 abgeschlossen"
|
| End Sub

Das führt (wie gewünscht) zum Abbruch des gesamten Code-Ablaufs, hat
aber dafür den Nachteil, dass man in der Fehlermeldung nicht erkennen
kann, wo der Fehler auftrat.
Aus diesem Grund nutze ich derzeit so ein Konzept:

C) Fehler abfangen, aber danach gleich wieder auslösen

| Sub Start()
|
| On Error GoTo ErrHandler
|
| Call Proc1
| MsgBox "Start abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| MsgBox "Fehler " & Err.Number & ": " & Err.Description & vbNewLine & _
| "(" & Err.source & ")"
| Resume ExitHere
|
| End Sub
|
| Sub Proc1()
|
| On Error GoTo ErrHandler
|
| Call Proc2
| MsgBox "Proc1 abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| Err.Raise Err.Number, "Proc1:" & Err.source, Err.Description
| Resume ExitHere
|
| End Sub
|
| Sub Proc2()
|
| On Error GoTo ErrHandler
|
| Dim X As Long
| X = 1 / 0
| MsgBox "Proc2 abgeschlossen"
|
| ExitHere:
| Exit Sub
|
| ErrHandler:
| Err.Raise Err.Number, "Proc2:" & Err.source, Err.Description
| Resume ExitHere
|
| End Sub

Solange Start() der àußerste Aufruf ist - also z. B. die Prozedur für
die Ereignisbehandlung eines Click-Ereignisses - klappt das ganz gut.
Aber kann man die àußerste Aufrufebene immer bestimmen?

Wie würdet ihr die Fehlerbehandlung für das obige Beispiel gestalten?
(Es darf keine "... abgeschlossen"-Meldung kommen.)


mfg
Josef

EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
 

Lesen sie die antworten

#1 Henry Habermacher
14/01/2010 - 03:43 | Warnen spam
Hallo Josef

Josef Poetzl wrote:
Solange Start() der àußerste Aufruf ist - also z. B. die Prozedur für
die Ereignisbehandlung eines Click-Ereignisses - klappt das ganz gut.
Aber kann man die àußerste Aufrufebene immer bestimmen?



Ja, das ist eine der von mir aus gesehen praktikabelsten Lösungen: Ein gutes
ErrorHandling auf der àussersten Ebene. Alternativ dazu kannst Du die
Fehlerbehandlung überall durchführen und im Fehlerfall mit einem Returncode
und der Fehlerinformation aus der Funktion hàndisch zurückspringen. Du
kannst Dir dazu z.B. ein globales Error Objekt anlegen und dieses dann mit
dem Fehler befüllen, wenn er aufgetreten ist. Nur sind dann verschachtelte
Aufrufe über mehrere Ebenen ziemlich mühsam zu handeln, weil Du bei jedem
Aufruf nachtràglich immer kontrollieren musst, ob ein Fehler aufgetreten
ist.

Wie würdet ihr die Fehlerbehandlung für das obige Beispiel gestalten?
(Es darf keine "... abgeschlossen"-Meldung kommen.)



Mit einem Returncode würde das schon machbar sein. Statt des Calls machst Du
dann:

If Proc1() <> 0 Then
"Fehler in Proc 1"
Else
"start abgeschlossen"
End If

etc, etc,

Gruss
Herny



Microsoft MVP Office Access
Keine E-Mails auf Postings in NGs. Danke.
Access FAQ www.donkarl.com

Ähnliche fragen