Codenavigation durch Exceptions?

Sunray

Erfahrenes Mitglied
Von Visual Basic und anderen (va.) prozedualen Spreachen kennt man ja diese Go To Befehle, die häufig in Spaghetti-Code enden sollen.
Ich selbst habe nie so programmiert.

Manchmal reicht aber Exit Function in VB.NET nicht aus um einen Vrogang abzubrechen, weil auf die aufrufende Methode abgebrochen werden soll.

Warum nicht die Vorteile der zentralisierten Fehlerbehandlung nutzen und beim erfolgreichen Beenden eines Vorgangs mit Hilfer einer eigens dafür definierten Exception-Klasse die Notbremse ziehen.
Auch für die Rückgabe von Werten lassen sich die .NET-Exceptions missbrauchen. (sogar serialisieren lassen sie sich :-) )

Jetzt möchte ich gerne wissen, ob das so "sauber programmiert" ist.
Im Prinzip ist eine Exception eine "Nichtbeachtung der Methodenhirarchie" und führt somit auch zu Spaghetticode.
Auf der anderen Seite ist es eine etwas mächtigere Version von Return in VB.NET. Wenn ein Thread abgebrochen wird, löst das Framework eine ThreadAbortException aus, die nicht abgefangen aber behandelt werden kann und nicht in einer Fehlermeldung endet.

Ist das sauber oder nicht?
 
Original geschrieben von Sunray

Jetzt möchte ich gerne wissen, ob das so "sauber programmiert" ist.

Nein ist es nicht. Erstens bringt die Erstellung von Exceptions einen riesen Overhead da
Exceptions auch ein haufen Informationen der Virtuellen Mashine beherbergen und sich
die Exception erst bei der Runtime darüber erkundigen muss.

Zweites sind Ausnahmen nunmal Ausnahmen. Sprich Profiler Debugger und sonstige
Tools behandeln dies auch so, eine maschinelle Überprüfung deines Codes endet im Chaos.

Drittens wenn einer deinen Code verstehen soll muss er sich erst mit einer komplett
falschen Art der Programmierung anfreunden.

Wenn du ein Eventhandling haben willst das innerhalb einer Methode events auslöst
und diese dann "Goto " entsprechend laufen dann kannst du ganz einfach listener
bzw (huch ich bin im .net Forum) delegates implementieren die genau das machen. Aber
selbst hier ist die Frage ob es sinnvoll ist.
 
Ok.

Ich habe bei meinem Projekt mehrere verschachtelte Prozeduren mit Rückgabewerten. Während dieses Ablaufs können verschiedene Situationen zum Abbruch des Vorgangs führen. Woher soll eine Methode, die sich 2-3 Ebenen oberhalb befindet wisse, ob es ein erwartetes, ein unerwartetes Ende, oder ein ungültiges Zeichen war?

Soll ich jetzt eine Klasse (Werttyp oder Objekttyp?) erstellen um den Grund des Abbruchs an die jeweils nächsthöhere Ebene zu übermitteln?
Diese Lösung passt mir irgendwie nicht.

Könntes du mir das mit den Informationen in der Virtual Machine genauer erklären oder hast du gerade einen Link?

Ob Fehler oder Erfolgsmeldung ist egal. Bei Ersterem wird halt eben eine Fehlermeldung ausgegeben, was ansonsten nicht der Fall ist.
Diesen Tools kann es doch egal sein, ob eine Ausnahme "schlecht" oder "gut" ist.

Ich will keine Recalls oder Delegates. Ich möchte einen Methodenabbruch, der über mehrere Ebenen wirksam ist und implizit an die nächsthöhere Ebene weitergegeben wird.

Was gibt es für Alternativen?
 
Exceptions weiterreichen. Damit bekommst die Exception in die erste Ebene zurück, worauf die Abbrechen kannst.

Bei einer Exception irgendwas aufzurufen was das ganze Abbricht macht keinen Sinn und Programme sollten auf diese Art nicht programmiert werden, die Exception jedoch eine Ebene höher weiterzureichen ist jedoch legitim und macht auchdurchaus Sinn.
 
Das sollte ungefähr so aussehen:
Code:
throw new Exception();
throw new FileNotFoundException();
throw new ArgumentException();
Allen kann man Parameter übergeben wie z.B. die Exception.Message.
Damit kannst Du in deiner Übergeordneten Instanz ermitteln was die Exception ausgelöst hat.

Achtung! Lasse keine Exception von selber entstehen um zu prüfen ob was geklappt hat oder nicht.
Prüfe ob "null", zuviel oder zu wenig vohanden ist da sonst der JIT selbst analysieren muss, was für eine Exception ausgelöst wurde und das kostet Zeit, viel Zeit.
Ich lasse mich auch gerne Korrigieren.

