if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von cloidnerux » Mi Aug 03, 2011 7:00 am

Java kam soweit ich weiß recht spät damit und bei C# bin ich mir gerade nichtmals im Klaren, ob sie existieren
Seit C# 4.0 schon.
Die Frage war aber eigentlich nach den Exceptions. Heißt Deine vorherige Antwort, dass sie einen anderen Vorteil haben oder dass sie überhaupt keinen Vorteil haben!?
C++ wurde auch nicht von Deppen geplant, von daher haben auch Exceptions einen nutzen. Das sie nun aber mehr schlecht als recht umgesetzt wurden, ist halt ein manko.
Was ich aber daran auch gut Finde, ist das man als Programmierer auch mal einen Fehler behandeln muss.
Das war bei einem Rückgabewert von fopen und co nicht so, habe ich es nicht kontrolliert ist es wo anderst abgestürzt.
So muss ich die Exception fangen und kann dann auch sagen, wo das Problem jetzt lag.
Andererseits ist es schlecht in einer Produktivsoftware ungefangene Exceptions zu haben, die dann zu Abstürzen führen.

Just my 2 cents.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Xin » Mi Aug 03, 2011 9:46 am

cloidnerux hat geschrieben:
Die Frage war aber eigentlich nach den Exceptions. Heißt Deine vorherige Antwort, dass sie einen anderen Vorteil haben oder dass sie überhaupt keinen Vorteil haben!?
C++ wurde auch nicht von Deppen geplant, von daher haben auch Exceptions einen nutzen. Das sie nun aber mehr schlecht als recht umgesetzt wurden, ist halt ein manko.
Weder sind Exceptions nutzlos, noch sind sie schlecht umgesetzt.
Sie sind nur schlecht genutzt.

Weil sie eigentlich fast nur schlecht genutzt werden, frage ich mich, ob es nicht mehr Sinn ergibt keine Exceptions zu ermöglichen und damit auf den Sinn von Exceptions zu verzichten, den ich noch nie verwendet gesehen habe.

Das Exceptionhandling von C ist eigentlich besser als das von C++/Java/C#. (Ja, es gibt ein Exceptionhandling in C - nur eben viel weniger, also benutzt man es auch nur in Ausnahmen).
cloidnerux hat geschrieben:Was ich aber daran auch gut Finde, ist das man als Programmierer auch mal einen Fehler behandeln muss.
Ich arbeite als professioneller Softwareentwickler und ich bin sehr bemüht, Fehler korrekt zu behandeln. Aus dieser Pespektive sage ich Dir, dass in der professionellen Softwareentwicklung es durchaus üblich ist Exceptions durch Ignorieren zu behandeln. Sie müssen ja behandelt werden: Klammer auf, Klammer zu, fertig. Damit sind Fakten geschaffen worden. Der Fehler ist nie aufgetreten, wird nie erwartet und muss trotzdem behandelt werden. Und nun wird er auch nie wieder auftreten.
Tritt diese Exception nun doch auf, verkompliziert sich die Fehlersuche massiv. Und das kommt unter'm Strich dabei heraus. Das ist übrigens der optimistische Fall. Häufig findet man auch catch( Exception e ) {}, da verfängt sich dann auch alles, was später mal entwickelt wurde und beliebige Exceptions wirft.
Statt eines einfachen Fehlers habe ich nun einen eventuell mächtig komplizierten.
cloidnerux hat geschrieben:Das war bei einem Rückgabewert von fopen und co nicht so, habe ich es nicht kontrolliert ist es wo anderst abgestürzt.
So muss ich die Exception fangen und kann dann auch sagen, wo das Problem jetzt lag.
Oder die Exception verfängt sich, wird als bearbeitet definiert und das Objekt, dass nicht geladen werden konnte als valide.
So fliegt eine neue Exception, die sich - wenn Du Glück hast - nicht verfängt und Du findest ein invalides Objekt und hast keine Ahnung, warum das invalid ist. Seit dem Ladevorgang sind viele Anweisungen vergangen.

