È possibile che la logica aziendale non si insinui nella vista?

31

Mi sono sviluppato per diversi progetti di applicazioni web negli ultimi 3 anni, sia personali che al lavoro, e non riesco a capire se sia possibile almeno per alcuni logiche di business non finendo nel livello vista dell'applicazione.

Nella maggior parte dei casi ci saranno problemi come "Se l'utente ha selezionato l'opzione x allora l'applicazione deve consentirgli di fornire informazioni per y, altrimenti non dovrebbe fornire informazioni z". Oppure esegui qualche operazione AJAX che dovrebbe applicare alcune modifiche al modello ma NON eseguirne il commit fino a quando l'utente non lo ha esplicitamente richiesto. Questi sono alcuni dei problemi più semplici che ho riscontrato e non riesco a capire come sia possibile evitare la logica complessa nella vista.

La maggior parte dei libri che ho letto che descrivono MVC di solito mostrano alcuni esempi molto banali, come le operazioni CRUD che aggiornano solo i dati sul server e li visualizzano, ma CRUD non è il caso delle applicazioni più ricche.

È possibile ottenere una visione senza logica aziendale?

    
posta vdaras 20.05.2014 - 13:04
fonte

7 risposte

21

Is it possible to achieve having a view with no business logic at all?

Trovo questa una domanda ingannevolmente difficile a cui rispondere. (Domanda stimolante!)

In teoria, sì, a seconda di ciò che definiamo come logica aziendale. In pratica, la separazione rigorosa diventa molto più difficile e forse anche indesiderabile.

La separazione delle preoccupazioni è un ottimo modo per pensare alla creazione di software: fornisce idee su dove collocare il codice e offre ai maintainer una buona idea su dove cercare il codice. Discuterò che è fondamentalmente impossibile per gli umani creare software funzionante senza separazione delle preoccupazioni. Abbiamo bisogno di questo.

Ma, come con tutte le cose, ci sono dei compromessi. La migliore posizione concettuale potrebbe non essere la posizione migliore per altri motivi. Forse c'è troppo carico sul tuo server web, quindi aggiungi qualche javascript alle tue pagine web per catturare facilmente gli errori di input prima che colpiscano il tuo server; ora hai alcune logiche di business nella tua visualizzazione.

La vista stessa, da sola, non ha valore senza la logica aziendale. E per essere efficace nell'uso e nella visualizzazione, implicitamente o esplicitamente, il punto di vista avrà una certa conoscenza dei processi aziendali in corso. Possiamo limitare questa quantità di conoscenza e possiamo isolarne alcune parti, ma le considerazioni pratiche spesso ci costringono a "rompere" la separazione delle preoccupazioni.

    
risposta data 20.05.2014 - 14:23
fonte
8

Solitamente lo faccio: se l'utente ha selezionato l'opzione x, la vista chiama

controller->OptionXChanged()

Quindi il controller abilita y sulla vista:

view->SetEnableInfoY(True) // suppose False=SetDisable

La vista notifica al controller cosa succede senza decidere nulla.

    
risposta data 20.05.2014 - 13:19
fonte
4

Mi chiedo se gli esempi che descrivi siano davvero logici di business. Gli esempi che descrivi sono operazioni che possono essere eseguite sul sistema. È come hai scelto di presentare le scelte all'utente che forse dà l'impressione che stai facendo business logic nella vista.

Dal punto di vista "View" fornisce solo InfoY o InfoZ al sistema. Solo perché l'implementazione dell'interfaccia utente sta eseguendo alcuni aggiornamenti dinamici in base alla scelta dell'operatore (ad esempio, l'attivazione di InfoY o InfoZ) non rende la logica aziendale della funzionalità. È davvero una visione logica di implementazione. Si potrebbe benissimo aver semplicemente dato all'operatore la possibilità di accedere a InfoY o InfoZ senza l'intera cosa abilitante. In quel contesto, considereresti ancora la logica del business? In caso contrario, lo stesso vale per l'attivazione / disattivazione dinamica dei campi info.

