Qualsiasi motivo per il modello DTO (ORM generati automaticamente) utilizzato come ViewModel?

7

Ho riscontrato ancora una volta questa situazione in cui i programmatori utilizzano modelli autogenerati (da LinqToSql, EF, nHibernate, qualunque cosa) come modelli di visualizzazione.

Di solito l'architettura è molto semplice:

  1. Un tipo di DAL contenente solo EF o LinqToSql
  2. Alcuni moduli per cose molto specifiche
  3. Progetto MVC

Può contenere o meno un repository. In entrambi i casi, i modelli DAL vengono utilizzati come modelli di vista. Il numero di proprietà utilizzate da detto modello varia dal 10% al 90% per visualizzazione, sebbene vengano utilizzate solitamente meno del 75% delle proprietà.

Recentemente ho riscontrato una nuova mutazione di detto pattern, in cui quando il modello DTO manca di un campo aggiuntivo richiesto, un programmatore crea un modello di vista che eredita il modello EF e lo passa alla vista.

Ci sono tutorial che spingono per questo approccio? O qualche libro o "allenatore" che lo spinge? C'è qualche ragione ragionevole accanto a "I'm pigro"? Sono sotto un'impressione totalmente sbagliata e questo è uno schema corretto e accettato?

    
posta Michał Brix 04.05.2017 - 16:06
fonte

4 risposte

6

Da un punto di vista della sicurezza è necessario utilizzare una vista 1 a 1 per visualizzare il modello e solo passare le proprietà necessarie alla vista. Se si utilizza la classe ORM completa, un utente malintenzionato potrebbe postare manualmente elementi aggiuntivi e modificare i dati che non si intende modificare (escludendo eventuali ulteriori server di convalida che non sarebbero necessari se la proprietà non fosse disponibile in primo luogo). Passando solo i dati richiesti per la vista, elimini questo possibile vettore di attacco non esponendo i parametri extra.

Insieme all'aspetto di sicurezza che ha i modelli di vista separati dalle classi ORM presenta una chiara interfaccia tra le cose. In Razor (.net) se si dovesse cambiare una classe ORM in un modo che creava un errore, si sarebbe mostrata solo in fase di esecuzione dove, come se ci fosse una mappatura che si è verificata tra l'ORM e il View Model (manuale o automatico) avrebbe una possibilità migliore di presentarsi come errore di compilazione.

Sì, ci sono alcune volte in cui questo creerà classi duplicate, ma vale la duplicazione perché le classi potrebbero cambiare in modo indipendente per diversi motivi.

    
risposta data 04.05.2017 - 23:15
fonte
7

