| Autor |
Nachricht |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 4840
|
cooky451 Mitglied
21:45:12 01.02.2012 Titel: |
Exception Practice |
Zitieren |
Hey,
ich würde ja eine Umfrage draus machen, aber das geht hier nicht. Na ja, Erklärungen sind ja auch ganz interessant.
Mich würde interessieren, wie ihr mit Exceptions umgeht. Üblicherweise erbt man ja von std::runtime_error, das macht wahrscheinlich jeder. (Oder man wirft gleich std::runtime_error) Aber:
- Wenn es zu der Exception einen Fehlercode gibt (z.B. bei socket Fehlern), kümmer ihr euch um den? Falls ja, übergebt ihr den einfach der Exception und schreibt der noch eine error_code() Methode? Oder baselt ihr vorher einen String mit dem Errorcode zusammen? Oder bastelt ihr den in der Exceptionklasse?
- Fangt ihr einfach std::runtime_error und gebt .what() aus? Oder macht ihr euch z.B. ganz viele verschiedene Exceptionklassen, sodass ihr beim Fangen schon in etwa wisst, was das für ein Fehler war? (socket_error, file_error, ..., std::runtime_error) |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
|
|
 |
seldon
Unregistrierter
|
seldon Unregistrierter
21:51:28 01.02.2012 Titel: |
|
Zitieren |
Eigentlich ist es meistens nicht besonders elegant, von std::runtime_error zu erben; std::logic_error ist meistens angebrachter. Das "runtime" in "runtime_error" ist nicht als "Fehler zur Laufzeit" zu verstehen, sondern als "Fehler in der Laufzeitumgebung" - deswegen erben overflow_error und underflow_error von runtime_error, während invalid_argument, out_of_bounds etc. von logic_error erben - das meint "Fehler in der Programmlogik", also quasi "ein anderer Programmteil hat mir Unfug angedreht."
Die Unterscheidung ist allerdings ziemlich vage und nicht besonders praktisch. Meistens erbe ich von std::logic_error und fange std::exception (oder halt konkret den Exceptiontyp, den ich selbst definiert habe). Fehlercodes speichere ich ggf. natürlich als Zahl und nicht als String - das wär ja albern. |
|
|
|
 |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 4840
|
cooky451 Mitglied
22:00:41 01.02.2012 Titel: |
|
Zitieren |
| seldon schrieb: | "Fehler in der Programmlogik"
| Danke für den Tipp. Bei meinen Beispielen allerdings scheint mir runtime_error durchaus angebracht. (Sockets, Dateien)
| seldon schrieb: | | Fehlercodes speichere ich ggf. natürlich als Zahl und nicht als String - das wär ja albern. |
Nun ja, dann musst du aber auch alle Exceptions unterschiedlich fangen. Denn ansonsten könne man auch einfach eine Basisklasse fangen, und in den jeweiligen Spezialisierungen einen vollständigen Fehlerstring zusammenbasteln.
Das hälst du nicht für wünschenswert? |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
|
|
 |
Mechanics
Mitglied
Benutzerprofil
Anmeldungsdatum: 27.01.2012
Beiträge: 432
|
Mechanics Mitglied
22:19:44 01.02.2012 Titel: |
|
Zitieren |
Ich versuche normal die möglichen Fehlerursachen in eigene Exceptions zu fassen und sie auch zu behandeln. Den String mit der Fehlermeldung kann ich dann in der Gui zusammenbauen. Etwas banales Beispiel, wenn ich eine Funktion aufrufe und weiß, sie kann eine IndexOutOfRange, eine DivisionByZero und eine InvalidParameter Exception schmeißen, dann kann ich an der Stelle wo ich sie aufrufe das auch abfangen, denn ich weiß normalerweise, woran das dann liegt, wenn so eine Exception kommt. Wenn ich den Fehler aber nicht im Griff habe, wird es etwas schwieriger. z.B. bei der Netzwerkkommunikation, wo 50 verschiedene Fehler kommen können. Dann reicht es aber vielleicht ersteinmal eine entsprechende NetworkCommunicationException zu schmeißen und dann weiß man, ok, bei der Kommunikation ist was schiefgelaufen und dann evtl. weiter nachforschen, z.b. über den Fehlercode, um dem Benutzer eine aussagekräftige Fehlermeldung (wie Passwort falsch oder Server nicht erreichbar) anzuzeigen. |
|
|
|
 |