Mein persönlicher Rekord im Exception-Ping-Pong sind drei Sätze. Das Programm crasht für Objekt A und warf eine Exception, die ignoriert wurde, was dazu führte, dass anderswo eine Exception für Objekt B geworfen wurde, die ignoriert wurde, was dazu führte, dass eine dritte Exception geworfen wurde, weil nun Objekt B krankt, die auch ignoriert wurde, was dazu führte, dass das Programm in meinem Abschnitt an einer Stelle fehlschlug, die ich wie blöd getestet habe und die definitiv funktionierte. Es kam aber halt ein absolut kaputtes Objekt C in den Algorithmus. Und jetzt muss man den Fall finden, an dem Objekt A die Exception wirft und den Ablauf, der dazu führt, dass über ein kaputtes B ein kaputtes C bei mir ankommt.

Das Debuggen hat mich sehr viel Zeit gekostet, ich habe dabei reichlich Fehler von Kollegen gefixt aus Bereichen, mit denen ich überhaupt gar nichts zu tun hatte. Da muss man erst mal verstehen, was da abgeht. Ich habe einen Netzwerkservice programmiert und dabei Interna einer Suchmaschine gefixt. Das macht mich nicht gerade produktiv, wenn es darum geht meinen Auftrag - den Netzwerkservice - zu erledigen.

Das ist professionelle Softwareentwicklung mit Exceptions.

Wäre der Ladevorgang in Deinem Beispiel fehlgeschlagen, weil Du fopen() nicht kontrolliert hättest, wäre das ein direktes Resultat, weil der FileStream invalid ist, Du baust die Abfrage bei fopen ein und fertig. Die Wirkung ist direkt mit der Wirkung verbunden.

Darum vermeide ich Exceptions: Zu teuer in der Entwicklung. Ich schreibe - privat - Compiler, Netzwerkdienste, Suchmaschinen, Wikis. Nicht in Vollzeit. Eine derartige Exception-Debugging-Session kann mich ein halbes oder ein ganzes Jahr kosten. Exceptions sind für mich kein kalkulierbares Risiko.

Man kann jetzt sagen, dass die Entwickler entsprechend dämlich sind - und das stimmt - aber die Fehlerbehandlung von Exceptions ist aufwendig, der Druck Features fertig zu stellen groß und wenn's erstmal funktioniert, dann läuft's doch... Professionelle Entwickler sind auch nur Menschen. Wenn die Wenn die Fehlerbehandlung von ausgebildeten Informatikern derart verhunzt wird, wer soll dieses Sprachfeature dann korrekt anwenden?

Exceptions sollen in der Theorie Fehler bekämpfen.
Meiner Erfahrung nach machen sie in der Realität Software irreparabel kaputt. Müsste ich ein Jahr wegen eines Exception-Ping-Pongs debuggen, müsste ich irgendwann alle Projekte am Stück sterben lassen, da alle meine Projekte auf der selben Codebasis laufen. Was als URL in den Webserver reinkommt, geht als Datentyp 'url' durch den Compiler, wird vom Wiki als Linksammlung verwendet.


In der Firma, in der ich jetzt arbeite haben wir auch Exceptions. Es gibt eine Assert-Makro, die eine Exception wirft. Schlägt das Assert fehl finde ich mich urplötzlich in der Exeptionbehandlung wieder, die erklärt, dass welches Assert explodiert ist. Werte? Stacktrace? Ich weiß nur, dass eine Bedingung nicht erfüllt wurde. Das kann ein Assert auch nicht leisten, denn mehr als eine Bedingung, die erfüllt sein soll, hat es nicht.

Ich habe dieses Makro jetzt mit einem Präprozessor-Schalter für mich geändert. Schlägt das Assert fehlt, schreibe ich auf Adresse 0 den Wert 0. Das Programm hängt sich sofort auf, Visual Studio bleibt stehen und ich stehe genau an der Stelle, an der das Assert hakt, kann mir den Stacktrace und alle Werte betrachten.

Ob ich den Eintrag ins Protokoll über das Makro schreibe oder über ein catch() spielt für das Log keine Rolle. Für mich aber schon.

Genauso mache ich es mit dem GCC, ich es gibt sogar eine Klasse XSD::Util::Crash, die zuerst die Ankündigung des Crashs ins Log einträgt und dann einen tödlichen Fehler initiiert. gdb hält an und ich kann mir gemütlich angucken, wie ich hier eigentlich hingekommen bin und warum.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Panke
Beiträge: 70
Registriert: So Nov 14, 2010 10:47 am

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Panke » Mi Aug 03, 2011 12:05 pm