Lo stesso vale per l'esempio di commit. Queste sono 2 operazioni separate che il sistema richiede per funzionare correttamente. La tua vista deve essere in grado di avviare le azioni appropriate per eseguire la funzionalità desiderata. Sapere come usare il tuo sistema significa che la logica aziendale sta trapelando? Vedo come qualcuno potrebbe dire di sì, ma se credi in quel modo, allora la realtà è che non esiste nulla che separa la logica di business da qualsiasi cosa. Devi sapere che cosa sta facendo / lavora il sistema per realizzare qualcosa di significativo. Altrimenti, sarebbe un gioco da ragazzi creare una singola View e Controller generica che funzioni con ogni immaginabile applicazione MVC. Che sappiamo è impossibile.

In conclusione, penso che la tua definizione di business logic non sia la stessa definizione di altri.

    
risposta data 20.05.2014 - 18:24
fonte
1

Lavoro in questo modo (Struts2 + Hibernate):

My Struts Actions è responsabile solo per mostrare le informazioni sul browser web. Non pensare.

Utente - > Azione - > Servizio - > Repository - > Accesso ai dati

o

Voglio vedere - > Come vedere - > Che cosa fare - > Come ottenere - > Dove ottenere

Quindi, nel primo livello (la vista) ho qualcosa del tipo:

public String execute ()   {
    try {
        CourseService cs = new CourseService();
        Course course = cs.getCourse(idCourse);
    } catch (NotFoundException e) {
        setMessageText("Course not found.");
    } catch (Exception e) {

    }
    return "ok";
}

Come vedi, la mia "vista" non pensa. Sta chiedendo un servizio (per gestire i corsi) un corso specifico. Quel servizio può fare molte altre cose, come report, seraches e così via. Il risultato è sempre un elenco o un oggetto specifico (come nell'esempio). I servizi sono la macchina reale, applicano le regole e accedono al repository (per gestire i dati).

Quindi, se metto i miei servizi, i miei repository e DAOS in diverse librerie, posso usarlo anche in un programma basato su testo o in un sistema desktop basato su Windows senza modificare nulla.

Il servizio sa cosa fare, ma non sa come mostrare. La vista sa come mostrare, ma non sa cosa fare. Lo stesso con Service / Repository: il servizio invia e richiede i dati, ma non sa dove sono i dati e come prenderli. Il repository "compone" i dati grezzi per creare oggetti con cui il Servizio può lavorare.

Ma il repository non sa nulla del database. Il tipo di database (MySQL, PostgreSQL, ...) riguarda DAO.

È possibile modificare il DAO se si desidera modificare il database e non deve influire sui livelli superiori. È possibile modificare il repository se si desidera aggiornare la gestione dei dati, ma ciò non deve influire sul DAO e sui livelli superiori. Puoi cambiare i Servizi se vuoi cambiare la tua logica, ma questo non deve rovinare i livelli sopra o sotto.

E puoi cambiare qualsiasi cosa in vista, anche la tecnologia (web, desktop, testo), ma questo non deve implicare nulla di sotto.

La logica aziendale è Servizio. Ma come interagire con questo è vedere. Quale pulsante mostrare ora? L'utente può vedere questo link? Pensa che il tuo sistema sia un programma basato su console: devi negare se l'utente sbagliato sceglie #> myprogram -CourseService -option=getCourse -idCourse=234 o gli impedisci di premere i tasti per scrivere questo comando?

Parlando nei sistemi basati sul web (Struts + JavaEE) Ho un pacchetto di controller GUI separato. In vista Azione, fornisco all'utente registrato e la classe mi fornisce i pulsanti (o qualsiasi elemento dell'interfaccia che desidero).

                <div id="userDetailSubBox">
                    <c:forEach var="actionButton" items="${actionButtons}" varStatus="id">
                        ${actionButton.buttonCode}
                    </c:forEach>
                </div>

E

private List<ActionButton> actionButtons;

Ricorda di tenerlo fuori dai servizi. Questa è la roba di VIEW. Tenerlo nelle azioni Struts. Qualsiasi interazione dell'interfaccia deve essere completamente separata dal codice aziendale reale, quindi se porti il tuo sistema, sarà facile tagliare ciò di cui non avrai più bisogno.

    
risposta data 20.05.2014 - 20:28
fonte
1

