| 

.NET C# Java Javascript Exception

4
hey leute,
ich hab da mal ne allgemeine frage.
ich schreib mir grad ne klasse um zu ner Datenbank zu connecten...
das is ja soweit alles kein problem.
die klasse hat die function verbinden, welche mehrere verbindungsversuche unternimmt.

mein problem ist jetzt, wenn sie verbindungen fehlschlage sollte sie ja etwas zurückgeben...
da dachte cih erst an nen boolean, aber dann ist mir eingefallen, ich hätte das lieber so, dass die finction gleich eine fehlermeldung mitgibt, aber denn müsste cih nen string nehmen.
das problem daran ist ja wieder, was geb cih denn mit wenn er keinen fehler hatte...

also meine frage ist jetz eigendlich, WIE MACHT MAN DAS RICHTIG...???
17.11.2011
DerPunk 1,2k 1 7
3
Bitte achte darauf, dass du versuchst in Zukunft eine aussagefähige Frage zu stellen. "ZUm Klassenschrieben" fing ich etwas, nun "nicht eindeutig" genug ;)
Mario Priebe 17.11.2011
bitte achte demnächst darauf, wie du schreibst. Dein Text hat so viele Rechtschreibfehler, dass es schwierig ist ihn zu verstehen.
luedi 18.11.2011
ja, sry, war gestern Abend ein bischen verwirrt
DerPunk 18.11.2011
3 Antworten
4
Du kannst doch einen Boolean verwenden, warum nicht. Falls eine Fehlermeldung erzeugt wird, kann man sie z.B. aus einem String auslesen, den du mit an deine Connect() Funktion übergibst. (ByRef verwenden).
17.11.2011
puls200 3,8k 7
Das is genau das was ich gesucht hab, danke
DerPunk 18.11.2011
1
Oder den Fehlerstring als Property deiner Connect-Klasse nach außen legen. Dann kann der Aufrufer bei Bedarf drauf zugreifen.
Andreas Richter 18.11.2011
1
Bloß keine Rückgabewerte verwenden! In Hochsprachen verwendet man aus gutem Grund (siehe andere Antworten) ausschließlich Exception-Handling.
Semmel 18.11.2011
1
Übrigens: Wann du wirklich einen Rückgabewert brauchst, kannst du oft am Namen festmachen. Mal stark vereinfacht ausgedrückt: TueEtwas() sollte keinen Wert zurückgeben, ganz im Gegensatz zu GibMirEtwas().
Folglich sollte dein Connect() im Normalfall keinen Rückgabewert haben.
Semmel 18.11.2011
@Semmel Im normalfall hast du recht, aber bei Sowas wie Connect() ist es für die aufrufende Funktion doch wichtig zu wissen, ob der Connect erfolgreich war, sonst bekommt sie doch im nächsten schritt nen Fehler.
DerPunk 21.11.2011
In den meisten Szenarien sollte ein Connect zur DB im Normalfall immer funktionieren und ein Fehler eine echte Ausnahme sein, verursacht z.B. durch eine Fehlkonfiguration, bei der man dann zur Laufzeit eh nichts anderes machen kann als die Anwendung zu beenden.
Wenn es in Deinem Kontext "normal" ist, dass die DB mal verfügbar ist und mal nicht und der aufrufende Code wirklich sinnvoll auf ein Nicht-Vorhandensein reagieren kann, würde ich Dir empfehlen, die Methode TryConnect() zu nennen und von der Signatur her analog zu int.TryParse() zu gestalten.
Matthias Hlawatsch 21.11.2011
1
@DerPunk:
Warum? Gerade bei einer Funktion wie Connect würde ich das nicht machen - zumindest nicht für dein Beispiel. Wenn du Connect aufrufst erwartest du ja dass die Verbindung hergestellt wird. Alles andere ist eine Ausnahme und dafür wirft man dann eine Exception.

Im Übrigen ist es eigentlich genau umgekehrt - für die aufrufende Funktion ist es fast nie wichtig zu wissen ob der Aufruf erfolgreich war (denn das ist der Normalfall von dem du ja hoffentlich ausgehst). Viel wichtiger ist es zu wissen wann der Aufruf fehlgeschlagen ist.
Semmel 21.11.2011
12
Nimm für eine "Fehlerbehandlung" lieber das klassische Exception-Handling anstelle eines Rückgabewertes. Hierfür gibt es mehrere Gründe. Einen findest du z.B. hier: Galileo Computing: Kapitel 5 Ausnahmebehandlung, 5.1 Was ist falsch an Rückgabecodes
Eine Ausnahme sollte von "unten" nach "oben" per try-catch durchgereicht werden, bis entweder eine Ausgabe an den Benutzer erfolgt oder die Ausnahme protokolliert wird. So kannst du feststellen, welche Routinen die Ausnahme durchlaufen hat.

