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


31

Ho sviluppato per diversi progetti di applicazioni Web negli ultimi 3 anni, sia personali che al lavoro, e non riesco a capire se sia possibile che almeno una logica aziendale non finisca nel livello di visualizzazione dell'applicazione.

Nella maggior parte dei casi ci saranno problemi come "Se l'utente ha selezionato l'opzione x, l'applicazione deve consentirgli di fornire informazioni per y, in caso contrario dovrebbe fornire informazioni z". Oppure esegui alcune operazioni AJAX che dovrebbero applicare alcune modifiche al modello ma NON commetterle finché 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 una logica complessa nella vista.

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

È possibile ottenere una visione senza alcuna logica aziendale?


2
Dai un'occhiata alle derivazioni MVC MVP e MVVM (vedi en.wikipedia.org/wiki/Model_View_Presenter e en.wikipedia.org/wiki/Model_View_ViewModel ), potrebbero essere quello che stai cercando.
Doc Brown,


2
La vista è la manifestazione esterna e visibile dei tuoi dati e della tua logica. Non è possibile per la vista NON presentare la logica aziendale. O stai dicendo che la vista non dovrebbe contenere alcun codice? Puoi sicuramente creare viste solo HTML.
BobDalgleish,

Potresti esaminare l' animazione del modello ; anche se questo probabilmente non eliminerà tutta la logica dal livello di visualizzazione , sembra che dovrebbe portare a una separazione un po 'migliore delle cose.
paul

Penso che una domanda migliore sia se è meglio che i dati della vista inquinino il modello o è meglio che la vista contenga una logica di vista correlata alla logica aziendale? Questo è lo scenario più reale. La tua domanda è essenzialmente quella di sostenere l'inquinamento del modello a supporto delle opinioni in quanto sarebbe l'unico modo per realizzare ciò che stai chiedendo.
Dunk,

Risposte:


22

È possibile ottenere una visione senza alcuna logica aziendale?

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

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

La separazione delle preoccupazioni è un ottimo modo di pensare alla creazione di software: ti fornisce idee su dove posizionare il codice e offre ai manutentori una buona idea su dove cercare il codice. Sosterrò che è praticamente impossibile per gli umani costruire software funzionante senza separazione delle preoccupazioni. Ne abbiamo bisogno.

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

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


2
The best conceptual location may not be the best location for other reasons: Bravo !!
Magno C,

8

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

controller->OptionXChanged()

Quindi il controller abilita y nella vista:

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

La vista notifica al controller ciò che accade senza decidere nulla.


+1. I banali problemi di OP di solito
venivano

Mettere questa logica nel controller ha due problemi: 1) complica i test unitari ed è impossibile supportare più viste degli stessi dati.
Kevin Cline,

4

Mi chiedo se gli esempi che descrivi siano davvero una logica aziendale. Gli esempi che descrivi sono operazioni che possono essere eseguite sul sistema. È il modo in cui hai scelto di presentare all'utente le scelte che forse danno l'impressione di avere una logica di business nella vista.

Dal punto di vista "Visualizza" fornisce solo InfoY o InfoZ al sistema. Solo perché l'implementazione dell'interfaccia utente sta eseguendo alcuni aggiornamenti dinamici sulla base di una scelta dell'operatore (ovvero abilitazione di InfoY o InfoZ) non rende la funzionalità logica aziendale. Visualizza davvero la logica di implementazione. Avresti potuto semplicemente dare all'operatore la possibilità di inserire InfoY o InfoZ senza tutto ciò che lo abilitava. In quel contesto, la considereresti ancora una logica aziendale? In caso contrario, lo stesso vale per l'abilitazione / disabilitazione dinamica dei campi informativi.

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 utilizzare il sistema significa che la logica aziendale sta perdendo? Posso vedere come qualcuno potrebbe dire di sì, ma se credi in quel modo, la realtà è che non esiste una separazione della logica aziendale da nulla. Devi sapere cosa sta facendo / lavorando il sistema per realizzare qualcosa di significativo. Altrimenti, sarebbe semplicissimo creare un'unica vista e controller generici che funzionino con ogni possibile applicazione MVC. Ciò che sappiamo è impossibile.

In conclusione, penso che la tua definizione di logica aziendale non sia la stessa di altre definizioni.


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 -> Cosa fare -> Come arrivare -> Dove andare

