2009-02-18 8 views
5

Irgendwie muss ich das OOP-Prinzip "Sag, frage nicht" in all den Jahren übersehen haben, weil ich erst vor ein paar Tagen zum ersten Mal davon erfahren habe.Gilt "sagen, nicht fragen" für die Validierung der Benutzereingabe?

Der Kontext war jedoch eine Diskussion über Validierungscode, der aus einer ASP.NET-Webformularseite in ein Daten-/Geschäftsobjekt verschoben wurde, und es gab keine "Validate()" -Methode, nur eine Speichermethode selbst hat Validierung und (angeblich) eine Ausnahme ausgelöst. Ich fragte, warum das auf diese Weise entworfen wurde, und ich wurde auf OOPs "Sag, frage nicht" -Prinzip verwiesen, von dem ich noch nie gehört hatte, also schauten wir gemeinsam zu Google und ich wurde sofort erzogen. ;) Noch etwas riecht nicht richtig, sollten Daten nicht geschrubbt werden, bevor es vom Benutzer und in die Geschäftsschicht, wo es verarbeitet und/oder gesammelt wird, übergeben wird, anstatt umgekehrt ? Ich bin verwirrt, wie dies für gutes Design sorgt.

Es scheint, als ob die Regel von "tell, do not ask" die Idee betrifft, dass Sie das Zielobjekt nicht über den Zustand des Zielobjekts befragen sollten und dass das Prinzip nie wirklich auf die Daten angewendet werden sollte übergeben wird an das Zielobjekt.

Antwort

2

ich mit AviewAview zustimmen, aber woul werfen d nur Ausnahmen, wenn der Benutzer sagt (nicht, wenn er fragt):

public Foo 
{ 
    bool Validate(Baz bar) 
    { 
     if(!is_number(bar)) return false; 
     return true; 
    } 

    AssignBar(Baz bar) 
    { 
     if (!Validate(bar)) throw numberexception(); 
    } 
} 

Tells:

try 
{ 
    foo.AssignBar(bar); 
} 
catch(numberexception e) 
{ 
    alert('Not a number!'); 
} 

Frage:

if (foo.Validate(bar) 
{ 
    foo.AssignBar(bar); 
} 
else 
{ 
    alert('Not a number!'); 
} 

So AssignBar erwartet eine VALID bar und löst eine Ausnahme Wenn dies nicht der Fall ist, bieten wir auch eine Validierungsmethode an, die keine Ausnahme auslöst.

+3

Ausnahmen sind für die Behandlung unerwarteter Fälle zulässig (nicht genügend Arbeitsspeicher/Datenträger ist voll/Verbindung geschlossen/verteilte Transaktion fehlgeschlagen) - Die vom Benutzer übermittelten Daten sind nicht unerwartet gültig. Verwenden Sie stattdessen "Handler" -Ansatz - rufen Sie einfach validate_number (invalid_handler_callback) auf –

3

Ich dachte, es klang wie eine Last von "Best Practices" und "Design Methodologies", die falsch gelaufen sind, aber jetzt macht es für mich Sinn. Sehen Sie es sich so an:

Stellen Sie sich die Validierung im Business-Objekt vor, aber die "Was mache ich, wenn die Validierung fehlschlägt". Dadurch könnten mehrere verschiedene Präsentationsebenen dieselbe Validierungslogik wiederverwenden, aber behandeln anders Fehler.

public Foo 
{ 
    Validate(Baz bar) 
    { 
     if(!is_number(bar)) throw numberexception(); 
    } 

    AssignBar(Baz bar) 
    { 
     Validate(bar); 
    } 
} 


//... 

try 
{ 
    foo.AssignBar(bar); 
} 
catch(numberexception e) 
{ 
    alert('Not a number!'); 
} 

nb Sie alles, was Sie wollen über das werfen Ausnahmen argumentieren kann, wurde als Beispiel gemeint. Zurück Staaten, bools, was Sie wollen.

0

Ich frage mich, ob dies eher eine Frage der "Trennung von Anliegen" als "Tell do not ask" ist. Wessen Verantwortung ist es, die Daten zu validieren? Es ist wohl die Sache, die dafür verantwortlich ist, dass es weiterbesteht.

Natürlich ist es manchmal nützlich, die Daten in mehreren Schichten zu validieren. Wenn dies bei Ihrer App der Fall ist, habe ich kein Problem damit, die Validierungslogik in der Ebene "Benutzer" verfügbar zu machen. Aber ich würde es immer noch in der Business-Schicht wollen.

Verwandte Themen