Nachschlag:
Das empfiehlt Microsoft in seinen patterns & practices: Security Guidelines: ADO.NET 2.0: Exception Management
17.11.2011
Jürgen Luhr 7,1k 1 9
2
Dachte schon, als ich mir die anderen Antworten angeguckt hatte, dass .Net keine Exceptions unterstützt. Exceptions werfen ist doch der Standardweg?!
LiRo 18.11.2011
2
@LiRo: Ja ;o)
Jürgen Luhr 18.11.2011
2
Für mich sind Exceptions immer genau das was das Wort bedeutet: Ausnahmen. Damit wird i.d.R. die Programmlogik durchbrochen, wie es auch goto's und breaks machen. Du solltest sie also nur verwenden, wenn es sich um einen "richtigen" Fehler handelt und keinen seltenen Zweig in deiner Programmlogik.
puls200 18.11.2011
1
@puls200: ...verbindungen fehlschlage... klingt für mich schon nach einer Ausnahme. Hast du das von mir verlinkte Beispiel angesehen? Spätestens wenn wie in dem Beispiel kein Rückgabewert ausgewertet wird, läuft man in eine hässliche Ausnahme, die sehr wahrscheinlich nicht einmal die eigentliche Ursache behandelt, da auf ein nicht initialisiertes Datenbankobjekt zugegriffen wird.
Jürgen Luhr 18.11.2011
1
@Jürgen, natürlich erfordert der Ansatz mit Rückgabewerten etwas mehr Disziplin. In diesem Fall bleibe ich aber dabei, dass der Fehlschlag beim Verbindungsversuch mit einer DB ein nicht allzu seltener Fall sein wird - schon allein wenn mal die Netzwerkverbindung nicht vorhanden ist.
puls200 18.11.2011
1
@puls200: Wie realisierst du das bei einer mehrschichtigen Architektur, unter anderem bei einer Web-Anwendung. Der Datenzugriff findet im DataAccessLayer statt. Das heißt, der boolsche Rückgabewert und der string, den du ByRef übergibst muss durch alle Functions bis zur Oberfläche gereicht werden.
Irgendwann sollte der User ja über die nicht vorhandene Verbindung informiert werden.
Und wie machst du das, wenn eine Function in der Kette einen anderen Rückgabewert als dieser Boolean haben sollte?
Jürgen Luhr 18.11.2011
1
@puls200: Disziplin reicht nicht immer. Ich verweise nochmal auf mein Beispiel:
Programmierer1 behandelt die nicht vorhandene Verbindung mit einem Rückgabewert. Nun kommt Programmierer2 im Team und verwendet diese Datenzugriffsklasse. Nun muss er entweder die Doku lesen oder sich bei Programmierer2 informieren, was im Falle eines Verbindungsabbruchs passiert. Wahrscheinlich steckt die Datenzugriffsklasse noch in einer anderen DLL, so sieht er nichtmal den Code. Tut er das nicht und ruft die Function ohne Rückgabe auf, hat er ein Problem. Das kann beim Exception-Handling nicht passieren.
Jürgen Luhr 18.11.2011
1
Zu meinem letzten Kommentar muss ich noch etwas korrigieren. "Disziplin reicht nicht immer." ist meiner Meinung nach falsch. Wenn ein selbstgestricktes Framework Disziplin erfordert, ist es nicht robust geschrieben und hat eine geringe Halbwertszeit.
Jürgen Luhr 18.11.2011
1
Jürgen, in Linux/Unix funktionieren viele Systembibliotheken nach diesem Muster. Man kann die Rückgabewerte entweder berücksichtigen = robuster Code oder ignorieren = "geringe Halbwertszeit". Die Doku ist dazu da, dass man nachliest was passieren kann und die Fälle entsprechend auswertet. Ich finde es eher kritisch einfach irgendwelches Zeug in einer Blackbox aufzurufen und darauf zu hoffen, dass das Exceptionhandling die Sache irgendwie rettet, wenn etwas schiefgeht.
puls200 18.11.2011
1
Ich habe meiner Antwort noch einen Link zu Microsofts patterns & practices hinzugefügt.
Jürgen Luhr 18.11.2011
1
@puls200: Robuster Code bedeutet, dass auch Anfänger ohne große Hürde in einem Team mitarbeiten können.
Jürgen Luhr 18.11.2011
1
@Jürgen: Der Anfänger muss demnach aber auch diese Guidelines verinnerlicht haben - auch eine (kleine) Hürde. Bevor hier ein falscher Eindruck entsteht: Ich habe nix gegen Exceptions an sich, nur gegen deren Missbrauch als Steuerung des Programmablaufs.
puls200 18.11.2011
1
@puls200: Es wäre schön, wenn du noch auf meine weiteren Fragen z.B. bzgl. mehrschichtiger Architektur, Ausgabe an den Benutzer und Funktionsrückgabewert bis zum UI eingehen würdest.
Ansonsten sehe ich eine fehlende Verbindung als Ausnahme und nicht als Missbrauch dessen Handlings. Da haben wir unterschiedliche Auffassungen und brauchen das nicht mehr vertiefen.
Jürgen Luhr 18.11.2011
1
@Jürgen Bei geschachtelten Funktionen (z.B. bei einem Fehler im Data Access Layer) muss sich die Logik durchgehend nach aussen bis zum Benutzer fortsetzen und zwar in der Weise, dass dem Benutzer am Ende die Meldung "Datenbank nicht erreichbar" präsentiert wird statt "Windows Socket Exception 0815". Genau, wie bei Inner Exceptions. Voraussetzung ist natürlich dass zwischendrin keine void() Funktionen vorhanden sind.
puls200 18.11.2011
2
@Daniel & Jürgen: +1+1+1+1+1+1+1+1+1+1... schöne Diskussion. Ich freu mich auf die Kaffeküche...
@Marvin: Kannst Du solche Diskussionen aus dem Kommentargrab retten? Und uns vielleicht als 'Zuckerl zum ersten Kaffee' servieren?
ffordermaier 18.11.2011
2
@puls200:
Ich gebe dir in soweit Recht, dass Exceptions genau das sind was der Name vermuten lässt: Ausnahmen. Das ist allerdings nicht gleichzusetzen mit Fehlern - Fehler sind nur eine Untermenge von Ausnahmen.
Wenn eine Ausnahme auftritt, dann heißt das in erster Linie, dass etwas nicht wie erwartet funktioniert hat (Internetverbindung ist nicht da, Server nicht erreichbar, etc.).