Quindi, nel primo livello (la vista) ho qualcosa di simile:

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. Richiede un servizio (per gestire i corsi) un corso specifico. Tale servizio può fare molte più cose, come report, serache e così via. Il risultato è sempre un elenco o un oggetto specifico (come nell'esempio). I servizi sono la vera macchina, applicano le regole e accedono al repository (per gestire i dati).

Quindi, se inserisco i miei servizi, repository e DAOS in librerie diverse, posso usarlo anche in un programma basato su testo o in un sistema desktop basato su Windows senza cambiare 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 portarli. Il repository "compone" i dati grezzi in oggetti buisines in modo che il servizio possa funzionare.

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. È possibile modificare i Servizi se si desidera modificare la logica, ma ciò non deve interferire con i livelli sopra o sotto.

E puoi cambiare qualsiasi cosa in vista, anche la tecnologia (web, desktop, testo) ma ciò non implica in contatto nulla di seguito.

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

Parlando in sistemi basati sul web (Struts + JavaEE) ho un pacchetto controller GUI separato. Nella vista Azione do l'utente registrato e la classe mi dà 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;

Ricordati di tenerlo fuori dai servizi. Questa è roba VISUALIZZA. Tienilo nelle azioni Struts. Qualsiasi interazione di interfaccia deve essere completamente separata dal vero codice aziendale, quindi se porti il ​​tuo sistema, sarà facile tagliare ciò che non ti servirà più.


1

Nella maggior parte dei casi ci saranno problemi come "Se l'utente ha selezionato l'opzione x, l'applicazione deve consentirgli di fornire informazioni per y, in caso contrario dovrebbe fornire informazioni z"

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

  • Il controller allega un gestore per gli eventi di visualizzazione
  • La vista allega un gestore per gli eventi del 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 del modello modificato e aggiorna la vista in modo che corrisponda al nuovo stato: inputY.enable(model.yAllowed()); inputZ.enable(model.zAllowed());

UI View Controller Model |.checkbox X checked.> | | | | | .. X selected ...>| | | | |-----> set X ------->| | | | | | |< .............state changed ............| | | | | | |-------------- Get state --------------->| | | | | | |<----------- new state ------------------| | <-- UI updates ------| Questo è il classico modello 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 modello MVC dell'interfaccia utente (di solito) non è un modello a oggetti business. È solo il modello per lo stato dell'interfaccia utente. In un'applicazione desktop, può contenere riferimenti a più modelli di business. In un'applicazione Web 2.0, è una classe Javascript che mantiene lo stato dell'interfaccia utente e comunica tramite AJAX al server. È molto importante essere in grado di scrivere test unitari del modello di stato dell'interfaccia utente, poiché è qui che si trovano la maggior parte dei bug dell'interfaccia utente. La vista e il controller dovrebbero essere connettori molto sottili.


1
Immagino che tutto si riduca a ciò che credi sia la definizione di MVC. Questa versione aderisce sicuramente a un'interpretazione molto, molto rigorosa di MVC. Il problema è che questa interpretazione rigorosa raramente fornisce un sistema utile o mantenibile nella vita reale. Il motivo è che ogni volta che ti viene in mente un nuovo elemento dell'interfaccia utente / modo di fare qualcosa devi cambiare il modello. Il modello diventa quindi ingombro di proprietà inutili rilevanti solo per l'interfaccia utente. Questi non hanno nulla a che fare con l'applicazione che si sta tentando di creare, ma solo per come si desidera presentare i dati all'operatore. MALE!
Dunk,

Kevin, ti preghiamo di inserire le tue risposte qui nella casella dei commenti, quindi è facile per noi risponderti. Sono d'accordo con te. Non è possibile mantenere le informazioni dell'interfaccia (UI) senza alcun tipo di struttura, ma la nomenclatura "MODELLO" potrebbe essere fonte di confusione. Preferisco gestire le cose dell'interfaccia utente in un diverso pacchetto intercambiabile per essere facile fare ciò di cui parla @Dunk. Vedi la mia risposta
Magno C,

@MagnoC: ho modificato la sua risposta in risposta a Dunk perché pensavo che il testo aggiunto migliorasse la risposta. Ecco di cosa tratta il sito: domande e risposte. Modello è un termine piuttosto generale e, nel modello MVC, significa "modello di stato dell'interfaccia utente".
Kevin Cline

0

Una logica aziendale è più simile 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 aziendale, delegare la scelta al dominio. L'interfaccia utente agirà semplicemente sulla decisione.


0

Se l'utente ha selezionato l'opzione x, l'applicazione deve consentirgli di fornire informazioni per y, in caso contrario deve fornire informazioni z ".

Ci sono input che hanno valori richiesti basati in modo condizionale. Nella maggior parte degli ambienti con interfaccia grafica, ci sono molte scelte su come gestire gli input, in particolare 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 importa la logica aziendale. In un modo o nell'altro, il controller prenderà una decisione e dovrà dire alla vista "è necessario".

Il modo in cui la vista interpreta o implementa ciò non ha importanza dal punto di vista della logica aziendale. Crea un campo obbligatorio. Fai apparire un pop-up o spara a un cannone e dì all'utente di inserire y o semplicemente essere testardo e non lasciare che il povero utente faccia nulla finché non lo capisce.

E basti pensare che tutto ciò potrebbe essersi verificato perché il controller ha tentato di salvare e non ha inserito un valore per un campo obbligatorio nel database e stava semplicemente rispondendo a un errore del database. Non importa per quanto riguarda la vista.

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

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.