Non ci sono standard chiari su come strutturare il livello "M" di un'applicazione MVC. Detto questo, ho riscontrato costantemente problemi nell'utilizzo di business class (o modelli di dominio o modelli ORM) nel livello di vista di un'applicazione.

  • La logica di visualizzazione si insinua nelle classi di business
  • La logica di visualizzazione viene caricata su tutti i modelli di visualizzazione
  • Nessuna chiara indicazione al programmatore di ciò che è assolutamente necessario per generare una vista
  • Le convalide specifiche della presentazione terminano con classi inquinanti che non si riferiscono alla presentazione
  • Le classi commerciali vengono modificate per consentire dati non validi in base alle regole aziendali, poiché la classe viene utilizzata per eseguire il rendering di un modulo (e pertanto deve consentire l'immissione di dati non validi)

    Questa è la grande ragione per separare i modelli di visualizzazione dalle business class!

Per questo motivo creo quasi sempre modelli di visualizzazione per le mie opinioni, circa il 99% delle volte. Non c'è molto sforzo in più per creare un modello di visualizzazione, e ti dà un posto dove mettere la logica specifica della presentazione. Avere quella separazione in atto dal primo giorno impedisce un imminente refactoring in seguito quando le esigenze dell'interfaccia utente si espandono.

Questo refactoring accade. Ogni. Singolo. Tempo.

Anche se le classi aziendali e i modelli di visualizzazione hanno esattamente le stesse proprietà, è OK copiare i dati. Non è corretto copiare la logica. E non è corretto combinare la logica di presentazione con la logica aziendale (o logica di archiviazione dei dati).

Separare i modelli di visualizzazione e le classi di business si riduce a Separazione dei dubbi ed è semplicemente una buona progettazione orientata agli oggetti.

In framework come ASP.NET MVC che utilizzano i modelli Razor, non si ottengono errori di compilatore nelle viste quando si rinomina un nome di proprietà o classe, il che complica il refactoring. Se si dispone di un modello di visualizzazione, è possibile refactoring delle classi di business come si ritiene opportuno e si otterranno errori del compilatore nei modelli di visualizzazione per modifiche incompatibili.

Se hai utilizzato le tue lezioni di business direttamente nelle tue visualizzazioni, allora ottieni un errore di run-time, che è più difficile da eseguire il debug e richiede più tempo per essere risolto.

Riguardo a YAGNI (non ne hai bisogno)

Il principio YAGNI ci dice di non costruire cose che non sono necessarie. Il problema è che le interfacce utente e le regole aziendali subiscono molti cambiamenti nel corso della vita di un'applicazione. Separare i due nelle proprie classi non sta violando YAGNI. Ricordati di non pensare solo a "Oggi". Le cose cambieranno e separare i modelli di visualizzazione dalle business class ti offre una zona cuscinetto tra questi due tipi di modifiche.

    
risposta data 04.05.2017 - 16:49
fonte
2

Essere pigri può essere un punto perfettamente valido perché:

  • Produrre più codice rende più codice da mantenere, il che è piuttosto triste se è del tutto inutile (YAGNI: Non lo impiccherai)
  • Se il tuo ORM usa la cache, funzionerà meglio con l'oggetto completo rispetto alla query selezionando colonne specifiche nelle tabelle, quelle non verranno memorizzate nella cache, quindi molto probabilmente finirai per interrogare la tua base più spesso.
  • Ereditare la dto per la vista evitare di copiare / incollare

Ovviamente non è gratis costa qualche aggancio più stretto e qualche svantaggio come se interrogassi due oggetti di tipo diverso (senza il collegamento di composizione / aggregazione tra di loro) separatamente dove potresti avere un join se l'oggetto della tua vista è separato dal quello di Dto.

    
risposta data 04.05.2017 - 16:29
fonte
0

Lo scopo di MVC è separare la logica di dominio dalla logica specifica dell'interfaccia utente.

La versione standard di MVC ha tre componenti. I componenti View e Controller definiscono l'interfaccia utente (rispettivamente la presentazione e le operazioni) mentre il modello è una sorta di modello di dominio indipendente da qualsiasi interfaccia utente specifica.

Il pattern MVC non dice nulla su cosa dovrebbe essere il modello, tranne che non dovrebbe contenere la logica specifica dell'interfaccia utente. Quindi, utilizzare gli oggetti entità del database come modello è completamente soddisfacente in base a questo.

Ora al centro della tua domanda:

Recently I've encountered a new mutation of said pattern, where when DTO model lacks a required additional field, a programmer creates a view model inheriting EF model and pass it to the view.

Bene, questo dipende da cosa è il campo aggiuntivo! Se si tratta di una sorta di logica di dominio (ad esempio un campo calcolato) che è indipendente dalle preoccupazioni dell'interfaccia utente, allora è fine . Se il campo è qualcosa di specifico dell'interfaccia utente, allora è cattivo , perché qualsiasi elemento specifico dell'interfaccia utente dovrebbe appartenere alla vista o al livello controller, non nel livello del modello e sottoclasse una classe modello, questo campo diventa strettamente accoppiato al modello.

    
risposta data 06.05.2017 - 11:57
fonte

Leggi altre domande sui tag