Cosa va nel "Controller" in "MVC"?


Penso di capire i concetti di base di MVC: il modello contiene i dati e il comportamento dell'applicazione, la Vista è responsabile della visualizzazione all'utente e il Controller si occupa dell'input dell'utente. Ciò di cui sono incerto è esattamente ciò che va nel Controller.

Diciamo ad esempio che ho un'applicazione abbastanza semplice (sto pensando specificamente a Java, ma suppongo che gli stessi principi si applichino altrove). Organizzo il mio codice in 3 pacchetti chiamati app.model, app.view e app.controller.

All'interno del pacchetto app.model, ho alcune classi che riflettono il comportamento effettivo dell'applicazione. Questi extends Observable e usano setChanged() e notifyObservers() per attivare le viste da aggiornare quando appropriato.

Il pacchetto app.view ha una classe (o più classi per diversi tipi di display) che utilizza i componenti javax.swing per gestire il display. Alcuni di questi componenti devono essere inseriti nel Modello. Se ho capito bene, la vista non dovrebbe avere nulla a che fare con il feedback-che dovrebbe essere affrontato dal Controller.

Quindi cosa metto effettivamente nel Controller? Metto public void actionPerformed(ActionEvent e) nella vista con solo una chiamata a un metodo nel Controller? In tal caso, qualsiasi convalida ecc. dovrebbe essere eseguita nel Controller? In tal caso, come faccio a riportare i messaggi di errore alla Vista - dovrebbe passare nuovamente attraverso il modello, o il Controller dovrebbe semplicemente inviarlo direttamente alla Vista?

Se la convalida viene eseguita nella vista, cosa inserisco nel Controllore?

Scusa per la lunga domanda, volevo solo documentare la mia comprensione del processo e spero che qualcuno possa chiarire questo problema per me!

Author: victor hugo, 2009-06-19

13 answers

Nell'esempio che hai suggerito, hai ragione: "l'utente ha fatto clic sul pulsante 'Elimina questo elemento'" nell'interfaccia dovrebbe fondamentalmente chiamare la funzione "elimina" del controller. Il controller, tuttavia, non ha idea di come sia la vista, e quindi la tua vista deve raccogliere alcune informazioni come "quale elemento è stato cliccato?"

In una forma di conversazione:

View : "Ehi, controller, l'utente mi ha appena detto che vuole l'articolo 4 cancellato."
Controller: "Hmm, dopo aver controllato le sue credenziali, gli è permesso farlo... Ehi, modella, voglio che tu prenda l'articolo 4 e faccia tutto il possibile per cancellarlo."
Modello : "Punto 4... capito. E ' cancellato. Torniamo a te, Controllore."
Controller: "Qui, raccoglierò il nuovo set di dati. Torniamo a te, view."
View : "Cool, mostrerò il nuovo set all'utente ora."

Alla fine di quella sezione, hai un'opzione: o la vista può fare una richiesta separata, "dammi il set di dati più recente", e quindi essere più puro, o il controller restituisce implicitamente il nuovo set di dati con l'operazione "elimina".

 456
Author: Andres Jaan Tack, 2010-08-23 18:47:53

Il problema con MVC è che le persone pensano che la vista, il controller e il modello debbano essere il più indipendenti possibile l'uno dall'altro. Non lo fanno - una vista e un controller sono spesso intrecciati-pensano come M(VC).

Il controller è il meccanismo di input dell'interfaccia utente, che è spesso aggrovigliato nella vista, in particolare con le GUI. Tuttavia, la vista è in uscita e il controller è in ingresso. Una vista può spesso funzionare senza un controller corrispondente, ma un controller è di solito molto meno utile senza una vista. I controller user-friendly utilizzano la vista per interpretare l'input dell'utente in modo più significativo e intuitivo. Questo è ciò che rende difficile separare il concetto di controller dalla vista.

Pensa a un robot radiocomandato su un campo di rilevamento in una scatola sigillata come modello.

Il modello riguarda le transizioni di stato e di stato senza alcun concetto di output (display) o ciò che sta innescando le transizioni di stato. Posso prendere il robot posizione sul campo e il robot sa come transizione posizione (fare un passo avanti/indietro/sinistra/destra. Facile da immaginare senza una vista o un controller, ma non fa nulla di utile

Pensa a una vista senza un controller, ad esempio qualcuno in un'altra stanza della rete in un'altra stanza che guarda la posizione del robot come coordinate (x,y) in streaming su una console a scorrimento. Questa vista mostra solo lo stato del modello, ma questo ragazzo non ha controller. Ancora una volta, facile immaginare questa vista senza un controller.

Pensa a un controller senza vista, ad esempio qualcuno chiuso in un armadio con il controller radio sintonizzato sulla frequenza del robot. Questo controller invia input e causa transizioni di stato senza idea di cosa stanno facendo al modello (se non altro). Facile da immaginare, ma non davvero utile senza una sorta di feedback dalla vista.

L'interfaccia utente più intuitiva coordina la vista con il controller per fornire un'interfaccia utente più intuitiva. Per ad esempio, immagina una vista / controller con un touch-screen che mostra la posizione corrente del robot in 2-D e consente all'utente di toccare il punto sullo schermo che si trova di fronte al robot. Il controller ha bisogno di dettagli sulla vista, ad esempio la posizione e la scala della finestra e la posizione dei pixel del punto toccato rispetto alla posizione dei pixel del robot sullo schermo) per interpretarlo correttamente (a differenza del ragazzo bloccato nell'armadio con la radio controller).

