Hallo Gottfried,
Post by Gottfried LesigangPost by Philipp StiefelPost by Gottfried Lesigang[On Error Resume Next ist näher an try-catch]
Bei einem "On Error goto ..." wird auch *sofort* bei Auftreten
des Fehlers in den Errorhandler gesprungen. Diese
Unterscheidung ist daher so nicht richtig. Du musst auch nicht
dieselbe "On Error goto ..." Srpungmarke für die ganze Prozedur
verwenden. Vielleicht mal ein wenig Pseudocode um das zu
vedeutlichen.
Ja, das ist schon klar. Aber ganz oft geht ja, anders als in
deinem Beispiel, nach einer verdächtigen Code-Zeile das Programm
noch weiter. Dann musst du aus deinen Error-Blöcken mit einer
"Resume" oder "Resume Next" Anweisung zurückspringen. Und dann
gibt es vielleicht auch Code-Teile, die jedenfalls abgearbeitet
werden sollten (in .NET das "finally"). Dann springst du
wahrscheinlich irgendwie an diese Stelle, lässt aber dein "On
Error Goto Spezialmarke" unverändert. Es gilt dann im anderen
Block immer noch die alte Fehler-Routine...
Letzteres Problem lässt sich durch ein entsprechendes On Error
Goto lösen. Praktisch ist das aus meiner Sicht aber eher weniger
ein Problem, da es i.d.R. wohl keinen Sinn macht eine Prozedur,
die bereits in einen unerwarteten, d.h. nicht vorher abgeprüften
Fehler gelaufen ist, lang weiterlaufen zu lassen. D.h. eigentlich
sollte sich der noch abzuarbeitende Code auf reine Aufräum-
anweisungen beschränken und diese lassen sich gut in einem Exit-
Block unterbringen.
Das funktioniert natürlich nur dann gut, wenn man /Problem-
situationen/, die man vorher schon erwartet, abprüft, ohne dabei
einen Laufzeitfehler auszulösen.
Post by Gottfried LesigangIch finde es viel logischer und auch richtiger das Programm von
oben nach unten ablaufen zu lassen, verdächtige Codezeilen zu
prüfen, darauf sauber zu reagieren, dann ein "Err.Clear" und
weiter geht's...
Logischer ja, ohne Frage. Das Problem ist aber, dass du bei einem
On Error Resume Next entweder sehr viel Code benötigst, der mit der
eigentlichen Logik der Prozedur nichts zu tun hat, um an allen
Stellen alle möglichen Fehler sinnvoll zu behandeln, oder du mehr
oder weniger große Code-Blöcke hast, bei denen du einfach davon
ausgehst, dass schon alles gut geht und in denen evtuelle Fehler
unter den Tisch fallen.
Post by Gottfried LesigangPost by Philipp StiefelDamit bist du, bis auf den unangenehmen Spaghetti-Effekt, da wo
du mit einem Try/Catch-Block auch wärst.
Ja, immer dann, wenn in allen Error-Fällen die Routine verlassen
werden soll - also selten ;-)
Wenn "verlassen" einen Exit-Block zum Freigeben evtl. belegter
Ressourcen inkludiert, müsste es für mich heißen:
Also (so gut wie) immer!
Post by Gottfried LesigangPost by Philipp StiefelMit einem "On Error
Resume Next" kommst du da aber nicht so einfach hin, weil du
dann nach jeder Anweisung übeprüfen musst (solltest) ob ein
Fehler aufgetreten ist.
Ich masse mir an bei einer ganzen Reihe von Zeilen anzunehmen,
dass da nix passiert...
Ich nicht! - Ich habe das lang getan und bin damit oft genug auf
die Schnautze gefallen. Inzwischen bemühe ich mich sämtliche
Annahmen von irgendetwas aus meinem Code zu verbannen. - Natürlich
gelingt das nicht immer.
[...]
Post by Gottfried LesigangPost by Philipp StiefelPost by Gottfried LesigangNoch wichtiger empfinde ich aber die bewusste lokalisierung
rund um "verdächtige" Codeteile...
Wie oben demonstriert ist diese Lokalisierung ohne weiteres
möglich, sie ist nur nicht so deutlich strukturiert.
Wenn du nun hintennach mehrere Error-Blöcke hast und dann
womöglich noch Rücksprünge stimmt das ganz und gar nicht. Es
wird dadurch nur alles ungeheuer aufgebläht. So würde ich nur
arbeiten, wenn ich nach Zeilen bezahlt wäre ;-)
Ja, das stimmt. Wie gesagt, kommt das aber bei mir praktisch
eigenlich nicht vor. Ab einer gewissen Komplexität ist
Errorhandling mit On Error Goto nicht mehr sinnvoll, aber ich bin
der Meinung, dass das praktisch eher von untergeordneter Bendeutung
ist, da es in einem solchen Fall sowieso sinnvoller, weil lesbarer
ist eine große/komplexe Prozedur in mehrere kleine aufzuteilen.
Post by Gottfried LesigangPost by Philipp StiefelPost by Gottfried Lesigang[Gottfrieds "Contains" Beispiel]
Wenn du alleine arbeitest ist das OK, solange du konsequent
bist und verinnerlicht hast, wie du mit deinem Code umgehen
musst.
Wo liegen denn da die Gefahren? Wenn einer der Collection was
hinzufügen will, oder wenn ein Item abgerufen werden soll, dann
gibt es ja einen Fehler, weil das dort Sinn macht...
Z.B. darin dass der Code eine zeit- und ressourcenfreesende
Berechnung für das neue Item, das hinzugefügt werden soll, weil es
nocht nicht in der Collections ist, ausführt, nur um später beim
Hinzufügen festzustellen, dass die ganze Collection nicht
exisitiert.
Post by Gottfried LesigangPost by Philipp StiefelWenn du aber im Team arbeitest und andere Entwickler
deinen Code nutzen, dann finde ich diesen Ansatz nicht gut,
weil er eine bestimmte Ausgangssituation voraussetzt, die
durch den Code selbst nicht verifiziert wird.
Wieso? Wenn ich an der Stelle wissen will, ob die Collection
instanziert ist, dann kann ich das ganz leicht mit "Is Nothing"
- allemal leichter als höchst überflüsiger Weise einen Fehler
hinaufzureichen, diesen oben dann wieder mit einem extra dafür
angelegeten Error-Block abzufangen, nur um nachher zu wissen,
dass der Key eben nicht in der Collection ist.
Ich glaube unsere Differenz ist vor allem philosophischer Natur.
Genau das würde ich nämlich nicht tun. Entweder ich reche an einer
bestimmten Stelle damit, dass die Collection nicht exisitiert, dann
prüfe ich sie auf Nothing und leitet ggfls. Maßnahmen ein, oder ich
gehe davon aus dass sie existiert, dann _will_ ich einen brutalen
Fehler, der auch nicht gesondert behandelt wird, wenn meine Annahme
an dieser Stelle falsch war. Ein solcher Fehler in dieser Situation
führt dann zum Abbruch alles laufenden Codes, daher muss dann
ausser Aufräumen
Post by Gottfried LesigangPost by Philipp StiefelNein, aber ich würde eine solche Methode nie auf ein Objekt
anwenden, wenn ich nicht davon ausgehen würde, dass es bereits
existiert.
Warum?
Gewohnheit, Philosophie, mein Verständins von einem sauberen
Programmierstil nenn es wie du willst. ;-)
Post by Gottfried LesigangIch verwende die Fehler als "zweite Rückmeldeschiene" und
fahre damit sehr gut.
Ich verstehe nicht so recht, was du mit "zweite Rückmeldeschiene"
meinst. Wie dem auch sei, rein technisch ist gegen deinen Ansatz
nichts einzuwenden, IMO ist er nur nicht "intuitiv", wenn man damit
nicht vertraut ist.
Post by Gottfried LesigangPost by Philipp StiefelPost by Gottfried LesigangBeschreibe mir doch mal einen besseren Weg zu prüfen ob ein
Key in einer Collection enthalten ist, ohne "On Error Resume
Next" zu verwenden.
Mir ging es nicht prizipiell um das On Error resume Next,
sondern darum dass du nicht prüfst welcher Fehler genau
aufgetreten ist.
Weil's an der Stelle nicht interessiert.
Das ist der "philosophische" Unterschied. - Mich interessiert es!
Post by Gottfried LesigangWas sollte ich denn
auch mit der Information anfangen. Letztlich wäre dieser
konkrete Fehler sicherlich einer der "nicht behandelten" in
deinem Error-Handler...
Ja, natürlich. Mehr als 95% aller Fehler gehören dazu. Bei Fehlern
die nicht dazu gehören, versuche ich vorher zu prüfen ob sie
auftreten werden und verhindere es dann.
Post by Gottfried LesigangPost by Philipp Stiefel'-------------------------------------------------
Public Function Contains(Key As String) As Boolean
Dim lngErrNo As Long
Dim tmpDummy As Object
On Error Resume Next
Set tmpDummy = MyCollection.Item(Key)
lngErrNo = Err.Number
On Error GoTo 0
If lngErrNo <> 5 Then
Err.Raise lngErrNo
End If
Contains = Not CBool(lngErrNo)
End Function
'-------------------------------------------------
So viele Zeilen, nur dafür, dass ich mich einen Stock darüber
wieder mit einem Fehler herum schlagen muss?
Ja, die Meldung der Fehler gehört idealerweise in das GUI-Layer.
Post by Gottfried LesigangWenn schon, dann
müsstest du noch die Fehler-Source puffern und den
Routinen-Namen der aktuellen Prozedur dranhängen, eine Message
dazu stellen...
Ja, klar. Das war eine vereinfachte Darstellung, in echtem Code tue
ich das natürlich.
Post by Gottfried LesigangPost by Philipp StiefelIch wähle üblicherweise immer den Ansatz, Fehler möglichst
zu vermeiden. D.h. ich würde lieber die Items der Collection
durchgehen und püfen ob das gesuchte enthalten ist. - Je
nach Größe der Collection kann sich das natürlich unangenehm
auf die Performance auswirken.
Wenn du die Items der Collection durchgehen willst, musst du
frisch wieder mit einer nicht instanzierten Collection rechnen -
da beißt sich dann die Katze in den Schwanz. Wenn du jetzt
sagst: "Das kann ich ja mit 'Is Nothing' abfragen.", dann würde
ich sagen: "Eben!"
Nein, eben nicht. Dieser Fehler wäre für mich einfach eine nicht
vorgesehene Situation und muss nicht dezidiert behandelt werden.
Post by Gottfried LesigangWie auch immer: Diskutieren macht Spaß!
Es verschafft vor allem interessante Einblicke in die
Programmierstile anderer Entwickler. Selbst wenn man dabei nicht
"zu einem Besseren bekehrt" wird, Lernt man doch welche
Alternativen es gibt, und warum genau man seine eigene Variante
vorzieht.
Viele Grüße
Phil
--
Bitte verwendet für Fragen zu Access mit DBMS-Server-Backends
die Newsgroup microsoft.public.de.access.clientserver! Danke!
Richtig zitieren im Usenet -> http://got.to/quote