Utilizzo di oggetti business nei modelli di visualizzazione


11

Quando si utilizzano oggetti business riutilizzabili, quali sono le migliori pratiche per la creazione di modelli di vista?

Usiamo un oggetto che chiamiamo Builderper costruire i nostri modelli di vista. Un costruttore per ogni unità logica di viste (ordini, utenti, ecc.), In cui ciascuna unità può contenere un numero di diversi modelli di vista (gli ordini contengono un riepilogo, righe ordine ecc.).

Un builder può estrarre i dati attraverso uno o più oggetti business standard al fine di costruire un modello di vista.

Qual è la pratica migliore quando si tratta di utilizzare oggetti / modelli di business nei modelli di vista?

Approccio 1

Consentire l'uso di oggetti business nel modello di visualizzazione?

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary();
        obModel.Order = obOrder;

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public Some.Business.Logic.Order Order;
    //Other methods for additional logic based on the order
    //and other properties
}

Approccio 2

Prendi solo i dati necessari dagli oggetti business

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary()
        {
            OrderNum = obOrder.OrderNum,
            NumOrderLnes = obOrder.NumOrderLines,
        }

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public int OrderNum;
    public int NumOrderLines
    //Other methods for additional logic based on the order
    //and other properties
}

Posso vedere i vantaggi e gli svantaggi di entrambi, ma mi chiedo se esiste un approccio accettato? Nell'approccio 1, non c'è duplicazione di codice attorno ai modelli, ma crea una dipendenza dalla logica aziendale. Nell'approccio 2, si prendono solo i dati necessari per la vista, ma si duplica il codice attorno ai modelli.

Risposte:


12

L'opzione 1 crea un accoppiamento stretto tra il modello di dominio e la vista. Ciò è in contrasto con i problemi di visualizzazione dei modelli progettati per risolvere.

Una "ragione per cambiare" dei modelli di vista è se la vista stessa cambia. Inserendo un oggetto modello di dominio nel modello di visualizzazione, si introduce un altro motivo per cambiare (ad es. Il dominio è cambiato). Questa è una chiara indicazione di una violazione del principio della responsabilità singola. Avere due o più motivi per cambiare porta a visualizzare modelli che richiedono molta manutenzione, probabilmente più del costo di manutenzione percepito della duplicazione tra modelli dominio / vista.

Suggerirei sempre l'approccio 2. Spesso i modelli di vista possono apparire molto simili, anche identici agli oggetti del modello di dominio, ma la distinzione, come ho già detto, è la diversa ragione del cambiamento.


Ho ragione nel pensare che per "ragione di cambiare" intendi cambiare in senso manutentivo, non cambiamento in senso di aggiornamento (es. Ui evento)?
Andy Hunt,

@AndyBursh sì, è corretto - vedi questo articolo , in particolare la riga "Robert C. Martin definisce una responsabilità come motivo per cambiare, e conclude che una classe o un modulo dovrebbe avere una, e una sola, ragione per cambiare."
MattDavey,

Mi piace la tua risposta ma alcuni pensieri ... Il modello di visualizzazione non cambia necessariamente solo perché il modello cambia. Solo se stavi vincolando o utilizzando una proprietà specifica modificata, questo sarebbe un problema poiché il tuo riferimento è all'intero oggetto. Avere un riferimento all'oggetto dominio rende più semplice apportare modifiche e salvarlo di nuovo. I metodi di salvataggio dipendono anche dall'oggetto dominio, quindi è necessario riconvertire il modello di visualizzazione o configurare il metodo di business per accettare i modelli di visualizzazione che non vanno bene. Penso ancora che il n. 2 abbia più senso, ma solo di due centesimi.
KingOf Hypocrites l'

Se non puoi avere oggetti di dominio in una macchina virtuale, come rappresenteresti qualcosa di più complicato come una matrice di ordini?
Jeff,

Ciò significa che cose come, diciamo, la formattazione di un timestamp per la visualizzazione dell'utente, dovrebbero appartenere al livello di visualizzazione, non al livello di dominio, e gli oggetti a livello di dominio dovrebbero restituire agli oggetti vista solo un timestamp non formattato e non formattato contenere la logica del formattatore?
The_Sympathizer il

2

L'opzione 1 è preferibile in quanto evita la duplicazione del codice. Questo è tutto.

Se il modello di dominio cambia in modo significativo, è quasi certo che la vista dovrà comunque cambiare. Con l'opzione 2, è necessario modificare il modello di vista E il builder nonché la vista stessa. Questo genere di cose è un veleno assoluto per la manutenzione. YAGNI.