Man hätte doch das gleiche Problem, wenn in Objekt A ein Fehlercode nicht geprüft wird und daher ein
falsches Objekt B an Objekt C weitergereicht wird.

Im Grunde ist es doch genau umgekehrt: Mit Exceptions wäre eigentlich bei A das Programm schon abgestürzt und
man hätte den Fehler schnell gefunden. Dass Java dich zwingt die Nicht-RuntimeErrors (sry, Java ein bisschen her)
zu fangen, ist der Fehler. Nicht Exceptions selbst. Ohne den Zwang wär dein Programm bei Objekt A abgestürzt, genau wie es soll.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Xin » Mi Aug 03, 2011 12:17 pm

Panke hat geschrieben:Man hätte doch das gleiche Problem, wenn in Objekt A ein Fehlercode nicht geprüft wird und daher ein falsches Objekt B an Objekt C weitergereicht wird.
Ein nicht beachteter Fehlercode, zum Beispiel ein FILE *, das NULL ist, sorgt dafür dass die nachfolgende freadf()-Anweisung knallt. Bei einer Exception wird die freadf() nicht mehr erreicht.
Panke hat geschrieben:Im Grunde ist es doch genau umgekehrt: Mit Exceptions wäre eigentlich bei A das Programm schon abgestürzt und man hätte den Fehler schnell gefunden.
Leider nicht. Das Programm warf die Exception, die Exception wurde ignoriert und das Programm lief weiter.
Panke hat geschrieben:Dass Java dich zwingt die Nicht-RuntimeErrors (sry, Java ein bisschen her)
zu fangen, ist der Fehler. Nicht Exceptions selbst. Ohne den Zwang wär dein Programm bei Objekt A abgestürzt, genau wie es soll.
Erstens zwingt Java Dich, zweitens kann die Fehlerbehandlung falsch sein - was sie in dem Fall ja auch ist. Die Fehlerbehandlung kann mit Exceptions ohne Bezug auf den Fehler durchgeführt werden. Damit scheiden Exceptions auch bei Sprachen ohne Zwang aus.

Exceptions können eine korrekte Fehlerbehandlung prinzipgesteuert nicht garantieren. Fehlercodes schon.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Panke
Beiträge: 70
Registriert: So Nov 14, 2010 10:47 am

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Panke » Mi Aug 03, 2011 12:33 pm

Exceptions können eine korrekte Fehlerbehandlung prinzipgesteuert nicht garantieren. Fehlercodes schon.
Das musst du erläutern.
Das Programm warf die Exception, die Exception wurde ignoriert und das Programm lief weiter.
Exceptions zu ignorieren, ist wie immer new aber nie delete aufrufen. Manchmal klappts, in der Regel aber nicht. Daraus zu schließen, mit new und delete sei keine Speicherverwaltung möglich, ist aber haarig.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Xin » Mi Aug 03, 2011 1:53 pm

Panke hat geschrieben:
Exceptions können eine korrekte Fehlerbehandlung prinzipgesteuert nicht garantieren. Fehlercodes schon.
Das musst du erläutern.
Ich kann in der semantischen Analyse der Funktion, die die Exception wirft, nicht prüfen, ob die Exception gefangen wird, weil mit einer Exception der lineare Programmablauf unterbrochen wird. Das entspricht gewissermaßen einem goto, ohne dass ich das Ziel kenne.

Ich kann aber prüfen, ob ich die Fehlercodes ignoriere.
Panke hat geschrieben:
Das Programm warf die Exception, die Exception wurde ignoriert und das Programm lief weiter.
Exceptions zu ignorieren, ist wie immer new aber nie delete aufrufen. Manchmal klappts, in der Regel aber nicht. Daraus zu schließen, mit new und delete sei keine Speicherverwaltung möglich, ist aber haarig.
Vielleicht fällt Dir auf, dass genau das gerade ein Trend ist. Oder rufst Du in Java oder C# noch delete auf?

Ansonsten: Ich stimme Dir zu, ich mag lediglich nicht die Möglichkeit, wie Java und C# darauf reagiert haben. Mit new und delete ist in C++ eine sichere Speicherverwaltung prinzipiell nicht zu garantieren.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Panke
Beiträge: 70
Registriert: So Nov 14, 2010 10:47 am

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Panke » Do Aug 04, 2011 9:30 am

