2010-07-14 8 views
5

Ich habe oft Aufrufhierarchien, in denen alle Methoden die gleichen Parameter benötigen. Wenn ich sie nicht auf Instanzebene (Mitglied der Klasse) setzen möchte, frage ich mich immer, ob es sinnvoll ist, die Gültigkeit in jeder Methode zu überprüfen.Wiederholte Parameterprüfungen in Funktionen

Zum Beispiel:

public void MethodA(object o){ 
    if(null == o){ 
     throw new ArgumentNullException("o"); 
    } 
    // Do some thing unrelated to o 

    MethodB(o); 

    // Do some thing unrelated to o 

} 

public void MethodB(object o){ 
    if(null == o){ 
     throw new ArgumentNullException("o"); 
    } 
    // Do something with o 
} 

Wenn Method A die Parameter verwendet, dann wird sie klar, ich habe die Gültigkeit dort und auch in MethdoB zu überprüfen. Aber solange MethodeA nichts mehr mit o tut, als MethodB zu geben, ist es ratsam, die Gültigkeit auch in MethodA zu überprüfen.

Der Vorteil der Überprüfung auch in MethodA kann sein, dass die Ausnahme wirft die Methode, die der Angerufene aufgerufen hat, das ist schön, aber ist es notwendig? Der Call-Stack wird dies auch angeben. Vielleicht seine Bedeutung in der Öffentlichkeit, intern, geschützt, aber nicht in privaten Methoden?

Ich nahm den Null-Check als Beispiel, aber auch Index-Validierungen oder Range-Validierungen fallen in die Selbstfrage, aber ich denke, es gibt Einschränkungen wegen der Gefahr von redundantem Code. Was denken Sie?

UPDATE

Durch die Antwort von AakashM ich gesehen habe, dass ich zu wenig präzise war. MethodA ruft nicht nur MethodB, es tut auch andere Dinge, aber nicht im Zusammenhang mit o. Ich habe ein Beispiel hinzugefügt, um dies zu verdeutlichen. Danke AakashM.

Antwort

9

Steve McConnells Code Complete spricht über das Konzept von 'der Barrikade' - eine Wand der Defensivität, außerhalb derer Daten nicht vertrauenswürdig sind, und in denen Daten vertrauenswürdig sind. Daten, die in die Barrikade gelangen wollen, müssen einen Validierungsprozess durchlaufen, aber innerhalb der Barrikade können sich Daten ungehindert durch den Validierungscode bewegen.

Wenn Sie diese Menge an Strukturierung und Layering in Ihrem Projekt erzwingen können, und dabei bleiben, macht es den Code innerhalb der Barrikade weniger zeremoniell und essenzieller. Aber es braucht nur eine Methode, um über die Barrikade zu rufen, damit alles schief geht. In Ihrem Beispiel ist MethodBpublic. Das bedeutet, dass Sie keine automatischen Zukunftsgarantien haben, dass MethodA sein einziger Anrufer ist - ich würde daher sagen, dass sein Validierungscode erhalten bleiben sollte. Wenn es für die Klasse jedoch private wäre, könnten Sie ein Argument für das Entfernen der Klasse erstellen.

Wie für MethodA, wenn es tatsächlich tut nichts mehr als MethodB anrufen, sollte es nicht existieren. Wenn es sich um einen Stub für zukünftige Erweiterungen handelt und irgendwann etwas mit o gemacht wird, sollte auch der Validierungscode beibehalten werden.

1

Ich denke, Sie sollten es einmal sicherstellen, wo der Eingabewert produziert wird (Verantwortung des Anrufers). Dies funktioniert, wenn die Klasse nur von internen Clients verwendet wird. Wenn es Teil der öffentlichen API ist, können Sie die Prüfungen nicht aufheben, aber Sie möchten sie möglicherweise wie in anderen Antworten vorgeschlagen in einen Faktor einteilen.

Für Testzwecke können Sie auch Debug.Assert(o != null) in beiden Methoden verwenden, und die Prüfungen werden aus Release-Code entfernt, wenn die Leistung ein Problem ist.

+0

Wo der Eingabewert erzeugt wird - bedeutet dies beim Anrufer? Das Beispiel, das mir beim Schreiben meines Beispiels vorschwebte, war, dass beide Methoden von außerhalb der Klasse zugänglich sind und es legitim ist, eine der beiden aufzurufen (Methode A macht dasselbe und etwas mehr als Methode B) – HCL

+0

Ja. Siehe meine Bearbeitung. – Mau

1

Ich halte Parameterüberprüfung nicht für "redundanten Code". Sie müssen alle externen Einstiegspunkte schützen. Wenn Sie eine private Methode haben, so dass Sie wissen, bis der Fluss dazu kommt, dass alle seine Parameter gültig sein werden, dann haben Sie vielleicht einen Fall, aber für public (und sogar protected) Methoden, die Sie wirklich nicht.