2013-07-18 12 views
19

Se client validation viene eseguito quando è necessario eseguire domain level validation?Visualizzazione convalida del modello rispetto alla convalida del modello di dominio

Io uso ASP.NET MVC per le mie applicazioni web. Mi piace distinguere tra il mio domain models e il view models. I miei modelli di dominio contengono i dati provenienti dal mio database e i miei modelli di visualizzazione contengono i dati sulle mie viste/pagine.

Diciamo che sto lavorando con i dati dei clienti.

Avrò una tabella nel mio database chiamato Customers.

avrò una classe cliente che potrebbe essere simile a questo:

public class Customer 
{ 
    public int Id { get; set; } 

    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    public DateTime DateOfBirth { get; set; } 
} 

E farò un creare vista del cliente il modello per rappresentare solo i dati che ho sul mio punto di vista:

[Validator(typeof(CustomerCreateViewModelValidator))] 
public class CustomerCreateViewModel 
{ 
    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    public DateTime DateOfBirth { get; set; } 
} 

avrò una creazione di vista che accetta la mia CustomerCreateViewModel e lega i miei campi di input alla mia vista del modello:

@model MyProject.ViewModels.Customers.CustomerCreateViewModel 

@using (Html.BeginForm()) 
{ 
    <table> 
      <tr> 
       <td> 
        @Html.TextBoxFor(x => x.FirstName) 
        @Html.ValidationMessageFor(x => x.FirstName) 
       </td> 
      </tr> 
      <tr> 
       <td> 
        @Html.TextBoxFor(x => x.LastName) 
        @Html.ValidationMessageFor(x => x.LastName) 
       </td> 
      </tr> 
    </table> 

    <button id="SaveButton" type="submit">Save</button> 
} 

Come potete vedere, ho un CustomerCreateViewModelValidator che contiene le mie regole di convalida. Dopo che l'utente ha inserito alcuni dati nelle caselle di testo, farà clic sul pulsante di invio. Se alcuni campi sono vuoti, la convalida fallisce. Se vengono inseriti tutti i campi richiesti, la convalida ha esito positivo. Io poi mappare i dati dal mio modello di vista al mio modello di dominio in questo modo: modello di dominio

Customer customer = Mapper.Map<Customer>(viewModel); 

Questo cliente prendo e passare sul mio strato repository ed aggiunge i dati al mio tavolo.

Quando deve essere eseguita la convalida su un modello di dominio? Faccio tutta la mia convalida sul mio modello di vista. Posso convalidare i miei dati nel mio modello di dominio appena prima di aggiungerlo al database ma vedendo che è stato convalidato sul modello di visualizzazione, non sarebbe solo la replica della stessa validazione sul lato client?

Qualcuno potrebbe per favore condividere un po 'di luce su questo argomento di convalida?

+0

Avete regole di convalida separate tra i livelli? Con ciò intendo, è possibile che qualcosa di valido nell'interfaccia utente non sia considerato valido nel dominio? –

+0

Al momento entrambi dovrebbero essere uguali. Sto generalizzando sulle convalide, non solo specifiche per i miei progetti. –

+1

Avrei però pensato che DDD si sarebbe orientato verso un metodo di istanza 'Validate()' su ogni oggetto di dominio che si auto convalida. Sono più lontano da un esperto di DDD però. +1 per una domanda interessante. –

risposta

9

Convalidare sempre a entrambi i livelli.

È necessario convalidare i modelli di visualizzazione perché si desidera restituire all'utente il più rapidamente e facilmente possibile se ha fatto qualcosa di sbagliato. Inoltre, non si desidera infastidire il resto della logica del dominio se il modello non è valido.

Ma, si vorrà anche verificare che tutto sia felice nel dominio, una volta che il modello di vista è stato convalidato. Per i modelli semplici, questi controlli possono essere uguali e quindi assomigliano alla logica di duplicazione, tuttavia non appena l'applicazione cresce e si possono avere più interfacce utente, o molte applicazioni diverse che utilizzano gli stessi modelli di dominio, diventa così importante controlla all'interno del dominio. Ad esempio, se l'applicazione cresce e alla fine si fornisce un'API ai clienti per interagire direttamente con l'applicazione a livello di programmazione, diventa necessario convalidare i modelli di dominio, poiché non è possibile garantire che l'interfaccia utente utilizzata abbia convalidato il dati allo standard di cui hai bisogno (o addirittura convalidato). C'è un argomento per dire che i dati ricevuti dalle API dovrebbero essere convalidati più o meno allo stesso modo in cui i modelli di visualizzazione sono convalidati, e questa è probabilmente una buona idea poiché sta conseguendo lo stesso obiettivo della convalida del modello di vista. Ma a prescindere dal percorso in ingresso (da un'interfaccia utente o dall'API), dovrai sempre garantire che i dati siano validi, quindi definire che in un punto centrale è l'ideale.

