October 7, 2011 0

Parameter einer Funktion elegant prüfen

By in Best practice, Designpattern, Uncategorized, VB.NET

Die meisten Programmiersprachen arbeiten mit Funktionen. Diese Funktionen sind in der Regel in der Lage Parameter entgegenzunehmen. Diese Parameter können können ihrerseits auf Datentypen festgelegt sein. Des weiteren kann es sein, dass für die ordnungsgemäße Ausführung der Funktion weitere Anforderungen an die übergebenen Parameter gestellt werden (z.B. ein fester Wertebereich).

Sie sehen schon, dass es unablässig ist, die eingehenden Werte einer Validierung zu unterziehen.
Ein wichtiges Konzept das es unbedingt zu beachten gilt, ist das der Vorbedingung: Das korrekte Verhalten einer Funktion ist nur unter bestimmten Bedingungen definiert! Aber heißt das nun, dass es nicht zur Aufgabe einer Funktion gehört, die eingehenden Werte einer Prüfung zu unterziehen? Informatik-Fundamentalisten mögen das wohl so sehen, ich für meinen Teil bin folgender Meinung: Die Funktion sollte die übergebenen Werte checken und falls diese nicht korrekt sind, eine Ausnahme werfen bzw. Fehler auslösen. Es ist nicht Teil der Aufgaben der Funktion die Werte zu korrigieren!

Warum denn nicht die Werte vor der Übergabe prüfen?

Zugegeben, das würde dem Prizip der Vorbedingung am meisten entsprechen. Allerdings ist es in der Praxis recht unhandlich: Stellen Sie sich vor, eine Funktion wird 10,100 oder gar 1000 mal von unterschiedlichen Stellen im Quellcode aufgerufen – dann müssten Sie 10,100 oder 1000 mal eine Überprüfung der Werte vornehmen. Dies widerspricht ganz klar einem weiteren Grundkozept guter Softwareentwicklung: Redundanzen sind zu vermeiden!
Außerdem weiß die Funktion selbst am besten über ihre Vorbedingungen bescheid und sollte daher die Validierung übernehmen.

Nun zur Praxis

Halten wir also fest: Am Anfang einer Funktion sollen alle Parameter auf Validität überprüft wetrden. Gehen wir nun von einer objektoriertierten Sprache wie JAVA, C# oder VB.NET aus. Hier können Objekte an Funktionen übergeben werden. Objekte (bzw. deren Zeiger) können aber auch den Wert NULL oder NOTHING annehmen. Der Zugriff auf Eigenschaften eines Objekts führt dann ganz unweigerlich zu einem Laufzeitfehler.

Wir sollten also zunächst alle Parameter daraufhin überprüfen, dass sie nicht leer (NULL oder NOTHING) sind. Dies könnte so aussehen:

If parameterOne Is Nothing Then
    throw new ArgumentException("Parameter is not set!")
End If

Wenn wir nun mehrere Parameter haben, müssten wir dieses Statement entsprechend oft wiederholden. Bei dem Ausdruck “entsprechend oft wiederholen” sollten sich Ihnen die Nackenhaare aufstellen! Na klar, wir gliedern die obige Validitätsprüfung in eine eigene Funktion aus. Diese übergeben wir eine Menge an Parametern, die sie einzeln überprüft.
In VB.NET kommt uns hier das sehr nützliche ParamArray entgegen: Es erlaubt unserer Validierungs-Funktion eine beliebige Menge an Parametern engegen zu nehmen – also genau das, was wir wollen!
Die fertige Funktion sieht dann so aus:

Public Sub validateParameters(ByVal ParamArray parameters() As Object)
    For Each p As Object In parameters
        If p Is Nothing Then
            Throw New ArgumentException("Parameter is not set!")
        End If
    Next
End Sub

Ein Aufruf der Validierungsfunktion ließe sich so implementieren:

Public Function F2(ByRef o1 As Object, ByRef o2 As Object)
    validateParameters(o1, o2)
    ...
End Function

Die Übergabe eines leeren Parameters würde nun folgendermaßen ablaufen:

  • die Funtkion F1() ruft die Funktion F2(ByRef o As Object) mit einem leeren Parameter auf: F2(Nothing)
  • F2 ruft die Validierungsfunction auf: validateParameters(o)
  • Diese identifiziert das leere Objekt und wirft eine Ausnahme
  • Da der Funktionsaufruf der Validierungsfunktion nicht in einem Try-Catch-Block steht, wirft F2 die Ausnahme an F1 weiter.
  • Die Information, dass die Funktion F2 anhand der übergebenen Parameter nicht in der Lage ist sinnvoll zu funktionieren ist bei F1 angelangt.

Das war es im Grund schon. Wir haben nun einen Validierungsfunktion, die Objekte auf so genannte Null-Referenzen überprüft. Die Validierungsprüfung setzten wir jetzt an den Anfang jeder Funktion, die in ihrer Vorbedingung stehen hat, dass sie keine leeren Objekte als Parameter akzeptiert.

Wie geht es weiter?

Natürlich ist die Prüfung auf Null-Referenzen nicht genug. Folgende Vorbedingungn tauchen (zumindest bei mir) ziehmlich häufig auf:

String darf nicht leer sein:

Public Sub validateParametersNoEmptyString(ByVal ParamArray parameters() As String)
    For Each p As String In parameters
        If p Is Nothing Then
            Throw New ArgumentException("String is empty")
        Else
            If p = String.Empty Then Throw New ArgumentException("String is empty")
        End If
    Next
End Sub

Eine Zahl darf nur positiv oder Null sein:

Public Sub validateParametersNumberBiggerZero(ByVal ParamArray parameters() As Double)
    For Each p As Double In parameters
        If p <= 0 Then Throw New ArgumentException("Parameter smaller or equal zero")
    Next
End Sub

Eine Zahl darf nur positiv sein:

Public Sub validateParametersNumberBiggerOrZero(ByVal ParamArray parameters() As Double)
    For Each p As Double In parameters
       If p < 0 Then Throw New ArgumentException("Number smaller zero")
    Next
End Sub

Tags: , ,

Leave a Reply