Automapper è un "oggetto-oggetto mappatore" per .Net, che significa copiare oggetti da una classe in un'altra classe che rappresenta la stessa cosa.
Perché è sempre utile? La duplicazione delle classi è sempre utile / buona progettazione?
Automapper è un "oggetto-oggetto mappatore" per .Net, che significa copiare oggetti da una classe in un'altra classe che rappresenta la stessa cosa.
Perché è sempre utile? La duplicazione delle classi è sempre utile / buona progettazione?
Una rapida ricerca su google ha rivelato questo esempio:
mostra un uso perfettamente valido di AutoMapper che non è sicuramente un esempio per un design scadente. In un'applicazione a livelli, potresti avere oggetti nei tuoi dati o nel tuo livello aziendale, e a volte hai bisogno solo di un sottoinsieme degli attributi di quegli oggetti dati, o qualche tipo di visualizzazione nel loro livello di interfaccia utente. Pertanto, crei un modello di visualizzazione che contiene oggetti con esattamente gli attributi necessari nell'interfaccia utente, non di più, e utilizza AutoMapper per fornire il contenuto di tali oggetti con un codice di codice inferiore.
In tale situazione i tuoi "oggetti vista" non sono un duplicato della classe originale. Hanno metodi diversi e forse alcuni attributi duplicati. Ma va bene fino a quando usi gli oggetti di visualizzazione solo per scopi di visualizzazione dell'interfaccia utente e non inizi a utilizzarli in modo errato per la manipolazione dei dati o le operazioni commerciali.
Un altro argomento che potresti leggere per capire meglio questo è il modello Segregazione di responsabilità della query di comando di Fowlers, al contrario di CRUD. Ti mostra situazioni in cui i diversi modelli di oggetti per interrogare i dati e aggiornarli in un database hanno senso. Qui, la mappatura da un modello di oggetto all'altro può anche essere eseguita da uno strumento come AutoMapper.
Is the duplication of classes ever useful/good design?
È buona norma avere una classe del modello di vista separata da utilizzare nel livello dell'interfaccia utente piuttosto che utilizzare la stessa classe utilizzata nel livello dati. La tua interfaccia utente / pagina web potrebbe dover visualizzare altri bit di informazioni che non sono strettamente correlati all'entità dati. Creando questa classe extra, ti stai dando la libertà di modificare facilmente la tua interfaccia utente man mano che i requisiti cambiano nel tempo.
Per quanto riguarda l'utilizzo di AutoMapper, lo evito personalmente per 3 motivi:
Fallimenti silenziosi più comuni
Poiché AutoMapper esegue automaticamente la mappatura tra le proprietà automaticamente, la modifica di un nome di proprietà su una classe e non sull'altra causerà l'omissione del mapping delle proprietà. Il compilatore non lo saprà. Automapper non si preoccuperà.
Mancanza dell'analisi statica
Quindi ti è stata data una base di codice di grandi dimensioni da gestire. C'è un milione di classi con un milione di proprietà. Molti sembrano non essere usati o duplicati. Lo strumento "Trova tutti i riferimenti" in Visual Studio ti aiuterà a vedere dove vengono utilizzate le proprietà e ti aiuta a costruire una mappa nella tua testa di come l'intera applicazione si blocca insieme. Ma aspetta, non ci sono riferimenti espliciti a metà delle proprietà perché Automapper è in uso. Il mio lavoro ora è molto più difficile.
Requisiti tardivi che aumentano la complessità
Automapper è perfetto e dandy quando tutto ciò che si vuole fare è copiare i valori da una classe all'altra (come spesso accade allo START dello sviluppo), ma ricorda quei requisiti che cambiano nel tempo? Che cosa succede se ora hai bisogno di ottenere valori da altre parti della tua applicazione, forse specifici per l'utente che ha effettuato l'accesso o qualche altro stato contestuale?
Lo schema di AutoMapper per la creazione dei mapping di classi one-to-one all'avvio dell'applicazione non si presta bene a questi tipi di modifiche specifiche del contesto. Sì, ci sono probabilmente dei modi per farlo funzionare, ma di solito lo trovo più pulito, più semplice e più espressivo per scrivere la logica da solo.
In sintesi, prima di raggiungere Automapper per risparmiare 30 secondi di mappatura manuale di una classe a un'altra, pensa a questo.
Programming is the art of telling another human what one wants the computer to do. - Donald Knuth
Con questo in mente, chiediti "AutoMapper è utile oggi e sarà domani?"
Nella mia esperienza, quando qualcuno si è lamentato di "troppo standard" e desidera utilizzare AutoMapper, è stato uno dei seguenti:
Tuttavia:
Se hai scelto una lingua tipizzata in modo statico, sfrutta la lingua. Se stai tentando di eludere i controlli nella lingua che aiutano a prevenire gli errori dovuti all'eccessivo utilizzo delle API di riflessione e magia come AutoMapper, significa semplicemente che hai scelto una lingua che non è soddisfacente per le tue esigenze.
Inoltre, solo perché Microsoft ha aggiunto funzionalità a C # non significa che siano un gioco equo in ogni situazione o che supportino le migliori pratiche. Riflessione e la parola chiave 'dinamica', ad esempio, dovrebbero essere utilizzati nei casi in cui semplicemente non è possibile realizzare ciò che è necessario senza di loro. AutoMapper non è una soluzione per qualsiasi caso d'uso che non può essere già risolto senza di esso.
Quindi, la duplicazione delle classi è un cattivo design? Non necessariamente.
AutoMapper è una cattiva idea? Si assolutamente.
L'uso di AutoMapper indica carenze sistemiche nel progetto. Se ti senti di averne bisogno, fermati e pensa al tuo design. Troverai sempre un design migliore, più leggibile, più manutenibile e privo di bug.
C'è un problema più profondo qui: il fatto che C # e Java insista sulla maggior parte / tutti i tipi deve essere distinguibile per nome piuttosto che per struttura: ad es. class MyPoint2D
e class YourPoint2D
sono tipi separati anche se hanno le stesse identiche definizioni. Quando il tipo che vuoi è "qualcosa di anonimo con un campo x
e un campo y
" (cioè un record ), sei sfortunato. Pertanto, quando desideri convertire YourPoint2D
in MyPoint2D
, hai tre opzioni:
this.x = that.x; this.y = that.y
La scelta 1 è abbastanza semplice in piccole dosi, ma diventa rapidamente un lavoro di routine quando il numero di tipi che devi mappare è grande.
La scelta 2 è meno che desiderabile perché ora devi aggiungere un ulteriore passaggio al tuo processo di compilazione per generare il codice e assicurarti che l'intero team riceva il promemoria. Nel peggiore dei casi devi anche generare il tuo generatore di codice o il tuo sistema di template.
Questo ti lascia con la riflessione. Potresti farlo da solo o utilizzare AutoMapper.
Automapper è una di quelle librerie / strumenti in cui l'imperatore sta letteralmente correndo nudo. Quando superi il logo sfarzoso, ti rendi conto che non fa nulla che non puoi fare manualmente con risultati molto migliori.
Sebbene non sia del tutto sicuro di come ciò accenni ai membri di mappatura automatica, molto probabilmente implica una logica di runtime aggiuntiva e una possibile riflessione. Questa potrebbe essere una significativa penalizzazione delle prestazioni in cambio di un risparmio di tempo. La mappatura manuale, d'altra parte, l'hint viene eseguita molto prima della compilazione.
Nei casi in cui AutoMapper non ha indizi, è necessario configurare il mapping con il codice e impostare i flag. Se ti preoccuperai di fare tutto il lavoro di configurazione e codice, devi mettere in discussione quanto risparmi rispetto alla mappatura manuale.