Riassunto l'interfaccia utente dal dominio

6

Il mio testo del corso suggerisce di creare una classe 'facciata' per astrarre completamente l'interfaccia utente dal livello dominio. Cioè, l'interfaccia utente utilizza solo tipi di base e, se ha bisogno di un riferimento a un oggetto dominio, la conosce solo come Object .

Per darti un'idea, questo è quello che potrebbe sembrare (esempio in Java ma potrebbe applicarsi anche ad altre lingue):

public class Facade
{
    ...
    public Object getLastOrder(Object customer)
    {
        Customer castCustomer = (Customer)customer;
        Order lastOrder = domainController.getLastOrder(castCustomer);
        return lastOrder;
    }
}

Nota: non sono sicuro che si tratti di un tipo di modello di facciata (l'ho sentito diversamente definito altrove), ma non voglio che troppo sia impantanato la terminologia.

Rispetto a nulla (se l'interfaccia utente chiama direttamente il controller di dominio), posso vedere che questo ha il vantaggio che l'interfaccia utente è molto più indipendente dalle modifiche all'implementazione del modello di dominio. C'è sempre il rischio che cambiamenti molto importanti (come non avere più nulla che rappresenti un ordine) spezzino le cose, ma questo sembra essere in grado di assorbire qualsiasi altra cosa.

Tuttavia, sembra sacrificare il controllo dei tipi e ciò significa che ottenere anche proprietà semplici degli oggetti di dominio più complicate di quanto necessario ( anOrder.getNumber() vs facade.getOrderNumber(anOrder) ).

Il mio pensiero era che sarebbe stato meglio per l'interfaccia utente fare riferimento agli oggetti del dominio in termini di interfacce, piuttosto che semplici oggetti. Ad esempio:

public class Facade
{
    ...
    public IOrder getLastOrder(ICustomer customer)
    {
        Customer castCustomer = (Customer)customer;
        Order lastOrder = domainController.getLastOrder(castCustomer);
        return lastOrder;
    }
}

o anche se il controller di dominio stesso esponeva solo i tipi di interfaccia, dimenticando completamente la "facciata".

Per quanto posso vedere, è meglio da un punto di vista del tipo di controllo. Le principali modifiche (ad esempio la rimozione di Order dal sistema) possono rompere le cose, ma ciò era vero per la soluzione 'plain Object '.

E tutti i metodi che sono stabili (ad esempio anOrder.getNumber() ) possono essere specificati nelle interfacce, quindi chiamarli dall'interfaccia utente è più semplice e più orientato agli oggetti. Ovviamente questo si applica solo ai metodi le cui firme sono stabili, per evitare di rompere l'interfaccia utente, ma l'implementazione è ancora libera di cambiare.

C'è qualcosa che mi manca? La mia soluzione 'interfaccia' presenta degli inconvenienti che non ho individuato? O c'è una soluzione completamente diversa e migliore che non ho però?

    
posta just me 03.10.2013 - 15:10
fonte

2 risposte

3

Ti consiglierei di utilizzare le classi viewmodel per l'interfaccia utente anziché per gli oggetti dominio. C'è una grande differenza tra la rappresentazione dei dati di cui la tua vista ha bisogno e la rappresentazione dei dati di cui ha bisogno il dominio.
Supponi di voler mostrare un elenco di ordini nell'interfaccia utente. Un Ordine nel dominio avrà probabilmente molte proprietà, alcuni oggetti di riferimento, ecc. Probabilmente non avrai bisogno di molte di quelle cose nell'interfaccia utente, quindi prendi semplicemente ciò che ti serve, inseriscilo in un modellabile e legalo a questo modello all'interfaccia utente.
PS: una facciata è usata per semplificare il lavoro con uno o più oggetti. Se vuoi ottenere qualcosa e farlo, dovresti fare 5 chiamate a 5 oggetti diversi, la responsabilità di una facciata sarebbe incapsulare quelle 5 chiamate, proteggendoti dalla complessità di lavorare con quei 5 oggetti diversi.

    
risposta data 07.10.2013 - 13:02
fonte
1

Vantaggio della prima versione:

  • la tua API non cambierà e sarà super-stabile in quanto non può essere più generica: public Anything DoSomething(Anything something) { }

Svantaggi:

  • il chiamante dovrebbe sempre indovinare e trasmettere il valore restituito. Che cosa succede se lo sviluppatore non controlla la documentazione e fa questo:

    if ((bool)yourObject.getLastOrder(customer)) { ... }

  • sei dove sei iniziato: sia il chiamante che la funzione dipendono dalla classe concreta Customer . È appena nascosto dalla firma, quindi introduci un nuovo livello di errore: cosa succede quando scrivi il seguente codice totalmente logico:

    Company theirCompany = MyDb.GetCompany (12345); Ordine ordine = (Ordine) yourObject.getLastOrder (theirCompany);

    Devi comunque controllare ogni singola chiamata se la classe Cliente cambia. Hai peggiorato la situazione sostituendo tutti i tipi di calcestruzzo con object . C'è un livello in cui non puoi essere più astratto e stai facendo più lavoro per te stesso.

Se hai un programma per la gestione degli ordini non puoi prepararlo a fare solo piccole modifiche in cui non stai più gestendo gli ordini ... Ma puoi prepararti se ci saranno nuovi tipi di ordini e clienti.

Dato questo, l'unico livello utile di astrazione che puoi avere qui è scoprire quale è la quantità minima di informazioni di cui hai bisogno nella tua funzione / classe riguardo l'ottenimento di un ordine.

Quindi, si suddividono tali informazioni dall'interfaccia ICustomer. Per gli ordini avrai, per esempio, un'interfaccia ICustomerID:

public interface ICustomerID { int getID(); }

public interface ICustomer : ICustomerID { ... } 

public interface ICompany : ICustomerID { ... }

Quindi torna alla tua funzione:

public IOrder getLatestOrder(ICustomerID id) { /* get order */ }

E la chiamata sarebbe simile a questa:

Customer customer = SomeFactory.GetCustomer(...);
Company company = SomeOtherFactory.GetCompany(...);

IOrder customerOrder = myObject.getLatestOrder(customer);
IOrder companyOrder = myObject.getLatestOrder(company);

Puoi avere due interfacce totalmente diverse per Cliente e Azienda; puoi cambiare le loro implementazioni in qualsiasi momento; non dovrai cambiare getLatestOrder.

    
risposta data 07.10.2013 - 12:36
fonte

Leggi altre domande sui tag