seldon
Unregistrierter
|
seldon Unregistrierter
22:51:31 01.02.2012 Titel: |
|
Zitieren |
| cooky451 schrieb: |
| seldon schrieb: | | Fehlercodes speichere ich ggf. natürlich als Zahl und nicht als String - das wär ja albern. |
Nun ja, dann musst du aber auch alle Exceptions unterschiedlich fangen. Denn ansonsten könne man auch einfach eine Basisklasse fangen, und in den jeweiligen Spezialisierungen einen vollständigen Fehlerstring zusammenbasteln.
|
Die what()-Methode gibt's ja nach wie vor, und wenn ich den Fehlercode direkt brauche, kann ich mit std::exception eh nichts anfangen. Ich meine das etwa so:
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Für diese Dinge benutze ich dann gerne X-Makros, um mir keine Gedanken
// um die Synchronisation zwsichen Fehlercode und Fehlermeldung machen zu müssen.
enum error_code {
ERR_SUCCESS,
ERR_FEHLER1,
ERR_FEHLER2,
...
};
extern char const *const error_messages[];
// Hier nicht von std::logic_error, weil kein std::string gebraucht wird, um
// die Fehlermeldung aufzubewahren.
class my_exception : public std::exception {
public:
my_exception(error_code ecode) : ecode_(ecode) { }
virtual ~my_exception() throw() { }
virtual error_code code() const throw() { return ecode_; }
virtual char const *what() const throw() { return error_messages[ecode_; }
private:
error_code ecode_;
};
| |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Für diese Dinge benutze ich dann gerne X-Makros, um mir keine Gedanken
// um die Synchronisation zwsichen Fehlercode und Fehlermeldung machen zu müssen.
enum error_code {
ERR_SUCCESS,
ERR_FEHLER1,
ERR_FEHLER2,
...
};
extern char const *const error_messages[];
// Hier nicht von std::logic_error, weil kein std::string gebraucht wird, um
// die Fehlermeldung aufzubewahren.
class my_exception : public std::exception {
public:
my_exception(error_code ecode) : ecode_(ecode) { }
virtual ~my_exception() throw() { }
virtual error_code code() const throw() { return ecode_; }
virtual char const *what() const throw() { return error_messages[ecode_; }
private:
error_code ecode_;
};
| |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Für diese Dinge benutze ich dann gerne X-Makros, um mir keine Gedanken
// um die Synchronisation zwsichen Fehlercode und Fehlermeldung machen zu müssen.
enum error_code {
ERR_SUCCESS,
ERR_FEHLER1,
ERR_FEHLER2,
...
};
extern char const *const error_messages[];
// Hier nicht von std::logic_error, weil kein std::string gebraucht wird, um
// die Fehlermeldung aufzubewahren.
class my_exception : public std::exception {
public:
my_exception(error_code ecode) : ecode_(ecode) { }
virtual ~my_exception() throw() { }
virtual error_code code() const throw() { return ecode_; }
virtual char const *what() const throw() { return error_messages[ecode_; }
private:
error_code ecode_;
};
| |
Natürlich ist es eine andere (und nicht triviale) Frage, wann man Fehlercodes benutzen und wann man neue Exceptionklassen einführen sollte; die kann ich aber nicht pauschal beantworten. |
|
|
|
 |
nostdexcept
Unregistrierter
|
nostdexcept Unregistrierter
23:01:41 01.02.2012 Titel: |
|
Zitieren |
| Mechanics schrieb: | | wie Passwort falsch oder Server nicht erreichbar | Warum sollte das eine Exception werfen? Solche erwarteten Fehler werden bei mir ohne Exceptions behandelt. |
|
|
|
 |
knivil
Mitglied
Benutzerprofil
Anmeldungsdatum: 11.02.2009
Beiträge: 4495
|
knivil Mitglied
23:18:08 01.02.2012 Titel: |
|
Zitieren |
Das leidige Thema. Such doch einfach im Forum. |
_________________ If it were not for laughter, there would be no Tao.
Sie können einen Beitrag nicht so schnell nach Ihrem letzten absenden, bitte warten Sie einen Augenblick.
|
|
 |
Mechanics
Mitglied
Benutzerprofil
Anmeldungsdatum: 27.01.2012
Beiträge: 432
|
Mechanics Mitglied
23:27:02 01.02.2012 Titel: |
|
Zitieren |
| nostdexcept schrieb: | | Mechanics schrieb: | | wie Passwort falsch oder Server nicht erreichbar | Warum sollte das eine Exception werfen? Solche erwarteten Fehler werden bei mir ohne Exceptions behandelt. |
Wo? Wenn es eine interne Funktion gibt, die irgendwas übers Netzwerk übertragen muss, hat sie keine "erwarteten Fehler" zu behandeln. Wenn die Netzwerkkommunikation nicht funktioniert hat, dann ist es eine Ausnahme von dem erwarteten Verhalten der Funktion und wird durch eine Exception weitergegeben. Behandeln könnte man sie dann z.B. in der GUI. |
|
|
|
 |
knivil
Mitglied
Benutzerprofil
Anmeldungsdatum: 11.02.2009
Beiträge: 4495
|
knivil Mitglied
00:36:27 02.02.2012 Titel: |
|
Zitieren |
Das erwartete Verhalten wird vom Device bestimmt und nicht vom Programmierer. Der Abbruch einer Netzwerkverbindung ist sehr wahrscheinlich. |
_________________ If it were not for laughter, there would be no Tao.
Sie können einen Beitrag nicht so schnell nach Ihrem letzten absenden, bitte warten Sie einen Augenblick.
|
|
 |
Mechanics
Mitglied
Benutzerprofil
Anmeldungsdatum: 27.01.2012
Beiträge: 432
|
Mechanics Mitglied
00:49:23 02.02.2012 Titel: |
|
Zitieren |
| knivil schrieb: | | Das erwartete Verhalten wird vom Device bestimmt und nicht vom Programmierer. Der Abbruch einer Netzwerkverbindung ist sehr wahrscheinlich. |
Das ist keine Antwort. Die Frage ist, wo was behandelt wird. Exceptions sind eine Möglichkeit, Fehler zu behandeln. Die Funktion selbst sollte sie nicht behandeln, das wär ganz schlechtes Design. Die Fehler müssen nach oben gegeben werden. Viel mehr Möglichkeiten als return codes oder Exceptions gibts nicht. Bevor ich return codes verwende, verwende ich doch viel lieber Exceptions. |
|
|
|
 |
Ethon
Mitglied
Benutzerprofil
Anmeldungsdatum: 28.01.2011
Beiträge: 1114
|
Ethon Mitglied
09:48:44 02.02.2012 Titel: |
|
Zitieren |
Habt ihr alle C++11 verpasst? std::error_code, std::error_category, std::error_condition, std::system_error etc? Da stellt sich überhaupt nicht frage was man mit Errorcodes macht, da die Best-Practise praktisch vorgegeben ist. |
|
|
|
 |
knivil
Mitglied
Benutzerprofil
Anmeldungsdatum: 11.02.2009
Beiträge: 4495
|
knivil Mitglied
10:34:40 02.02.2012 Titel: |
|
Zitieren |
| Zitat: | | Das ist keine Antwort. | Nein, ich sage nur, dass deine Argumentation scheisse ist.
| Zitat: | | Die Funktion selbst sollte sie nicht behandeln, das wär ganz schlechtes Design. | Hast du deinen Doktor in Design gemacht? Du bist voreingenommen und kann wie alles nicht pauschal beantwortet werden. Aber vielleicht kann ja jemand ein gutes Buch zum Thema empfehlen. Persoenlich wuerde mich interessieren, wie sich Exceptions mit Multithreading verhalten. |
_________________ If it were not for laughter, there would be no Tao.
Sie können einen Beitrag nicht so schnell nach Ihrem letzten absenden, bitte warten Sie einen Augenblick.
Zuletzt bearbeitet von knivil am 12:05:22 02.02.2012, insgesamt 4-mal bearbeitet |
|
 |