Ich kann in der semantischen Analyse der Funktion, die die Exception wirft, nicht prüfen, ob die Exception gefangen wird, weil mit einer Exception der lineare Programmablauf unterbrochen wird. Das entspricht gewissermaßen einem goto, ohne dass ich das Ziel kenne.
Das ist richtig. Die Funktion allein zu prüfen reicht nicht, du musst auch den Kontext prüfen. Das Ziel des Goto ist ja sehr wohl definiert.
Ich kann aber prüfen, ob ich die Fehlercodes ignoriere.
Genau das gleiche Problem wie bei Exceptions. Was ist, wenn du den Fehler nur an die aufrufende Funktion weiterreichen willst? Dann reicht die Prüfung einer einzigen Funktion eben nicht aus.
Außerdem kannst du eh nicht prüfen, ob etwas sinnvolles machst, sondern nur ob du überhaupt etwas machst. Das ist ja gerade der Irrweg, der bei Java zu den fang-alles- und fangen-aber-verwerfen-Fehlern führt. Und wenn ein Fehler auftritt, den ich noch nicht behandelt habe, will ich dass mein Programm mit einer hoffentlich halbwegs guten Fehlermeldung abschmiert. Das garantieren - bei Beachtung simpler Programmierregeln - Exceptions. Fehlercodes stützen sich darauf, dass vielleicht der folgende Code abstürzt, das ist aber nicht garantiert. Und kann ebenso zu Problemen wie von dir beschrieben führen. Und eine Fehlermeldung haben sich auch nicht im Bauch. Ich schrieb neulich einen kleinen Server. Der stürzte relativ häufig ab mit
what() : Port already in use
Kein Problem, hatte halt eine andere Instanz laufen. Wäre er mit
segmantation fault
oder etwas ähnlichem abgestürzt,
hätte ich einen eher schwierig zu reproduzierenden Fehler gehabt, den
ich erstmal hätte suchen müssen. So hat mich das nicht eine Sekunde gekostet.

Du hast noch gar nicht dargelegt, wie der Fehlercode-Mechanismus von dir aussehen soll. Vielleicht reden wir auch aneinander vorbei.

Folgendes Szenario: Ich habe einen relativ komplexen Algorithmus, der viel Speicher frisst. Sagen wir aus dem Bereich KI und Planung. Die sind ja immer im Grunde Suchverfahren mit Backtracking mit kleveren Heuristiken. Ich kann eine gewisse Suchtiefe angeben und der Speicherverbrauch ist exponentiell zur Tiefe. Jetzt will ich folgendes machen können:

Code: Alles auswählen