MFG cosmo
 
Es ging eigentlich darum einen Vorgang durch Exceptions abzubrechen, sobald ein Ergebnis vorliegt. Dazu habe ich meine eigene Exception-Klasse (von ApplicationException abgeleitet), die beliebig viele Methoden-Ebenen "überspringen" kann um ihren Wert (das Resultat in Form eines Objekts) zu übergeben.

Ich wusste nämlich zum vornherein nicht, welche Methode ein Resultat zurück liefern wird Zudem hatte ich noch mit dem Problem zu kämpfen, dass einige dieser Methoden bereits Funktionen sind. Das "Resultat" sollte durch mehrere z.T. voneinander abhängige Vorgänge ermittelt werden und wenn ein Vorgang "per Zufall" auf die Lösung stösst, bricht er die gesamte Suche durch eben diese Exception ab.

Ich habs jetzt anders gelöst, Exceptions wohl wirklich nicht gerade Performance fördernd sind...
 
Sorry, dass ich mir hier etwas unqualifiziert einmische.
Ich kenne .NET nicht, sondern Exceptions nur aus Java.
In Java kannst Du einer Methodedeklaration mitgeben, dass die Methode eine Excepion werfen kann. Damit ist jede aufrufende Methode gezwungen diese Exception mit try-catch zu fangen oder selber mit der Deklaration weiterzugeben.
So erhältst Du die Exception auch weiter oben und kannst den Grund für den Abbruch erfahren.
Wenn es das in .NET auch gibt, ist das IMHO keine unsaubere Art zu programmieren, wenn es nicht dazu ausartet, nur noch mit Excepstions zu rechnen, anstatt if-Abfragen und ander Konstrukte zu verwenden (hab ich schon gesehen, das geht! :confused: ).
Vom Sprachgebrauch her solltest Du Dir aber schon überlegen, ob Deine Abbruchkriterien Ausnahmen sind oder eher die Regel. Fehleingaben eines Users sind IMHO zum Beispiel Ausnahmen, die ich in der Regel über Exceptions abfange.
 
Du hast Dich unqualifiziert eingemischt!

Wenn Du falsche Eingaben durch Exzeptions abängst machst Du es noch schlimmer.
Ich zitiere mich selber:
Achtung! Lasse keine Exception von selber entstehen um zu prüfen ob was geklappt hat oder nicht.
Prüfe ob "null", zuviel oder zu wenig vohanden ist da sonst der JIT selbst analysieren muss, was für eine Exception ausgelöst wurde und das kostet Zeit, viel Zeit.
Ich lasse mich auch gerne Korrigieren.
Wenn man prüfen will ob eine Zahl oder ein Buchstabe eigegeben worden ist, könnte man auch das Regex-Objekt hernehmen und man muss nicht die Konvertierung abschmieren lassen um herauszufinden was passiert ist. Punkt.

Es ist natürlich eine andere Sache wenn man selber die Exceptions mit
Code:
throw new IrgendEineException( Parameter );
auslöst. Alles klar?
 