Ho già risposto alla tua domanda? :-)

Il controller è tutto ciò che prende input dall'utente che viene utilizzato per causare lo stato di transizione del modello. Cerca di mantenere la vista e il controller separati, ma renditi conto che sono spesso interdipendenti l'uno dall'altro, quindi va bene se il confine tra loro è sfocato, cioè avere la vista e il controller come pacchetti separati potrebbe non essere così separati come vorresti, ma va bene. Potrebbe essere necessario accettare il il controller non sarà separato in modo pulito dalla vista poiché la vista proviene dal modello.

... dovrebbe essere qualsiasi convalida ecc fatto nel controller? Se sì, come fare I messaggi di errore di feedback torna al Vista-dovrebbe passare attraverso il Modello di nuovo, o dovrebbe il controller basta inviare subito indietro per Visualizzare?

Se la convalida viene eseguita nella Vista, cosa metto nel controller?

Dico che una vista e un controller collegati dovrebbero interagire liberamente senza passare attraverso il modello. Il controller prende l'input dell'utente e dovrebbe eseguire la convalida (magari utilizzando le informazioni dal modello e/o dalla vista), ma se la convalida fallisce, il controller dovrebbe essere in grado di aggiornare direttamente la sua vista correlata (ad esempio messaggio di errore).

Il test acido per questo è chiedersi se una vista indipendente (cioè il ragazzo nell'altra stanza che guarda la posizione del robot attraverso la rete) dovrebbe vedere qualcosa o meno come risultato di qualcun altro il ragazzo nell'armadio ha cercato di dire al robot di uscire dal campo). In generale, la risposta è no: l'errore di convalida ha impedito la transizione di stato. Se non c'era tranistion stato (il robot non si muoveva), non c'è bisogno di dire le altre viste. Il ragazzo nell'armadio non ha ricevuto alcun feedback che ha cercato di causare una transizione illegale (nessuna interfaccia utente vista - cattiva), e nessun altro ha bisogno di saperlo.

Se il ragazzo con il touchscreen ha cercato di invia il robot fuori dal campo, ha ottenuto un bel messaggio facile da usare chiedendo che non uccidere il robot con l'invio fuori dal campo di rilevamento, ma ancora una volta, nessun altro ha bisogno di sapere questo.

Se altre viste hanno bisogno di sapere su questi errori, allora stai effettivamente dicendo che gli input dell'utente e gli eventuali errori risultanti sono parte del modello e il tutto è un po ' più complicato ...

 57
Author: Bert F, 2010-04-17 14:19:23

Ecco un buon articolo sulle basi di MVC.

Afferma ...

Controller-Il controller traduce interazioni con la vista in azioni che devono essere eseguite dal modello.

In altre parole, la tua logica aziendale. Il controller risponde alle azioni intraprese dall'utente nella vista e risponde. Si inserisce la convalida qui e si seleziona la vista appropriata se la convalida fallisce o ha esito positivo (pagina di errore, finestra di messaggio, qualunque).

C'è un altro buon articolo su Fowler.

 23
Author: JP Alioto, 2017-09-14 15:47:47

Il modello MVC vuole semplicemente separare la presentazione (=vista) dalla logica di buisiness (=modello). La parte del controller è lì solo per causare confusione.

 14
Author: Dimitri C., 2009-11-23 09:23:56

In base alla tua domanda, ho l'impressione che tu sia un po ' confuso sul ruolo del Modello. Il modello è fissato sui dati associati all'applicazione; se l'app ha un database, il compito del modello sarà quello di parlare con esso. Gestirà anche qualsiasi logica semplice associata a tali dati; se si dispone di una regola che lo dice per tutti i casi in cui la TABELLA.foo = = " Urrà!"e TAVOLO.bar = = " Huzzah!"poi impostare TAVOLO.campo= " W00t!", quindi vuoi che il Modello si prenda cura di esso.

Il Controller è ciò che dovrebbe gestire la maggior parte del comportamento dell'applicazione. Quindi per rispondere alle tue domande:

"Metto il public void actionPerformed(ActionEvent e) nella vista con solo una chiamata a un metodo nel Controller?"

Direi di no. Direi che dovrebbe vivere nel Controller; la Vista dovrebbe semplicemente alimentare i dati provenienti dall'interfaccia utente nel Controller e lasciare che il Controller decida quali metodi dovrebbero essere chiamati in risposta.

"Se è così, dovrebbe qualsiasi convalida ecc."

La maggior parte della convalida dovrebbe essere eseguita dal Controller; dovrebbe rispondere alla domanda se i dati siano validi o meno e, in caso contrario, inviare i messaggi di errore appropriati alla Vista. In pratica, è possibile incorporare alcuni semplici controlli di integrità nel livello di visualizzazione per migliorare l'esperienza dell'utente. (Sto pensando principalmente agli ambienti web, in cui potresti voler far apparire un messaggio di errore al momento l'utente preme "Invia" piuttosto che attendere l'intero ciclo di invio -> processo -> caricamento della pagina prima di dire loro che hanno rovinato.) Fai attenzione ; non vuoi duplicare lo sforzo più di quanto devi, e in molti ambienti (di nuovo, sto pensando al web) spesso devi trattare tutti i dati provenienti dall'interfaccia utente come un pacchetto di bugie sporche e sporche finché non hai confermato che è effettivamente legittimo.

" In tal caso, come faccio a riportare i messaggi di errore alla Vista-dovrebbe passare nuovamente attraverso il modello, o il Controller dovrebbe semplicemente inviarlo direttamente alla vista?"

Dovresti avere un protocollo impostato in cui la Vista non sa necessariamente cosa succede dopo finché il Controller non lo dice. Quale schermata li mostri dopo che l'utente ha colpito quel pulsante? La vista potrebbe non saperlo e il Controller potrebbe non saperlo fino a quando non esamina i dati appena ricevuti. Potrebbe essere "Vai a quest'altra schermata, come previsto" o " Rimani su questa schermata e visualizza questo errore messaggio".

Nella mia esperienza, la comunicazione diretta tra il Modello e la Vista dovrebbe essere molto, molto limitata e la Vista non dovrebbe alterare direttamente nessuno dei dati del modello; questo dovrebbe essere il lavoro del Controller.

"Se la convalida viene eseguita nella Vista, cosa inserisco nel Controller?"

Vedi sopra; la vera convalida dovrebbe essere nel Controller. E spero che tu abbia un'idea di cosa dovrebbe essere messo nel Controller ormai. :-)

Vale la pena notare che tutto può diventare un po ' sfocato intorno ai bordi; come con la maggior parte di qualsiasi cosa complessa come l'ingegneria del software, le chiamate di giudizio abbonderanno. Basta usare il vostro giudizio migliore, cercare di rimanere coerenti all'interno di questa applicazione, e cercare di applicare le lezioni che si impara al prossimo progetto.

 9
Author: BlairHippo, 2009-06-19 00:44:53

In pratica, non ho mai trovato il concetto di controller particolarmente utile. Uso una rigorosa separazione modello / vista nel mio codice ma non esiste un controller chiaramente definito. Sembra essere un'astrazione non necessaria.

Personalmente, MVC in piena regola sembra il modello di progettazione di fabbrica in quanto porta facilmente a un design confuso e troppo complicato. Non essere un astronauta di architettura .

 9
Author: John Kugelman, 2017-05-23 10:31:26

Controller è davvero parte della Vista. Il suo compito è capire quali servizi sono necessari per soddisfare la richiesta, i valori unmarshal dalla Vista agli oggetti richiesti dall'interfaccia del servizio, determinare la vista successiva e marshallare la risposta in un modulo che la vista successiva può utilizzare. Gestisce anche tutte le eccezioni che vengono generate e le rende in viste che gli utenti possono capire.

Il livello di servizio è la cosa che conosce i casi d'uso, le unità di lavoro e il modello oggetto. Il controller sarà diverso per ogni tipo di vista: non avrai lo stesso controller per le UI desktop, basate su browser, Flex o mobili. Quindi dico che fa davvero parte dell'interfaccia utente.

Orientato ai servizi: è qui che viene svolto il lavoro.

 7
Author: duffymo, 2009-06-19 01:16:54

Il controller serve principalmente per il coordinamento tra la vista e il modello.

Purtroppo, a volte finisce per essere mescolato con la vista-in piccole applicazioni anche se questo non è male.

Ti suggerisco di mettere il:

public void actionPerformed(ActionEvent e)

Nel controller. Quindi il tuo listener di azioni nella tua vista dovrebbe delegare al controller.

Per quanto riguarda la parte di convalida, puoi metterlo nella vista o nel controller, personalmente penso che appartenga nel controller.