Anche gli obiettivi dei due livelli di convalida sono diversi. Mi aspetto una convalida del modello di visualizzazione per informarmi di tutti i problemi (come il nome mancante, il cognome è troppo lungo, il DoB non è una data). Tuttavia, penso che sarebbe ok per la logica del dominio fallire al primo errore, e basta segnalarlo. Anche in questo caso, per i modelli semplici, potrebbe essere possibile raccogliere tutti gli errori e riportarli tutti, tuttavia, più un'applicazione complessa diventa complessa, più difficile sarà anticipare tutti gli errori, soprattutto se la logica cambierà in base ai dati. Ma, finché solo i dati buoni vengono superati, dovrebbe andare bene!

0

È necessario disporre di un validatore del modello nel caso in cui si disponga di più client per il modello. Ad esempio, se ASP.NET MVC chiama il modello e un'applicazione WPF, in questo caso ha senso avere la logica di convalida sul modello. Ma nel tuo caso in cui hai un solo cliente che sarebbe eccessivo.

+0

Quindi stai dicendo che se hai solo 1 applicazione che usa il tuo database allora la validazione sul modello di visualizzazione è sufficiente? –

+1

Ciò che dico è che se si utilizza il repository solo da un client, ovviamente la convalida sul ViewModel sarà sufficiente in quanto non ci saranno altri modi per arrivare al repository, solo attraverso i controller che invocano la logica di validazione –

+2

Questo lead a un modello di dominio anemico. Il tuo modello di dominio deve proteggere i suoi invarianti. – JefClaes

2

Tendo a pensare alla convalida del client come più sanificante dei dati a livello di interfaccia utente. In altre parole, controllando che, ad esempio, un campo di input che è un numero, venga assegnato un numero dall'utente. O se la lunghezza di un input di testo soddisfa il requisito di lunghezza minima. Roba del genere.

A livello di dominio, è necessario controllare le regole del dominio aziendale. Ad esempio, se l'utente sta inserendo dettagli su un nuovo prodotto, il nome del prodotto esiste già? O forse controllando che l'utente abbia selezionato un Dipartimento valido durante la configurazione di un nuovo utente, in base alle competenze di quell'utente? Questi sono solo degli esempi, ma spero che mi diano un'idea di cosa intendo.

6

Come regola generale, considero il modello di dominio il codice più importante e quindi la gestione del suo stato santo.Per questo motivo non assumerei mai che il modello di dominio sia in uno stato valido solo perché è stato gestito da un livello di presentazione che dovrebbe rafforzare la validità. Ciò significherebbe che il tuo livello di dominio è strettamente associato al tuo livello di presentazione.

È consigliabile iniziare a pensare dal modello di dominio verso l'esterno (onion architecture). Il motivo dietro tutto ciò è che il modello di dominio è il meno probabile a cambiare nel tempo e funge da nucleo per un'applicazione, isolando i livelli dai difetti degli altri.

Quindi, partendo da un modello di dominio che applica la propria validità, rimane la questione della duplicazione del codice di convalida. Ci sono alcuni modi per evitarlo. Ad esempio, il tuo modello di visualizzazione può provare a creare un oggetto dominio e tradurre eventuali eccezioni generate come errori di convalida. I validatori possono anche essere estratti e riutilizzati. A seconda dei casi d'uso, devi vedere cosa funziona meglio per te. Fai solo attenzione a mantenerlo semplice. Forse, se i tuoi casi d'uso non lo sono, potrebbe essere più semplice duplicare semplicemente la convalida. Ricorda che la deduplicazione aumenta la complessità.

Ho visto basi di codice in cui solo il livello dominio gestiva la validazione e le basi di codice in cui veniva gestita la convalida sia nel dominio sia nel livello di presentazione. Preferisco semplicemente duplicare la logica di validazione a questo punto, perché ho visto quanto sia difficile mappare in modo significativo gli errori di convalida del dominio con un'interfaccia utente contestuale.

Problemi correlati