In most cases there will be problems like "If the user has selected option x then the application must enable him to supply info for y, if not then s/he should supply info z"

Questa è logica per il modello, non per la vista. Potrebbe trattarsi di un "modello di visualizzazione", creato appositamente per supportare l'interfaccia utente, ma è ancora la logica del modello. La sequenza di controllo è:

  • Controller allega un gestore per gli eventi di visualizzazione
  • Visualizza allega un gestore per eventi modello
  • L'utente seleziona l'opzione X.
  • La vista genera un evento "Opzione X selezionata"
  • Il controller riceve l'evento e chiama model.selectOptionX ()
  • Il modello genera un evento "Stato modello modificato"
  • La vista riceve l'evento modificato del modello e aggiorna la vista in modo che corrisponda al nuovo stato: %codice%

inputY.enable(model.yAllowed()); inputZ.enable(model.zAllowed()); Questo è il classico pattern MVC. È possibile testare completamente la logica del modello separatamente dall'interfaccia utente. Il controller e la vista sono molto sottili e facili da testare.

=== In risposta a Dunk ===

Il modello in un pattern MVC UI è (solitamente) non un modello di oggetto business. È solo il modello per lo stato dell'interfaccia utente. In un'applicazione desktop, potrebbe contenere riferimenti a più modelli di business. In un'applicazione Web 2.0, è una classe Javascript che contiene lo stato dell'interfaccia utente e comunica tramite AJAX al server. È molto importante essere in grado di scrivere test di unità hands-off del modello di stato dell'interfaccia utente, poiché è lì che si trovano la maggior parte dei bug dell'interfaccia utente. La vista e il controller dovrebbero essere connettori molto sottili.

    
risposta data 20.05.2014 - 20:45
fonte
0

Una logica di business è più simile a If X then return InfoType.Y , quindi l'interfaccia utente visualizzerà i campi in base al risultato restituito dal dominio.

// Controller method pseudocode
option changed routine

    get selected option

    get required info type from domain routine based on selected option

    display fields based on required info type

Se l'interfaccia utente richiede una logica di business, quindi delegare la scelta al dominio. L'interfaccia utente semplicemente agirà in base alla decisione.

    
risposta data 20.05.2014 - 13:24
fonte
0

If the user has selected option x then the application must enable him to supply info for y, if not then s/he should supply info z".

Ci sono input che hanno valori richiesti basati sulla condizione. Nella maggior parte degli ambienti GUI, ci sono molte scelte su come gestire gli input, specialmente i tempi. L'opzione selezionata (in questo caso x) deve essere elaborata, quindi inviarla al controller. Invia quando gli utenti lasciano il campo di input. Attendi fino a quando non fanno clic su un altro oggetto o premi Salva. Non ha importanza per la logica aziendale. In un modo o nell'altro, il controller prenderà una decisione e dovrà dire la vista, "è richiesto".

Il modo in cui la vista interpreta o implementa ciò non ha molta importanza dal punto di vista della logica aziendale. Crea un campo obbligatorio. Avere un pop-up o sparare a un cannone e dire all'utente di entrare o essere solo testardo e non lasciare che l'utente povero faccia qualcosa finché non lo capisce.

Pensa che tutto ciò potrebbe essersi verificato perché il controllore ha provato a salvare e non ha inserito un valore per un campo obbligatorio nel database e ha semplicemente risposto a un errore del database. Non ha importanza per quanto riguarda la vista.

Qualcosa come un valore richiesto o limitato per un input può essere gestito in molti posti. Se lo si "affronta" solo nella vista, molti sviluppatori vedrebbero questo come un problema quando possono esserci più interfacce utente. Questo è il motivo per cui la logica aziendale può essere creata e testata senza molta interfaccia utente o persino un database. Non devi nemmeno avere un sito web.

    
risposta data 21.05.2014 - 14:43
fonte

Leggi altre domande sui tag