Consiglio vivamente di dare un'occhiata a Passive View e Supervisionare Presenter (che è essenzialmente in quale Model View Presenter è diviso - almeno da Fowler). Vedi:

Http://www.martinfowler.com/eaaDev/PassiveScreen.html

Http://www.martinfowler.com/eaaDev/SupervisingPresenter.html

 3
Author: Jon, 2009-06-19 00:40:21

Ecco una regola empirica che uso: se è una procedura che userò specificamente per un'azione su questa pagina , appartiene al controller, non al modello. Il modello dovrebbe fornire solo un'astrazione coerente alla memorizzazione dei dati.

L'ho inventato dopo aver lavorato con una webapp di grandi dimensioni scritta da sviluppatori che pensavano di essere stati capiti MVC ma in realtà no. I loro "controller" sono ridotti a otto righe di chiamata di metodi di classe statici che di solito sono chiamati da nessun'altra parte :-/ rendendo i loro modelli poco più che modi di creare spazi dei nomi. Refactoring questo fa correttamente tre cose: sposta tutto l'SQL nel livello di accesso ai dati (modello aka), rende il codice del controller un po ' più dettagliato ma molto più comprensibile e riduce i vecchi file "modello" a nulla. :-)

 3
Author: staticsan, 2009-06-19 01:02:49

Si noti inoltre che ogni widget Swing può essere considerato contenere i tre componenti MVC: ognuno ha un modello (cioè ButtonModel), una Vista (BasicButtonUI) e un controllo (JButton stesso).

 1
Author: akf, 2009-06-19 01:00:47

Hai essenzialmente ragione su ciò che hai inserito nel controller. È l'unico modo in cui il Modello dovrebbe interagire con la Vista. Actionperformed può essere posizionato nella vista, ma la funzionalità effettiva può essere posizionata in un'altra classe che fungerebbe da Controller. Se hai intenzione di farlo, ti consiglio di esaminare il modello di comando, che è un modo per astrarre tutti i comandi che hanno lo stesso ricevitore. Scusa per la digressione.

Comunque, un MVC corretto l'implementazione avrà solo le seguenti interazioni: Modello - > Vista Vista - > Controllore Controller - > Visualizza

L'unico posto in cui potrebbe esserci un'altra interazione è se si utilizza un osservatore per aggiornare la Vista, la Vista dovrà chiedere al Controller le informazioni di cui ha bisogno.

 1
Author: mnuzzo, 2009-06-19 01:12:32

A quanto ho capito, il Controller traduce dalle azioni dell'interfaccia utente alle azioni a livello di applicazione. Ad esempio, in un videogioco il controller potrebbe tradurre "spostato il mouse così tanti pixel" in "vuole guardare in tale e tale direzione. In un'app CRUD, la traduzione potrebbe essere "cliccata su tale e tale pulsante" per "stampare questa cosa", ma il concetto è lo stesso.

 0
Author: David Seiler, 2009-06-19 00:05:20

Lo facciamo così, usando i controller principalmente per gestire e reagire agli input/azioni guidati dall'utente (e _Logic per tutto il resto, tranne view, data e ovvi _Model stuff):

(1) (response, reaction-ciò che la webapp "fa" in risposta all'utente) Blog_Controller

- > principale ()

- > handleSubmit_AddNewCustomer ()

- > verifyUser_HasProperAuth ()

(2) ("business" logica, cosa e come la webapp "pensare") Blog_Logic

- > sanityCheck_AddNewCustomer ()

- > handleUsernameChange ()

- >sendEmail_NotifyRequestedUpdate ()

(3) (viste, portali, come appare la webapp "") Blog_View

- > genWelcome ()

- > genForm_AddNewBlogEntry ()

- > genPage_DataEntryForm ()

(4) (solo oggetto dati, acquisito in _ construct () di ogni Blog* classe, utilizzato per mantenere tutti i dati webapp/inmemory insieme come un unico oggetto) Blog_Meta

(5) (livello dati di base, legge / scrive in DB) Blog_Model

- > Salvadatomemcache ()

->saveDataToMongo ()

- > saveDataToSql ()

- >loadData ()

A volte ci confondiamo un po ' su dove mettere un metodo, nella C o nella L. Ma il modello è solido come una roccia, cristallino, e poiché tutti i dati in memoria risiedono nella _Meta, è un gioco da ragazzi anche lì. Il nostro più grande balzo in avanti è stato l'adozione dell'uso _Meta, a proposito, poiché questo ha eliminato tutto il crud dal vari oggetti _C, _L e _Model, hanno reso tutto mentalmente facile da gestire, inoltre, in un colpo solo, ci ha dato quella che viene chiamata "Iniezione di dipendenza", o un modo per passare intorno a un intero ambiente insieme a tutti i dati (il cui bonus è la facile creazione di un ambiente" test").

 0
Author: FYA, 2011-05-20 16:22:49