while(!done) {
try { 
    search(depth=20);
} catch(std::bad_alloc e)
{
    // tja, nicht genug Speicher für depth=20. Zum Glück sind Exceptions
    // mehr als ein goto und "search" garantiert mir, dass es im Falle einer
    // Ausnahme einen konsistenten, aufgeräumten Zustand hinterlässt durch
    // Stack Unwinding und RAII. Also kann ich hier einfach weitermachen.
}
try {
    search(depth=10)
} catch(std::bad_alloc e)
{ 
    // ach, scheiß drauf. das wird nichts mit der Suche.
    return false;
} // while
Wenn search jetzt die Funktionen foo, fart, faz, bar, bart, batz aufruft, möchte ich nicht
in so einem Callstack
foo
----fart
-------- faz
------------ bar
---------------- bart
-------------------- batz
In jeder Funktion den Fehlercode bei jeder Allocation prüfen und eventuell reagieren müssen. Mit Exceptions knallt mir mein
Bad-Alloc -- ohne, dass ich mich in foo, fart, faz, bar, bart, batz drum kümmern muss -- einfach bis nach
oben durch. Das ist doch der Vorteil von Exceptions. Das können Fehlercodes leider nicht.
Umgekehrt krieg ich mit Exceptions alles hin, was Fehlercodes auch können.

Folgender Code:

Code: Alles auswählen

 
A a;
// a hier richtig initialisiert?
Mit Exceptions kein Problem. Mit Fehlercodes? Entweder immer ein Aufruf mehr oder man macht nicht triviale Initialisierung in einer
init-Methode. Auch nicht schön.

Ich behaupte nicht, dass Exceptions der Weisheit letzter Schluss sind, aber jeder Ersatz muss mindestens den gleichen Komfort bieten. Die Alternative ist nicht, zu Fehlerbehandlung der 80iger Jahre zurückzukehren. Die ist eben nicht gleichwertig. Und der Hauptkritikpunkt an Exceptions scheint ja >catch-all, weil faul< zu sein. Das ist aber kein Problem von Exceptions an und für sich, sondern daran, dass Java es einfacher macht, leere catch-Klauseln von Exclipse generieren zu lassen, als erst gar keine hinzuschreiben.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Dirty Oerti » Do Aug 04, 2011 10:51 am

Meiner Ansicht nach sind Exceptions in der Anwendung, wie du sie oben beschreibst (mit deinem Callstack da) eine ernstzunehmende Gefahr für guten, sinnvollen Code.
Denn das Grundprinzip in der Programmierung lautet immer noch Abstraktion.
Wenn also ein Fehler auf unterster Ebene auftritt, dann will ich mich mit diesem Fehler nicht auf einer hohen Ebene arbeiten müssen. Ich will auf Anwendungsebene keine Exception fangen müssen, die durch ein Low Level Problem ausgelöst wurde.
Solche Probleme haben die "unteren" Ebenen zu lösen, wenn sie es nicht schaffen, schafft es die obere auch(erst recht) nicht, und die obere Ebene sollte nur wissen, dass es falsch gelaufen ist, nicht, ob eine Speicherallozierung oder sonstwas fehlschlug.

Das ist meiner Ansicht nach der Vorteil von Return Codes, ich MUSS sofort überprüfen, ob alles im Lot ist, weiterreichen ist schwer bis gar nicht möglich.

Ein Queraspekt hier ran ist aber z.B. das Logging. Es sollte natürlich trotzdem die genaue Ursache des Fehlers in eine Logdatei geschrieben werden.
Dieses Problem, dass das Logging schwer unterzubringen ist, entstand durch die Objektorientierte Programmierung.
Logging ist nunmal kein Objekt, sondern ein Aspekt.
Deswegen hab ich hier auch das Buch Aspektorientierte Programmierung (auch wenn das etwas zu heftig ist, es gibt wohl einfachere Lösungen)
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Panke
Beiträge: 70
Registriert: So Nov 14, 2010 10:47 am

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Panke » Do Aug 04, 2011 10:58 am

Ich will auf Anwendungsebene keine Exception fangen müssen, die durch ein Low Level Problem ausgelöst wurde.
Solche Probleme haben die "unteren" Ebenen zu lösen, wenn sie es nicht schaffen, schafft es die obere auch(erst recht) nicht, und die obere Ebene sollte nur wissen, dass es falsch gelaufen ist, nicht, ob eine Speicherallozierung oder sonstwas fehlschlug.
Wie würde denn eine äquivalente Lösung mit Fehlercodes aussehen, bei der ich den Vorgang nochmal mit geringerer Suchtiefe starte? Das der Speicher weg ist, ist zwar ein low-level-Problem. Aber hier ist ja gerade ein Beispiel, wo der Anwendungscode das Problem beheben kann. Aber erst einige Ebenen im Callstack weiter oben.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: if( Konzept && !Konzept ) { printf( "Lehrmeinung?" );

Beitrag von Dirty Oerti » Do Aug 04, 2011 10:23 pm

? Du meinst, die Anwendungsebene sollte hier dann "intelligenterweise" entscheiden, noch mal zu suchen, aber dafür halt nicht alles zu suchen?
Das halte ich persönlich für vollkommenen Quatsch.
Wenn die Suche zu viel Speicher verbraten kann, dann muss sie eine eigene Speicherverwaltung haben.
Dann tritt das Problem nicht auf.

Das ist meiner Ansicht nach also keine Aufgabe einer Anwendungsebene sondern schlicht und einfach ein Planungs/Designfehler. Theoretisch würde ich das sogar mit einem ASSERT o.ä nur überprüfen, weil der Fehler im Produktivsystem nicht aufzutauchen hat. Wenn er auftaucht, dann ist es kein Fehler des Programmablaufs, sondern schlicht und einfach ein Fehler des Programmierers bzw dessen Unfähigkeit :)

Wenn du von mir eine konkretere Antwort erwartest, dann brauche ich ein konkretes Beispiel :)
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Antworten