Das mit dem Mißbrauch zur Steuerung des Programmablaufs kann ich nicht nachvollziehen. Ein Beispiel wäre nett.
Semmel 21.11.2011
2
Im Übrigen:
Klar arbeiten Systembibliotheken mit Rückgabewerten - die sind ja auch systemnah und es gibt keine andere Möglichkeit Ausnahmen/Fehler zu behandeln. Das ist aber für aktuelle (Hoch-)Hochsprachen obsolet.

Ansonsten kann ich der Aussage von Jürgen über "fremden" Code nur zustimmen: Wenn die Verwendung eines Frameworks, einer Bibliothek oder Hilfsfunktionen Disziplin erfordert, dann ist was ganz gehörig falsch gelaufen. Robuster Code bezieht sich hier ja auf den externen Code (der verwendbar sein sollte ohne das alles kracht, wenn mal was vergessen wurde) und nicht den eigenen.
Semmel 21.11.2011
1
@semmel: http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl - lies einfach mal den ersten Satz (und vielleicht die anderen Kommentare in diesem Thread).
puls200 21.11.2011
2
@puls200: Du hast Recht mit der Aussage, dass Exceptions nicht zur Steuerung von Programmlogik verwendet werden soll.
semmel scheint aber genau wie ich der Auffassung zu sein, dass eine fehlende Datenverbindung kein Programmzweig ist, sondern eine Ausnahme. Aufgrund meiner obigen Argumente denke ich weiterhin, dass auf jeden Fall ein Exception-Handling für diese Ausnahme verwendet werden muss.
Jürgen Luhr 21.11.2011
1
Danke für den Link. Ich muss aber sagen, dass sich an meiner Aussage nichts geändert hat. Wenn man etwas weiter liest, dann sieht man auch, dass man das dich so pauschalisieren kann.
Grundsätzlich stimme ich dir aber zu: Ausnahmen zur Steuerung des Programmflusses sind tendenziell eher keine gute Idee. Die Unterscheidung was genau eine bestimmte Ausnahme macht ist aber manchmal nicht ganz leicht.
Im Übrigen wird von ADO (oder was auch immer) selbst ja auch eine Ausnahme generiert wenn die Verbindung nicht klappt. Warum sollte man selbst also davon abweichen?
Semmel 29.11.2011
2
Hallo, ich würde mir ein Enum erstellen mit verschiedenen Status, z. B. Connected, Error, what ever

Dann würde ich mir eine neue Klasse erstellen mit 2 Properties:
public EnumTyp ConnectionStatus {get; set;}
public string Message {get; set;}


Deiner Methode "Connect()" oder wie auch immer sie heißt gibst du als Rückgabe-Wert die neue Klasse, also
public MyClass Connect()


Dann kannst du inerhalb deiner Connect Klasse die Message und den Status setzen und entsprechend reagieren.

Gruß
17.11.2011
Nicolai Schönberg 2,4k 2 9

Stelle deine .net-Frage jetzt!