| 

.NET C# Java Javascript Exception

4
Nehmen wir an, ich habe folgende Methode in irgendeiner Klasse oder meinetwegen auch Funktion (hier Java-Code, aber sollte eher als Pseudocode betrachtet werden):
void sqrt_from_text(String text)
{
int number = Integer.parseInt(text); //Macht aus dem String eine Zahl

return Math.sqrt(number);
}


Hier gibt es viele Fehlerquellen, die auftreten können, wenn ein falscher String übergeben wird:
  • Der String lautet z.B. "hallo" und daraus kann keine Zahl gemacht werden (NumberFormatException wird geworfen)
  • Der String lautet -1 und number wird -1. Aber aus -1 kann man keine Wurzel ziehen (irgendeine MathException wird geworfen)
  • Der String ist leer (NumberFormatException wird geworfen)
  • Der String ist null (NullPointerException wird geworfen)


Jetzt habe ich als Programmierer zwei Möglichkeiten:
  • Alle möglichen Wegen abfangen und den Code damit extrem aufplustern, starke Beeinträchtigung der Übersichtlichkeit und Lesbarkeit
  • Keine Überprüfungen machen, weil der Programmierer selbst dafür sorgen muss, dass den Methoden/Funktionen die richtigen Parameter übergeben werden


Was ist eurer Meinung nach besserer Stil?
   PS: Es geht hier NICHT um Benutzereingaben!
News:
23.03.2010
Griever 109 1 2
Griever 109 1 2
3 Antworten
2
Da ein Programmierer in der Regel immer bestrebt ist wiederverwendbaren Code zu schreiben, würde ich persönlich den weg gehen:

void sqrt_from_text(String text)
{
if(string.IsNullOrEmpty(text)) throw new ArgumentNullException("text");

int number;
bool result = Integer.tryParse(text, number); //Macht aus dem String eine Zahl

if(!result) throw new ArgumentNotNumericException("text",text);
if(number< 0) throw new ArgumentOutOfRangeException("text",text);

return Math.sqrt(number);
}


Alternative wäre auch folgender Lösungsweg denkbar:

void sqrt_from_text(String text)
{
try{
int number = Integer.parseInt(text); //Macht aus dem String eine Zahl
return Math.sqrt(number);
}catch(Exception ex){
throw new MathSqrtException(ex); //ex = InnerException
}
}


Prinzipjell finde ich jedoch die erste Lösung besser da ich der Meinung bin, das jeder Fehler der behandelbar oder erwartbar ist, behandelt werden sollte.

Der Vorteil des ersten Lösungswegs ist, das für definierte Fehler auch definierte Ausgänge und somit eine konkrete Behandlung möglich ist. Der Quellcode kann ohne Modifikationen in ein anderes Programm/Projekt überführt werden. Aus dem Quellcode ist ersichtlich welche Fehler auftreten können und die Exceptions sind aussagekräftig.

Darüber hinaus ließe sich im Anschluss, abhängig vom Projekt, "Aspekte" Programmierer die die Exceptions behandeln und den Rückgabewert ggf. verändern wenn dies notwendig wäre.
24.03.2010
Floyd 14,6k 3 9
1
Man könnte sagen: "Das ist egal. Das wichtige ist, dass es dokumentiert ist"

Eine Möglichkeit wäre
/**
* Parses the given string to an integer value, and returns the
* square root of this value. The string must contain a valid
* non-negative integer.
*
* @param text The number as a string
* @return The square root of the parsed number
* @throws NumberFormatException If the string does not contain a valid number
* @throws ...
*/
double sqrtFromText(String text)
{
int number = Integer.parseInt(text);
return Math.sqrt(number);
}


Die andere wäre
/**
* Parses the given string to an integer value, and returns the
* square root of this value, or 0 if the String did not contain
* a valid non-negative integer.
*
* @param text The number as a string
* @return The square root of the parsed number
*/
double sqrtFromText(String text)
{
if (text == null) return 0;
try
{
int n = Integer.parseInt(text);
if (n<0) return 0;
return Math.sqrt(n);
}
catch (NumberFormatException e) { return 0; }
}


Alternativ kann man im zweiten Beispiel auch die Überprüfungen machen und ggf. eine IllegalArgumentException werfen.

Sowas wie ein pauschales "catch (Exception e)" sollte man nicht machen. Und mit eigenen Exceptions sollte man sparsam umgehen - in diesem Fall passt eine IllegalAgumentException mit einer passenden message eigentlich für alle Fälle.

Ein wichtiger Punkt dabei ist IMHO auch in welchem Zusammenhang diese Methode angeboten und verwendet wird, und welche Sichtbarkeit (public/private/default) sie hat. Für eine public-Methode sollte man her "defensiver" sein, und die Überprüfungen machen und ggf. eine IllegalArgumentException werfen. Wenn die Methode private ist, sollte jeder, der sie aufruft, sich im klaren sein, was die Methode unter welchen Bedingungen tut, und ob er ggf. selbst eine Überprüfung machen muss.

In ähnlichen Fällen könnte auch die Frage eine Rolle spielen, ob die Methode zeitkritisch ist und die Überprüfungen vielleicht zu aufwändig sind, aber das spielt meistens (und in diesem Fall sowieso) nur eine untergeordnete Rolle.
26.04.2010
Marco13 286 1 2
Grundsätzlich halte ich es nicht für eine gute Lösung die Fehlerbehandlung über einen boolschen oder einen speziellen Rückgabewert (in deinem Beispiel 0, aber besser wäre wohl -1 oder irgendeine andere negative Zahl) zu realisieren.
Zwei Gründe:
a) Die Fehlerbehandlung ist schwierig, wenn man nur weiß, dass es nicht geklappt hat, aber nicht warum nicht.
b) Häufig wird die Fehlerbehandlung vergessen. Dagegen wird eine nicht behandelte Exception früher oder später wohl in einen Logfile protokoliert werden und eher bemerkt, als wenn das Program mit einem falschen Wert weiterrechnet.
BeachBlocker 26.04.2010
Im allgemeinen stimmt das, deswegen der Hinweis, dass man ggf. eine IllegalArgumentException werfen sollte. Der zweite Codeblock sollte das "extreme Gegenbeispiel" zum ersten sein, in dem alle Exceptions 1:1 weitergereicht werden.

In manchen Fällen kann aber ein spezieller Rückgabewert angebracht sein. Etwa bei privaten Hilfsmethoden, wenn man sonst die Exception bei jedem Aufruf dieser privaten Hilfmethode fangen müßte, um dann nichts anderes zu machen, als daraufhin den "Standwardwert" zu verwenden.

(Bei "Im allgemeinen" statt "Grundsätzlich" hätte ich nicht widersprochen ;-) )
Marco13 27.04.2010
0
Wenn es sich nicht um Benutzereingaben handelt, sondern um Programmierereingaben aus anderen Funktionen, dann ist aus meiner Sicht der Fall klar:
- null-Eingaben sind eh nicht zu tätigen
- der Aufrufer muss sich um die Fehlerbehandlung selber kümmern, wenn man innerhalb einer Schicht bleibt.
- wenn eine andere Schicht die Methode aufruft: Eigene Exceptions definieren, nämlich NotParsableSQRTParameter(String str) für die Umwandlung und InvalidSQRTParameter(Integer i) für die Berechnung.

In jedem Fall unterstütze ich die Aussage von BeachBlocker KEINE Rückgabewerte für die Fehlererkennung zu verwenden.
09.02.2011
oopexpert 455 1 8

Stelle deine Java-Frage jetzt!