Il punto di avere un modello di vista separato è mantenere lo stato significativo solo per la vista (ad es. Quale scheda è attualmente selezionata) separata dal modello di business. Ma i dati aziendali stessi dovrebbero essere riutilizzati piuttosto che duplicati.


YAGNI - l'assassino segreto della risoluzione della maggior parte dei problemi di progettazione del software.
Martin Blore,

6
Mi dispiace ma questo è un consiglio orribile per tutti tranne che per le applicazioni più banali. Visualizza i modelli non hanno stato. Sono oggetti di trasferimento dati. La scheda selezionata fa parte della STRUTTURA della vista e non ha nulla a che fare con i DATI nel modello di vista. La manutenzione non è un incubo se strutturi correttamente il tuo programma e usi qualcosa come Automapper per idratare i tuoi modelli di vista.
Lucifero Sam,

"Se il modello di dominio cambia in modo significativo, è quasi certo che la vista dovrà cambiare comunque." - Concordato. Ma che dire quando hai una piccola modifica al dominio? Con l'opzione 1, ogni piccola modifica al dominio (anche solo rinominando una proprietà) richiede una corrispondente modifica alla vista. Questo è anche un veleno assoluto per la manutenibilità.
MattDavey,

@MattDavey: se si rinomina una proprietà, quindi con un modello di vista separato è necessario modificare anche la vista (o qualunque mappa tra dominio e modello di vista) e ora abbiano due nomi diversi per la stessa cosa, che sicuramente causerà confusione.
Michael Borgwardt,

@Lucifer Sam: ovviamente abbiamo concetti molto diversi su cosa sia un modello di vista. La tua suona molto, molto strana per me, come se stessi descrivendo app mainframe per terminali stupidi, ma certamente non moderne app Web o client fat.
Michael Borgwardt,

2

I principi e i mantra sono talvolta preziosi per guidare il design ... ma ecco la mia risposta pratica:

Immagina che i tuoi modelli di visualizzazione vengano serializzati in JSON o XML. Se provi a serializzare i tuoi modelli di dominio, finirai con un orribile disordine di testo e molto probabilmente incontrerai problemi con riferimenti circolari e altri problemi.

Lo scopo di un modello di visualizzazione non è di raggruppare i modelli di dominio in modo che la vista possa utilizzarli. Invece il modello di vista dovrebbe essere un modello completamente piatto della vista ... la cosa reale che stai guardando sullo schermo. La logica della vista dovrebbe riguardare solo la strutturazione dei dati presenti nel modello di vista.

Idealmente, il modello di visualizzazione dovrebbe essere composto quasi interamente da stringhe preformattate. Pensaci ... non vuoi nemmeno un DateTime o un decimale nel tuo modello di vista perché poi sei bloccato a fare la logica di formattazione in C #, Javascript, Objective-C, ecc.


2
Non ho mai avuto problemi con la serializzazione dei modelli di dominio. E convertire tutto in stringhe in un modello? Sul serio?
Michael Borgwardt,

3
@MichaelBorgwardt Sì, questo è quello che DOVREBBE essere un modello di visualizzazione. Non vuoi serializzare i tuoi modelli di dominio e inviarli ovunque. Tutte le logiche aziendali dovrebbero rimanere al sicuro a casa in un unico posto. Le viste tuttavia dovrebbero essere flessibili e poter essere visualizzate su qualsiasi dispositivo, motivo per cui si desidera separare completamente STRUTTURA, DATI e STILE.
Lucifero Sam,

Siamo spiacenti, ma QUESTO è un consiglio orribile per qualsiasi applicazione, punto. Porta ad applicazioni ingegnerizzate piene di codice duplicato che sono l'esatto opposto di flessibile.
Michael Borgwardt,

1
@MichaelBorgwardt sembra che tu sia abituato a lavorare con modelli di dominio anemici in cui le entità sono poco più che borse di proprietà con un comportamento scarso o nullo. In tal caso sì, un modello DTO / View sarebbe sostanzialmente un duplicato. Tuttavia, se si dispone di un modello di dominio avanzato con relazioni complesse, diventa necessario un livello di modelli DTO / View e non saranno così simili alle entità di dominio.
MattDavey,

@MattDavey: Sembra che i modelli di dominio con cui sei abituato a lavorare non siano solo cleptocrati ricchi ma veri. Non mi piacciono nemmeno i modelli anemici, ma sono ancora modelli e il loro comportamento dovrebbe essere limitato a rappresentare il dominio. Principio della responsabilità unica e tutto il resto ...
Michael Borgwardt,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.