Exception oder selber bearbeiten
-
Achja, ein Gedanke fehlt noch:
In Deinem speziellen Fall, kann man möglicherweise den Fehler auch über einen assert prüfen.
Ein falscher Index deutet darauf hin, daß schon vorher was falsch gelaufen ist. Mach einen ordentlichen Entwicklungstest mit einer Debugversion Deines Programmes und beseitige die Ursachen der Fehler nicht die Wirkung. Dann können sich Deine Anwender über ein schnelles und stabiles Programm freuen.
Mfg Martin
-
Was soll das Programm noch sinnvolles tun, wenn es noch nicht einmal den Index richtig setzen kann?
Wenn dir da nichts einfällt, kannst du auch gleich std::terminate aufrufen.
-
Nein...das Spiel selber läuft tip top...ich habe dazu noch einen Editor gebastelt, mit der man auf jedes einzelne Rechteck zugreifen kann. Da kann es nun vorkommen, dass der Benutzer des Editors, einen falschen Wert eingibt. Exception oder eben wie ich es gemacht hab, dass sich die Funktion selber rettet.
Nicht nur beim IndexOperator sieht das so aus.Z.B. habe ich eine Funktion, mit welcher man die Textur setzen kann. Die Textures werden bspw. mit Zahlen von 1-4 dargestellt. Ich habe es nun so gemacht, dass wenn die Zahl > 4 || Zahl < 1 ist, dass der Wert garnicht verändert wird, sondern true zurückgegeben wird.
Darum geht es mir: Ist dieser Ansatz okay oder soll ich alles wegmachen und auf Exceptions setzen?
-
Weder noch. Benutzereingaben sollten möglichst früh validiert werden. In Deinem Index operator ist es zu spät.
Der Grund ist ganz einfach: Dein Objekt wird abhängig von dem UI.
-
Wie ich finde ist genau das der klassische Einsatzbereich für Exceptions.
Der User gibt etwas ein (du kannst nicht wissen was genau), du musst es prüfen und kannst erst dann damit was anfangen.
Es könnte jedoch bei dem Ändern selbst zu spät sein. D.h. du musst bzw. solltest vorher prüfen, ob die Eingabe gültig war.
So wie sich das bei dir anhört hast du quasi mehrere Möglichkeiten (die Anzahl ist im Vorraus zur Compiletime bekannt), wieso testest du die Abfrage nicht dahingehend?
Denn dass der operator[] (der auf Array Ebene arbeitet, so wie ich das verstanden habe) dies prüft würde ich zwar mit einem assert im Debug Modus testen, aber eben nicht mehr im Release.
-
mgaeckler schrieb:
Wenn die ¨Selbstheilung¨ nicht geht, ziehe ich die Signalisierung über die Rückgabe dem Werfen einer Ausnahme vor. Ausnahmen stören den Kontrollfluß
Erklär mal inwieweit das relevant ist.
mgaeckler schrieb:
und können von C Funktionen (auch, wenn das für die meisten von Euch keine Rolle spielen wird) nicht behandelt werden.
Same here, wieso sollte mich das kratzen?
mgaeckler schrieb:
Der Grund ist ganz einfach: Dein Objekt wird abhängig von dem UI.
Genau umgekehrt: das UI wird abhängig von der anderen Klasse.
Davon abgesehen sollte man sich wirklich überlegen ob der Indexing-Operator der richtige Platz für einen Range-Check ist, soweit geb' ich dir schon Recht.
@Testosteron
Grundsätzlich eine gute Sache dass dein Programm bei kaputten Level-Files nicht einfach abschmiert, sondern versucht wenigstens noch irgendwas zu laden. Bloss gehört das nicht in die ganzen Utility-Funktionen verstreut.
Wenn bei der "Texte-Wechsel" Funktion ne falsche Texturnummer übergeben wird, dann sollte die ein passendes assert() drinnen haben. Genau so für ungültige Indexe irgendwo.
Das Geradebieden von falschen aus Files (oder direkt vom User) gelesenen Werten machst du dann am besten genau dort wo du die Werte aus dem File bzw. vom User bekommst. Der restliche Code sollte sich darum nicht kümmern.
-
Meiner Meinung nach sollte eine exception das sein, was der Name schon sagt: eine Ausnahme (,die du nicht mehr im Griff hast). Alles Andere regele ich per Rückgabewert.
Zum Beispiel:
Wenn ein socket nicht erstellt werden kann, hole ich mit Sicherheit nicht gleich die ganz große Keule raus, sondern gebe halt zurück, daß das nicht geklappt hat. Wie er damit umgeht ist dann Sache des Aufrufers.
-
EOP schrieb:
Zum Beispiel:
Wenn ein socket nicht erstellt werden kann, hole ich mit Sicherheit nicht gleich die ganz große Keule raus, sondern gebe halt zurück, daß das nicht geklappt hat. Wie er damit umgeht ist dann Sache des Aufrufers.Ein socket der nicht erstellt werden konnte ist so ziemlich DAS PERFEKTE Beispiel dafür wo man auf jeden Fall und ohne Diskussion gefälligst eine Exception zu werfen hat.
Oder rufst du etwa auch überall new mitstd::nothrowauf?
Tjoah.
Soviel dazu.
-
hustbaer schrieb:
EOP schrieb:
Zum Beispiel:
Wenn ein socket nicht erstellt werden kann, hole ich mit Sicherheit nicht gleich die ganz große Keule raus, sondern gebe halt zurück, daß das nicht geklappt hat. Wie er damit umgeht ist dann Sache des Aufrufers.Ein socket der nicht erstellt werden konnte ist so ziemlich DAS PERFEKTE Beispiel dafür wo man auf jeden Fall und ohne Diskussion gefälligst eine Exception zu werfen hat.
[[Continue][Retry][Exit]] wäre mein Vorschlag.
hustbaer schrieb:
Oder rufst du etwa auch überall new mit
std::nothrowauf?Eigentlich schon. Was soll ich auch Besseres machen wenn ich per pointer ständig Datenmengen via PostMessage verschicken will?
Wenn new fehlschlägt gebe ich halt alles vorherige frei und beende den thread ordentlich weil's anscheinend sowieso nix mehr bringt. So löst sich alles im Guten auf. Und wenn ich gut gelaunt bin kriegt der Anwender auch noch ne Nachricht, die aussagekräftiger ist als "error 293647".EDIT:
Wenn 50 threads laufen und bei einem schlägt new wiesoauchimmer fehl - soll ich dann alles hinschmeissen. Alle 49 laufenden ergebnisse?
Wobei mir auch nicht ganz klar ist was das für ne Auswirkung auf Alles hat wenn ich aus nem thread raus ne exception schmeisse.
Vielleicht ist die CPU gerade mit vielen anderen Sachen beschäftigt und ne zehntel Sekunde später geht es wieder. Alles schon gehabt.
Ist ne Abwägungssache.
-
Ich hoffe sehr dass du gerade versuchst mich zu verarschen. Wie dem auch sei, die Sache ist nicht wert weiter diskutiert zu werden.
-
hustbaer schrieb:
mgaeckler schrieb:
Wenn die ¨Selbstheilung¨ nicht geht, ziehe ich die Signalisierung über die Rückgabe dem Werfen einer Ausnahme vor. Ausnahmen stören den Kontrollfluß
Erklär mal inwieweit das relevant ist.
Jede Störung des Kontrolflußes erschwert die nachträgliche Analyse des Quelltextes. Daher sollte sowas (z.B. return mittendrinnen, goto, break, continue, throw etc.) nur mit Bedacht eingesetzt werden.
hustbaer schrieb:
mgaeckler schrieb:
und können von C Funktionen (auch, wenn das für die meisten von Euch keine Rolle spielen wird) nicht behandelt werden.
Same here, wieso sollte mich das kratzen?
Wie ich schon schrieb, newbies, die mit C nix am Hut haben, kratzt das nicht. Du wirst es aber wohl kaum glauben, es wurde schon Software entwickelt, da hast Du noch in die Hose gemacht.
hustbaer schrieb:
mgaeckler schrieb:
Der Grund ist ganz einfach: Dein Objekt wird abhängig von dem UI.
Genau umgekehrt: das UI wird abhängig von der anderen Klasse.
Das wiederum kratzt mich überhaupt nicht. Hast Du es schon mal geschafft, erfolgreich das UI einer Bankingsoftware nur durch Austausch der Datenklassen in ein Grafikprogramm zu wandeln?
Mfg Martin
-
mgaeckler schrieb:
hustbaer schrieb:
mgaeckler schrieb:
Wenn die ¨Selbstheilung¨ nicht geht, ziehe ich die Signalisierung über die Rückgabe dem Werfen einer Ausnahme vor. Ausnahmen stören den Kontrollfluß
Erklär mal inwieweit das relevant ist.
Jede Störung des Kontrolflußes erschwert die nachträgliche Analyse des Quelltextes.
Ja und nein. Auf nen Einzelfall bezogen: ja. Wenn man öfter mit verschiedenen Stellen eines halbwegs konsequent aufgezogenen Programms zu tun hat: nein. Weil das ganze manuelle if-blah-else if-blub Gedöns einem den Schirm und das Hirn vollmüllt.
Wenn man sich dagegen einmal die Arbeit gemacht hat nachzuvollziehen wie die Exception-Safety in einem Programm funktioniert (also wie diverse Sentinel/Guard/... Klassen arbeiten und zusammenspielen), dann sieht man recht schnell wenn wo etwas nicht passt.
Genau so wie diese Mechanismen einem beim Programmieren Arbeit abnehmen, nehmen sie einem auch Arbeit beim Lesen/Fehlersuchen ab.mgaeckler schrieb:
Daher sollte sowas (z.B. return mittendrinnen, goto, break, continue, throw etc.) nur mit Bedacht eingesetzt werden.
Siehste, es ist genau umgekehrt: man sollte sich sehr sehr gut überlegen ob man in C++ anfangen will Dinge über Errorcodes zu machen die man normalerweise über Exceptions machen würde/sollte. Denn in den allermeisten Fällen muss man dann beides sicherstellen: 1x dass man überall brav die ganze widerliche manuelle Fehlerbehandlung richtig macht, UND dass das Programm trotzdem noch Exception-safe ist. Weil man in den meisten Programmen früher oder später einfach Komponenten hat die Exceptions werfen. Das fängt mit der Standard-Library an und geht mit haufenweise Thirdparty-Libraries weiter.
Und an allen Schnittpunkten try-catch zu schreiben kann ja wohl auch nicht die Lösung sein.Wenn man sich ein ganze eigenes Framework mit Hilfe von C Libraries selbst aufbaut, dann kann man es so machen. Die Frage bleibt aber immer noch ob man es dann so machen sollte.
mgaeckler schrieb:
hustbaer schrieb:
mgaeckler schrieb:
und können von C Funktionen (auch, wenn das für die meisten von Euch keine Rolle spielen wird) nicht behandelt werden.
Same here, wieso sollte mich das kratzen?
Wie ich schon schrieb, newbies, die mit C nix am Hut haben, kratzt das nicht. Du wirst es aber wohl kaum glauben, es wurde schon Software entwickelt, da hast Du noch in die Hose gemacht.
Uiiiiii, danke für die Aufklärung, Opi.
Wird für die meisten Leute die eine C++ Anwendung schreiben aber reichlich egal sein, nen?mgaeckler schrieb:
hustbaer schrieb:
mgaeckler schrieb:
Der Grund ist ganz einfach: Dein Objekt wird abhängig von dem UI.
Genau umgekehrt: das UI wird abhängig von der anderen Klasse.
Das wiederum kratzt mich überhaupt nicht. Hast Du es schon mal geschafft, erfolgreich das UI einer Bankingsoftware nur durch Austausch der Datenklassen in ein Grafikprogramm zu wandeln?
Du hast behauptet dass durch den Check im Indexing-Operator das Objekt abhängig vom UI wird. Ich behaupte dass es umgekehrt ist. Und nu?
-
hustbaer schrieb:
mgaeckler schrieb:
hustbaer schrieb:
mgaeckler schrieb:
Wenn die ¨Selbstheilung¨ nicht geht, ziehe ich die Signalisierung über die Rückgabe dem Werfen einer Ausnahme vor. Ausnahmen stören den Kontrollfluß
Erklär mal inwieweit das relevant ist.
Jede Störung des Kontrolflußes erschwert die nachträgliche Analyse des Quelltextes.
Ja und nein. Auf nen Einzelfall bezogen: ja. Wenn man öfter mit verschiedenen Stellen eines halbwegs konsequent aufgezogenen Programms zu tun hat: nein. Weil das ganze manuelle if-blah-else if-blub Gedöns einem den Schirm und das Hirn vollmüllt.
Wenn man sich dagegen einmal die Arbeit gemacht hat nachzuvollziehen wie die Exception-Safety in einem Programm funktioniert (also wie diverse Sentinel/Guard/... Klassen arbeiten und zusammenspielen), dann sieht man recht schnell wenn wo etwas nicht passt.
Genau so wie diese Mechanismen einem beim Programmieren Arbeit abnehmen, nehmen sie einem auch Arbeit beim Lesen/Fehlersuchen ab.Zustimmung. Deswegen sage ich ja auch immer, daß jedes Sprachmittel, seine Berechtigung hat. Man muß halt stets abwägen, ob Ihr Einsatz nachvollziehbar ist. Exceptions sind richtig angewended ein Segen.
hustbaer schrieb:
mgaeckler schrieb:
Daher sollte sowas (z.B. return mittendrinnen, goto, break, continue, throw etc.) nur mit Bedacht eingesetzt werden.
Siehste, es ist genau umgekehrt: man sollte sich sehr sehr gut überlegen ob man in C++ anfangen will Dinge über Errorcodes zu machen die man normalerweise über Exceptions machen würde/sollte. Denn in den allermeisten Fällen muss man dann beides sicherstellen: 1x dass man überall brav die ganze widerliche manuelle Fehlerbehandlung richtig macht, UND dass das Programm trotzdem noch Exception-safe ist. Weil man in den meisten Programmen früher oder später einfach Komponenten hat die Exceptions werfen. Das fängt mit der Standard-Library an und geht mit haufenweise Thirdparty-Libraries weiter.
Und an allen Schnittpunkten try-catch zu schreiben kann ja wohl auch nicht die Lösung sein.Wenn man sich ein ganze eigenes Framework mit Hilfe von C Libraries selbst aufbaut, dann kann man es so machen. Die Frage bleibt aber immer noch ob man es dann so machen sollte.
Richtig, die Sache mit den errorCodes hat nämlich auch üble Nachteile. Deswegen immer neu entscheiden, nie pauschale Antworten geben.
hustbaer schrieb:
Opi.
Noch nicht.
hustbaer schrieb:
Wird für die meisten Leute die eine C++ Anwendung schreiben aber reichlich egal sein, nen?
Wenn Du meinen Text aufmerksam gelesen hättest...
hustbaer schrieb:
mgaeckler schrieb:
hustbaer schrieb:
mgaeckler schrieb:
Der Grund ist ganz einfach: Dein Objekt wird abhängig von dem UI.
Genau umgekehrt: das UI wird abhängig von der anderen Klasse.
Das wiederum kratzt mich überhaupt nicht. Hast Du es schon mal geschafft, erfolgreich das UI einer Bankingsoftware nur durch Austausch der Datenklassen in ein Grafikprogramm zu wandeln?
Du hast behauptet dass durch den Check im Indexing-Operator das Objekt abhängig vom UI wird. Ich behaupte dass es umgekehrt ist. Und nu?
Das UserInterface st doch in den meisten Fällen abhängig von den Datenobjekten. Das UserInterface sollte auch genügend Wissen haben, Benutzereingben zu validieren. Stell Dir vor, das UI und die Objekte laufen auf unterschiedlichen Rechnern. Das wäre doch blöd, wenn das Frontend jedesmal über das Netzwerk das Backend befragen muß, ob die Eingabe gültig ist.
Das Backend braucht dann eigentich nur noch via assert beim Entwicklungstest prüfen.
Mfg Martin