Zuletzt bearbeitet:
Halli und Hallo,
eine sehr interessante Diskusion, so ich finde. Also aus meiner Sicht ist es nicht falsch Anwendungsexceptions zu entwicken. Natürlich kommt es auf den tieferen Sinn an.
Sinn einer Excepion, wie hier schon gesagt wurde, soll immer eine Ausnahmebehandlung sein, also nichts fachlich Reguläres.
So weit ich es programmierhistorisch verfolgen konnte entstand der Wunsch nach Excepions vermutlich auf diese Weise....
In der Prozeduralen Welt gab es vor allem in der Sprache C (und ähnlchen), Rückgabewerte, die dann mittels Fallunterscheidung (if-then-else oder switch) abgefragt wurden, um zu erfahren, ob etwas geklappt hat oder nicht und warum nicht etc.
Nun ist es aber so, dass, wenn man jeden Funktionsaufruf, der Erfolgsmeldungen (hier seien mathematische funktionen außen vor) rausgibt, anschließend mit Fallunterscheidungen beglückt, der Code, aus lauter Fallunterscheidungen bestehend, irgenwann unübersichtlich werden kann, da das eigetnlich Fachliche nur wenige Zeilen des Gesamtcodes betreffen würde. Erschwehrend kommt hinzu, dass z.B. C wenig restrictiv ist, so dass viele undisziplinierte Programmierer die Erfolgsabfragen nicht immer machen. Also dort ist mit reinen Returncodes gelegentlich Gefahr im Verzuge, da vielleicht der Programmierer nicht alles abgetestet hat, sei es aus Faulheit oder aus Vergesslichkeit.
Exceptions sollten eigetnlich diese 2 Phenomäne lösen, 1. durch gnadenlosen Abbruch des funktionsblockes mit dem Ziel nicht jede Mehtode mit Fallunterscheidungen beglücken zu müssen und den Code damit wweniger aufzublähen, 2. mit selbigem Mechnaismus der Vergesslichkeit einiger Programmierer entgegenzuwirken.
Es ist, so sehe ich es zumindest, natürlich eine Gradwanderung was man als Entwickler für ein Ausnahmeverhalten hält und was nicht.
Der Exceptionmechnanismus ist, wie hier schon von den vorherigen Beträgen angemerkt wurde, mit Overhead verbunden. Jedoch sollte man sich überlegen, ob dieser Overhead bemerkbar ist oder nicht. In einer Dialoganwendung ist des dem Anwender egal, ob etwas sagen wir mal 1 millisekunde oder 100 millisekunden dauert. Er bekommt es gar nicht mit. In einer langlaufenden Batchanwendung kann das schon wieder anders sein, denn hier summiert es sich.
Eingabefehler durch Anwender, sind meines Erachtens nicht notwendigerweise falsch als Ausnahme zu empfinden. Ich selbst verwende da einen Exceptionhandler-mechanismus (er ist quasi nach Dekorater-Pattern eigengebraut)
Damit ist es möglich z.B. bei Anwendereingabefehlern, die nicht direkt durch das verwendete Guielement unterbunden werden können, wie z.B. Texteingabefeld lässt nur Zahlen zu, sehr codezentralisiert Fehlermeldungen auszuspucken. Das kommt dann z.b. zum Tragen wenn man im Code nur mit Fehlerzahlen rumjongliert und dann irgenwann zentralisiert in Texte umwandeln möchte. Ein Dialog, der den Benutzer dann auf seinen Fehler hinweist, würde nicht überall in jedem Panel bekannt sein, sondern nur dem speziellen Exceptionhandler, der selbst halt nur durch eine dekorierte ExceptionHandlerKlasse mitells Interface aufgerufen wird.
man würde also im Code in den meisten Fällen nur noch folgendes sagen
Code:
main()
{
   ...
   ExceptionHandler.setHandler(new MyExceptionHandler())
   ...
}

somefunction(Object x, Object y, Object z)
try
{
...  fachlicher Code ohne Abfrage auf aufgetretene Fehler...
}
catch (Exception ex)
{
   ExceptionHandler.handleException(ex)
}

Anstelle von
Code:
try
{
...  fachlicher Code ohne Abfrage auf aufgetretene Fehler...
}
catch (DieseException e1)
{
---  reagiere auf e1
}
catch (JeneException e2)
{
---  reagiere auf e2
}
catch (DieseException ex)
{
---  reagiere auf ex
}
in Code ganz ohne Exceptions wäre es vermutlich so ...
Code:
...
{
...
  int rc =  funkotionA (x, y, z)
  switch(rc)
  {
    case HAT_GEKLAPPT:
        rc =  funkotionB ()
        switch(rc)
        {
         ....
        }
         ....
    case EINBISSLE_FALSCH:
       ....
    case GANZ_FALSCH:
      ....
    default: // unbekannter returncode
     ....
  }

  rc =  funkotionC ()
  switch(rc)
  {
     ....
  }
...
}

Und da es nur wenige sehr disziplinierte Entwickler gibt (zumindest traf ich selbst nur auf sehr wenige), die braf alles erdenkliche abfangen zumal der Code ohne Exceptions wie im letzten angedeuteten Beispiel aufgebläht wird, können mit unter anwedungsfachliche Exceptions sinnvoll sein.

aber wie dem auch sei ... ein interessantes Diskusionsthema

Takidoso
 
hpvw hat gesagt.:
Sorry, dass ich mir hier etwas unqualifiziert einmische.
Ich kenne .NET nicht, sondern Exceptions nur aus Java.
In Java kannst Du einer Methodedeklaration mitgeben, dass die Methode eine Excepion werfen kann. Damit ist jede aufrufende Methode gezwungen diese Exception mit try-catch zu fangen oder selber mit der Deklaration weiterzugeben.
So erhältst Du die Exception auch weiter oben und kannst den Grund für den Abbruch erfahren.
Wenn es das in .NET auch gibt, ist das IMHO keine unsaubere Art zu programmieren.
Nur so zur Info, das ist auch unsauber: Why doesn't C# have exception specifications?.
 
Zurück