View Full Version : [MVC] Interdipendenze tra Model View e Controller
tomminno
09-02-2010, 10:17
In un paradigma MVC come è meglio istanziare i singoli componenti?
Questo pattern ha senso anche per programmi che hanno una semplice interfaccia o rappresenta solo una complicazione eccessiva?
Il seguente pseudo codice può essere considerato una implementazione valida del pattern?
Altre possibilità?
Il più delle volte mi pare una complicazione inutile che non porta a grossi benefici.
Main()
{
MainController c = new MainController ();
c.RenderView();
}
class MainController
{
//Così facendo però la testabilità non è il massimo, o dovrei complicare ulteriormente
//affidandomi a ViewFactory e ModelFactory solo per motivi di testabilità del controller?
private View view;
private Model model;
public MainController()
{
view = new View();//o ViewFactory.Create("MainView");
//oppure è il caso che la view abbia un riferimento all'interfaccia del controller
//e la comunicazione avvenga per eventi?
//view = new View(this);
//Magari in un metodo InitView...
view.OnClickSave += this.OnClickSave;
view.OnClickNewDialog += this.OnClickNewDialog;
//evento necessario per la validazione dei dati inseriti
view.OnText1ChangeToValidate += this.OnText1ChangeToValidate;
//modifica immediata del model o altro tipo mostra messagebox
view.OnCheckbox1Checked += this.OnCheckbox1Checked;
...
model = new Model();//o ModelFactory.Create("MainModel");
model.OnChange += this.OnModelChange;
}
public void RenderView()
{
view.Show();
}
private void OnModelChange(ModelData modelData)
{
//Aggiorno i dati visualizzati prendendoli dal model
//ModelData potrebbe essere un contenitore per la valorizzazione di 5 checkbox e 10 texbox
view.OnUpdate(modelData);
}
private void OnClickSave()
{
//Salvo i dati modificati dalla view
model.Save(view.ModelData);
}
private void OnClickNewDialog()
{
//Se devo mostrare un altro dialog o form la cui finestra padre è view
Controller2 c2 = new Controller2(view);//o ControllerFactory.Create("Controller2");
c2.RenderView();
}
}
CozzaAmara
09-02-2010, 11:13
Bah dipende, il pattern MVC ha diversi chiari vantaggi di cui puoi beneficiarne anche per progetti piccoli.
Diciamo che se non ti appoggi ad un framework già esistente ma fai una tua "libera interpretazione" del suddetto pattern forse è il caso di evitarlo per progetti piuttosto semplici dove avresti solamente un allungamento dei tempi di sviluppo.
nuovoUtente86
09-02-2010, 11:19
il MVC è una specializzazione del 3-tier, quindi sarebbe utili per qualsiasi tipo di progetto.
Utilizzando Java, ad esempio viene offerto aggratis dalla metodologia di sviluppo e listening dei componenti grafici.
tomminno
09-02-2010, 12:35
Bah dipende, il pattern MVC ha diversi chiari vantaggi di cui puoi beneficiarne anche per progetti piccoli.
Mi sto chiedendo anche quali. La complessità mi sembra sproporzionata rispetto ai benefici, oltretutto l'utilizzo delle interfacce tra GUI e Business mi sembra ottenga lo stesso effetto a livello di test e di separazione logica tra i componenti.
Alla fine il controller è solo un elemento in più che riceve comandi già gestiti dalla GUI/View e che non deve fare altro che reinoltrare al Business/Model.
E gestire il controller diventa noioso spesso nel caso in cui a seguito di una azione debbano essere disabilitati dei controlli, ovvero per la gestione dello stato della View.
Lo svantaggio è che dato un codice già scritto dover far comunicare tra di loro diversi MVC comincia ad essere impegnativo e spesso porta a refactoring di un certo rilievo, per cui spesso si parte già ad usare il cannone (penso a Front Controller) solo per l'eventualità di doverlo usare in futuro.
Diciamo che se non ti appoggi ad un framework già esistente ma fai una tua "libera interpretazione" del suddetto pattern forse è il caso di evitarlo per progetti piuttosto semplici dove avresti solamente un allungamento dei tempi di sviluppo.
Peccato che non ci siano framework esistenti per WinForm nè QT.
Ma ha senso l'utilizzo dell'MVC con questi toolkit?
Vedo framework per l'MVC praticamente solo in ambito web (dove effettivamente ha un suo perchè).
CozzaAmara
09-02-2010, 13:54
Mi sto chiedendo anche quali. La complessità mi sembra sproporzionata rispetto ai benefici, oltretutto l'utilizzo delle interfacce tra GUI e Business mi sembra ottenga lo stesso effetto a livello di test e di separazione logica tra i componenti.
Alla fine il controller è solo un elemento in più che riceve comandi già gestiti dalla GUI/View e che non deve fare altro che reinoltrare al Business/Model.
E gestire il controller diventa noioso spesso nel caso in cui a seguito di una azione debbano essere disabilitati dei controlli, ovvero per la gestione dello stato della View.
Lo svantaggio è che dato un codice già scritto dover far comunicare tra di loro diversi MVC comincia ad essere impegnativo e spesso porta a refactoring di un certo rilievo, per cui spesso si parte già ad usare il cannone (penso a Front Controller) solo per l'eventualità di doverlo usare in futuro.
Peccato che non ci siano framework esistenti per WinForm nè QT.
Ma ha senso l'utilizzo dell'MVC con questi toolkit?
Vedo framework per l'MVC praticamente solo in ambito web (dove effettivamente ha un suo perchè).
Alt, preciso: io mi riferisco alla programmazione per il web.
Parlo ad esempio di Framework MVC come: Symfony, Zend, Ruby on Rails ecc.
nuovoUtente86
09-02-2010, 14:25
In ambiente Desktop il MVC è spesso realizzato mediante l' utilizzo di Observer.
tomminno
09-02-2010, 16:36
Alt, preciso: io mi riferisco alla programmazione per il web.
Parlo ad esempio di Framework MVC come: Symfony, Zend, Ruby on Rails ecc.
Quindi escluso WPF con il suo MVVM, in ambito desktop è inutile perdere tempo dietro a MVC?
tomminno
09-02-2010, 16:48
In ambiente Desktop il MVC è spesso realizzato mediante l' utilizzo di Observer.
Quindi fondamentalmente una tradizionale comunicazione ad eventi tra GUI e Business.
nuovoUtente86
09-02-2010, 20:55
Come dicevo qualche post fa è una estensione del modello n-tier (solitamente 3-tier) per mezzo del controller.
In linea generale la view è l' observer mentre il modello rappresenta il subject, e grazie al disaccoppiamento possono stare in rapporto di 1 a molti (quindi avere più viste di uno stesso modello, classico l' esempio di un file di log e una GUI).
Sebbene in linea teorica le 2 entità dovrebbero dialogare esclusivamente per mezzo del controller, nella pratica, come si può evincere da quanto accennato circa l' observer, la view viene informata (o eventualmente può fare polling) attraverso il push dei dati, trasmessi dall' observable al momento di un cambio di stato ovvero la chiamata di un metodo update. Cosa se ne debba fare di questi dati ricevuto, è compito del controller stabilirlo, che inoltre lato view si occupa della gestione degli eventi, mentre lato model deve essere in grado di interagire (spesso viene usato il termine stimolare) con le funzionalità della logia dell' applicazione (in pratica deve conoscere l' interfaccia esposta dal model).
tomminno
10-02-2010, 07:48
Come dicevo qualche post fa è una estensione del modello n-tier (solitamente 3-tier) per mezzo del controller.
In linea generale la view è l' observer mentre il modello rappresenta il subject, e grazie al disaccoppiamento possono stare in rapporto di 1 a molti (quindi avere più viste di uno stesso modello, classico l' esempio di un file di log e una GUI).
Questo lo fai con o senza l'MVC anche in un normalissimo programma strutturato a 3 livelli. La Vista è comunque separata da chi genera i dati, puoi usare il pattern observer, puoi usare più brutalmente dei riferimenti diretti tramite interfacce.
Sebbene in linea teorica le 2 entità dovrebbero dialogare esclusivamente per mezzo del controller, nella pratica, come si può evincere da quanto accennato circa l' observer, la view viene informata (o eventualmente può fare polling) attraverso il push dei dati, trasmessi dall' observable al momento di un cambio di stato ovvero la chiamata di un metodo update. Cosa se ne debba fare di questi dati ricevuto, è compito del controller stabilirlo, che inoltre lato view si occupa della gestione degli eventi, mentre lato model deve essere in grado di interagire (spesso viene usato il termine stimolare) con le funzionalità della logia dell' applicazione (in pratica deve conoscere l' interfaccia esposta dal model).
Il problema magari non è solo il mostrare i dati, ma anche gestire la visualizzazione che dipende il più delle volte dai dati, è veramente necessario fare la fatica di duplicare la gestione dei singoli controlli grafici per far si che il controller gestisca ogni possibile stato (visibile/non visibile, abilitato/non abilitato, colore, ...)?
Quindi escluso WPF con il suo MVVM, in ambito desktop è inutile perdere tempo dietro a MVC?
penso dipenda dal framework cui ti appoggi. a titolo di esempio cocoa su os x è 100% mvc (e sei di fatto obbligato ad utilizzare questo paradigma)
CozzaAmara
10-02-2010, 11:11
Quindi escluso WPF con il suo MVVM, in ambito desktop è inutile perdere tempo dietro a MVC?
Non mi esprimo, non ho mai lavorato in ambito desktop se non per piccoli esercizi miei con Ruby e Qt.
Tuttavia non sarei così categorico perchè, se non ricordo male, il pattern MVC nasce in ambiente desktop e si riadatta poi anche per il web quindi ...
l'MVC comunque è uno strumento, nulla più, è sbagliato dire a priori che sia utile o inutile, dipende da mille fattori.
Se ritieni che nel tuo caso non serva non usarlo.
Poi magari fra qualche tempo acquisici esperienza in merito e ti rendi conto che forse era meglio seguire l'MVC.
Mai confondere il mezzo col fine.
nuovoUtente86
10-02-2010, 12:02
Questo lo fai con o senza l'MVC anche in un normalissimo programma strutturato a 3 livelli. La Vista è comunque separata da chi genera i dati, puoi usare il pattern observer, puoi usare più brutalmente dei riferimenti diretti tramite interfacce.
Il problema magari non è solo il mostrare i dati, ma anche gestire la visualizzazione che dipende il più delle volte dai dati, è veramente necessario fare la fatica di duplicare la gestione dei singoli controlli grafici per far si che il controller gestisca ogni possibile stato (visibile/non visibile, abilitato/non abilitato, colore, ...)?
Si la prima parte stabilisce unicamemte la separazione presentazione-logica.
Uno dei vantaggi nell' utilizzo di un mediatore come il controller è la riusabilità massima del codice, dovendo di fatto modificare o adattatore solo il controllore, mentre in una struttura a livelli classica la view deve al minimo conoscere e poter invocare l' interfaccia dello strato applicazione.
tomminno
10-02-2010, 14:46
Si la prima parte stabilisce unicamemte la separazione presentazione-logica.
Uno dei vantaggi nell' utilizzo di un mediatore come il controller è la riusabilità massima del codice, dovendo di fatto modificare o adattatore solo il controllore,
Modifichi sempre 1 elemento, in un caso la GUI in un altro il controller.
Ma nell'MVC se le modifiche a basso livello comportano (come quasi sempre quando avvengono modifiche al biz) modifiche visuali (cambio di un controllo, di una validazione, di uno stato della vista) ecco che con l'MVC devi modificare 2 elementi controller e view invece di 1, e lo stesso doppio lavoro lo dovrai fare su tutti i controller e tutte le view che insistono su quello stesso model modificato.
mentre in una struttura a livelli classica la view deve al minimo conoscere e poter invocare l' interfaccia dello strato applicazione.
In ogni caso la view deve conoscere chi gli sta sotto sia questo il controller o il biz o ancora la sua interfaccia. La vista dovrà per lo meno registrarsi agli eventi del controller per ricevere le modifiche dal model? E viceversa il controller dovrà a sua volta registrarsi agli eventi della vista. Dopotutto ogni vista ha il suo controller e quindi sono strettamente legati (anche solo da interfacce).
Non riesco a vedere la differenza rispetto ad un tradizionale sviluppo a n-livelli, se non la complicazione di un elemento in più che deve essere strettamente legato alla vista per gestirne lo stato. Solo che nei framework grafici lo stato della vista si gestisce bene dall'interno della vista stessa, senza necessitare di un elemento in più che deve intercettarne ogni singolo evento possibile. E ogni controllo grafico ha molti possibili eventi.
nuovoUtente86
10-02-2010, 15:38
Premetto che non sono un amante del MVC, ma alcune cosiderazioni vanno fatte.
Sempre restando nell' ambito della riutilizzabilità del codice e considerando il principio di open/closed è sempre meso dispendioso e anche più corretto andare a modificare un elemento bridge (come può essere il controller) rispetto ad operare sugli strati veri e propri. Riprendendo un esempio di prima, potrei usare un sistema di logging quasi standard, andando a modificare solo il controller (lato model) e sfruttando observer sull' asse view-model(anche se non dovrebbe starci).
La stessa cosa la potresti ottenere con una architettura a livelli standard, ma al minimo dovresti utilizzare un wrapper per il nuovo livello applicazione.
Quindi MVC, costituisce una possibile soluzione ma ve ne sono tante altre che garantisco lo stesso risultato, in maniera complementare o supplementare, a partire dal 3-tier, utilizzando un factory piuttosto che un proxy(magari dynamic) o ancora la reflection.
Bingo!!!
http://www.youtube.com/watch?v=cgeLY7CL5IE
tomminno
10-02-2010, 19:45
Premetto che non sono un amante del MVC, ma alcune cosiderazioni vanno fatte.
Sempre restando nell' ambito della riutilizzabilità del codice e considerando il principio di open/closed è sempre meso dispendioso e anche più corretto andare a modificare un elemento bridge (come può essere il controller) rispetto ad operare sugli strati veri e propri.
Il problema è che qui l'elemento che si interpone è strettamente legato ad uno dei 2 punti che vorrebbe congiungere.
Se modifichi solo il controller significa che hai delle modifiche nel model che non si ripercuotono sulla view, altrimenti avresti dovuto modificare anche la view e l'interazione view/controller oltre a quella controller/model.
Riprendendo un esempio di prima, potrei usare un sistema di logging quasi standard, andando a modificare solo il controller (lato model) e sfruttando observer sull' asse view-model(anche se non dovrebbe starci).
Cosa intendi per "usare un sistema di logging quasi standard"?
Visualizzazione di log che vengono aggiornati durante l'esecuzione del programma?
Personalmente preferisco che view e model non interagiscano per niente, e che la view dialoghi solo con il controller. Anche perchè se la view si collega in qualche modo con il model tanto vale non fare la fatica di usare il controller e sviluppare un semplice n-tier.
Ma forse sono io che non ho afferrato bene quali sono i compiti del controller, se deve essere solo un passa carte da e verso il model, oppure come l'ho inteso io, debba gestire lo stato della view.
Ma lo stato della view è composto da una infinità di fattori, più o meno pari al prodotto cartesiano di tutte le combinazioni delle proprietà di tutti i controlli presenti. Se ognuno di questi deve essere gestito dal controller dovremmo gestire decine di eventi per le interfacce più semplici fino a qualche centinaio se non di più per quelle un pò più complesse.
Oppure lo stato della View è gestito dalla View stessa e quindi non capisco nuovamente il ruolo del controller.
La stessa cosa la potresti ottenere con una architettura a livelli standard, ma al minimo dovresti utilizzare un wrapper per il nuovo livello applicazione.
Ovvero?
Se ho aggiunto la possibilità di visualizzare i log nel momento in cui vengono generati, devo per forza modificare la view, in un caso mi basta aggiungere una interfaccia ILogEventSource e legare la view agli eventi sollevati da questa (+ sincronizzazione), nell'altro caso è il controller a doversi interfacciare con questa per poi rimandare alla view i dati ricavati dall'evento, con in più il fatto di dover gestire magari anche lo stato del visualizzatore se ad esempio volessi mostrare solo gli ultimi 5 log.
Quindi MVC, costituisce una possibile soluzione ma ve ne sono tante altre che garantisco lo stesso risultato, in maniera complementare o supplementare, a partire dal 3-tier, utilizzando un factory piuttosto che un proxy(magari dynamic) o ancora la reflection.
No la reflection no! Ho un'avversione innata per la reflection... :)
nuovoUtente86
10-02-2010, 20:11
Il problema è che qui l'elemento che si interpone è strettamente legato ad uno dei 2 punti che vorrebbe congiungere.
Se modifichi solo il controller significa che hai delle modifiche nel model che non si ripercuotono sulla view, altrimenti avresti dovuto modificare anche la view e l'interazione view/controller oltre a quella controller/model.
non è detto, dipende da quanto siano di utilizzo generale la view e l' interfaccia esposta da questi verso lo strato presentazione.
Cosa intendi per "usare un sistema di logging quasi standard"?
Visualizzazione di log che vengono aggiornati durante l'esecuzione del programma?
Personalmente preferisco che view e model non interagiscano per niente, e che la view dialoghi solo con il controller. Anche perchè se la view si collega in qualche modo con il model tanto vale non fare la fatica di usare il controller e sviluppare un semplice n-tier.
la dipendenza tra view e model è mantenuta solo a livello concettuale (anche se non dovrebbe essere cosi, ma ormai è universalmente riconosciuto lo sia ), in quanto a livello pratico risultano legati da deboli legami di conoscenza (la view deve unicamente registrarsi come ascoltatore di stato del model, tradotto in codice la view si aspetta un Observable indipendentemente dalle altre 1000 funzioni il modello esponga).
Ma forse sono io che non ho afferrato bene quali sono i compiti del controller, se deve essere solo un passa carte da e verso il model, oppure come l'ho inteso io, debba gestire lo stato della view.
Ma lo stato della view è composto da una infinità di fattori, più o meno pari al prodotto cartesiano di tutte le combinazioni delle proprietà di tutti i controlli presenti. Se ognuno di questi deve essere gestito dal controller dovremmo gestire decine di eventi per le interfacce più semplici fino a qualche centinaio se non di più per quelle un pò più complesse.
Oppure lo stato della View è gestito dalla View stessa e quindi non capisco nuovamente il ruolo del controller.
Lo stato della view deve essere gestito dal controller che inoltre ha il compito di intercettare e getire gli eventi, stimolando opportune funzioni del model.
Quello che il controller non fa è comunicare alla view cambiamenti di stato nel livello applicazioni, in quanto gli stessi (spesso sotto forma di dati da spare in output)vengono pushati dalla layer business alla Gui, il come questi debbano essere gestiti è lavoro peculiare del controller.
In molti framework (swing in primis), la distinzione tra view e controller non è cosi netta ma le 2 entità finisco per collassare quasi in un tutt' uno, nel caso specifico per il sistema di gestione degli eventi.
Ovvero?
Se ho aggiunto la possibilità di visualizzare i log nel momento in cui vengono generati, devo per forza modificare la view, in un caso mi basta aggiungere una interfaccia ILogEventSource e legare la view agli eventi sollevati da questa (+ sincronizzazione), nell'altro caso è il controller a doversi interfacciare con questa per poi rimandare alla view i dati ricavati dall'evento, con in più il fatto di dover gestire magari anche lo stato del visualizzatore se ad esempio volessi mostrare solo gli ultimi 5 log.
No intendevo qualcosa di diverso: potrebbe essere necessario affiancare alla visualizzazione grafica un log su file, quindi in questo caso basterebbe semplicemente conoscere l' interfaccia del controller, senza sapere come agisce il resto.
tomminno
10-02-2010, 23:15
Lo stato della view deve essere gestito dal controller che inoltre ha il compito di intercettare e getire gli eventi, stimolando opportune funzioni del model.
Non tutte le azioni della View comportano modifiche al model, un esempio è il classico MessageBox al click su qualche controllo, non è il primo click che modifica il model ma l'Ok sul MessageBox. In tal caso c'è un evento che passa da View al Controller per il primo click, poi un evento dal controller al View che indica al View di mostrare il MessageBox e tutte le opzioni possibili del MessageBox (ovviamente senza sapere niente dell'oggetto grafico MessageBox), sull'ok si ripassa dalla view e di lì nuovamente al controller che poi eventulamente passerà l'informazione al model.
E il problema si complica se vogliamo mostrare un altro dialog che comporta l'ingresso di un altra tripletta MVC, quindi il controller deve avviare un altro controller e passargli le informazioni per avvisarlo di mostrare una view modale o magari no, in primo piano o magari no, che magari deve riportare delle modifiche grafiche sulla prima view (penso alle classiche barre degli strumenti di tutti gli editor di immagini, dove un click su un dialog comporta cambiamenti nello stato della finestra principale) piuttosto che no, poi chissà magari il model è lo stesso perchè i dati sono correlati a quelli mostrati precedentemente ovvero sono legati allo stato del primo model, quindi bisogna fare in modo che il nuovo controller gestisca lo stesso model del precedente, perchè può essere che dipenda dal contesto e in certi casi necessiti di un nuovo model e in altri no...
Quello che il controller non fa è comunicare alla view cambiamenti di stato nel livello applicazioni, in quanto gli stessi (spesso sotto forma di dati da spare in output)vengono pushati dalla layer business alla Gui, il come questi debbano essere gestiti è lavoro peculiare del controller.
Che però non è a conoscenza degli elementi grafici che dovranno mostrare questi dati.
Il controller è tenuto a sapere che un messaggio verrà mostrato su un MessageBox piuttosto che su una label di errore? In tal caso deve sapere che il MessageBox ha un testo, un titolo, una immagine e tanti pulsanti possibili da visualizzare, nell'altro caso deve sapere che una label ha il testo, il colore, il font e ovviamente li deve comunicare alla finestra.
Si limita a mandare alla view un evento di "Mostra messaggio" che poi la view mostrerà come meglio crede? Ma in questo caso il controller non mantiene lo stato della view.
E che si intende esattamente per stato della view? La conoscenza dello stato di ogni controllo in essa contenuto? Lo stato dei dati da mostrare? Altro?
In molti framework (swing in primis), la distinzione tra view e controller non è cosi netta ma le 2 entità finisco per collassare quasi in un tutt' uno, nel caso specifico per il sistema di gestione degli eventi.
Praticamente in tutti i framework la gestione degli eventi è annegata nella gestione stessa della gui. Se ho un pulsante in una finestra l'evento click (e tutti gli altri) mi viene passato ad un metodo dalla finestra stessa. Perchè dovrei fare la fatica di segnalare l'evento a qualcun altro che poi dovrà in maniera un pò astratta indicare nuovamente alla finestra cosa fare di quel click?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.