MVC (Model, View, Controller) è un modello per l'organizzazione del codice in un'applicazione per migliorare la manutenibilità.
Immagina un fotografo con la sua macchina fotografica in uno studio. Un cliente gli chiede di scattare una foto di una scatola.
Le architetture non MVC tendono ad essere strettamente integrate insieme. Se la scatola, il controller e la videocamera fossero lo stesso oggetto, allora dovremmo separarci e ricostruire sia la scatola che la videocamera ogni volta che desideriamo ottenere una nuova vista. Inoltre, scattare la foto sarebbe sempre come provare a fare un selfie - e non è sempre molto facile.
bwaha ha scritto:
L'autore fa riferimento a mvctree.py in wxPython come esempio di progettazione MVC. Comunque sono ancora troppo verde quindi trovo quell'esempio particolare troppo complesso e non capisco la separazione che l'autore sta raccomandando.
MVC è tutto sulla separazione delle preoccupazioni.
Il modello è responsabile della gestione dei dati del programma (sia privati che client). Il View / Controller è responsabile di fornire al mondo esterno i mezzi per interagire con i dati del client del programma.
Il modello fornisce un'interfaccia interna (API) per consentire ad altre parti del programma di interagire con esso. View / Controller fornisce un'interfaccia esterna (GUI / CLI / modulo web / IPC di alto livello / ecc.) Per consentire a tutto ciò che è estraneo al programma di comunicare con esso.
Il Modello è responsabile del mantenimento dell'integrità dei dati del programma, perché se viene danneggiato, il gioco è finito per tutti. Il View / Controller è responsabile del mantenimento dell'integrità dell'interfaccia utente, assicurandosi che tutte le visualizzazioni di testo visualizzino valori aggiornati, disabilitando le voci di menu che non si applicano al focus corrente, ecc.
Il modello non contiene alcun codice View / Controller; nessuna classe di widget GUI, nessun codice per la disposizione di finestre di dialogo o la ricezione di input da parte dell'utente. La vista / controller non contiene alcun codice modello; nessun codice per la convalida degli URL o l'esecuzione di query SQL e nessuno stato originale: tutti i dati detenuti dai widget sono solo a scopo di visualizzazione e sono semplicemente un riflesso dei dati reali memorizzati nel modello.
Ora, ecco il test di un vero design MVC: il programma dovrebbe in sostanza essere perfettamente funzionante anche senza un View / Controller collegato. OK, il mondo esterno avrà difficoltà ad interagire con esso in quella forma, ma fino a quando si conoscono gli incantesimi API modello appropriati, il programma manterrà e manipolerà i dati normalmente.
Perché è possibile? Bene, la semplice risposta è che è tutto grazie al basso accoppiamento tra i livelli Model e View / Controller. Tuttavia, questa non è la storia completa. La chiave di tutto il modello MVC è la direzione in cui va quella connessione: TUTTE le istruzioni scorrono dalla vista / controller al modello. Il modello MAI dice al View / Controller cosa fare.
Perché? Perché in MVC, mentre al View / Controller è permesso conoscere un po 'del Modello (in particolare, l'API del Modello), ma al Modello non è permesso sapere nulla del View / Controller.
Perché? Perché MVC riguarda la creazione di una chiara separazione delle preoccupazioni.
Perché? Per aiutare a prevenire la complessità del programma che sfugge al controllo e seppellisce te, lo sviluppatore, sotto di esso. Maggiore è il programma, maggiore è il numero di componenti in quel programma. E più connessioni esistono tra questi componenti, più è difficile per gli sviluppatori mantenere / estendere / sostituire i singoli componenti o anche semplicemente seguire il funzionamento dell'intero sistema. Chiediti questo: guardando un diagramma della struttura del programma, preferiresti vedere un albero o la culla di un gatto? Il modello MVC evita quest'ultimo impedendo le connessioni circolari: B può connettersi ad A, ma A non può connettersi a B. In questo caso, A è il modello e B è il View / Controller.
A proposito, se sei acuto, noterai un problema con la restrizione "unidirezionale" appena descritta: come può il Modello informare il View / Controller dei cambiamenti nei dati dell'utente del Modello quando il Modello non è nemmeno autorizzato a sai che il View / Controller, non importa inviare messaggi ad esso? Ma non preoccuparti: esiste una soluzione a questo, ed è piuttosto pulito anche se all'inizio sembra un po 'rotonda. Torneremo su questo tra un momento.
In termini pratici, quindi, un oggetto View / Controller può, tramite l'API del Modello, 1. dire al Modello di fare cose (eseguire comandi) e 2. dire al Modello di dargli cose (restituire dati). Il livello Visualizza / Controller
invia le istruzioni al livello Modello e estrae informazioni dal livello Modello.
Ed è qui che il tuo primo esempio di MyCoolListControl va storto, perché l'API per quella classe richiede che le informazioni vengano inserite
al suo interno, quindi sei tornato ad avere un accoppiamento a due vie tra i livelli, violando le regole MVC e scaricandoti di nuovo nel l'architettura della culla di gatto che stavi [presumibilmente] cercando di evitare in primo luogo.
Invece, la classe MyCoolListControl dovrebbe andare con il flusso, estraendo i dati di cui ha bisogno dal livello sottostante, quando ne ha bisogno. Nel caso di un widget elenco, ciò significa generalmente chiedere quanti valori ci sono e quindi chiedere ciascuno di questi elementi a turno, perché si tratta del modo più semplice e più lento di farlo e quindi riduce al minimo il tipo di accoppiamento. E se il widget vuole, per esempio, presentare questi valori all'utente in un piacevole ordine alfabetico, allora è perogativo; e la sua responsabilità, ovviamente.
Ora, un ultimo enigma, come ho accennato in precedenza: come mantenere sincronizzato il display dell'interfaccia utente con lo stato del modello in un sistema basato su MVC?
Ecco il problema: molti oggetti View sono statiful, ad esempio una casella di controllo può essere spuntata o deselezionata, un campo di testo può contenere del testo modificabile. Tuttavia, MVC impone che tutti i dati utente vengano archiviati nel livello Modello, quindi tutti i dati conservati da altri livelli a scopo di visualizzazione (lo stato della casella di controllo, il testo corrente del campo di testo) devono quindi essere una copia sussidiaria di tali dati Modello principali. Ma se lo stato del modello cambia, la copia della vista di quello stato non sarà più accurata e dovrà essere aggiornata.
Ma come? Il modello MVC impedisce al modello di inviare una nuova copia di tali informazioni nel livello Visualizza. Diamine, non consente nemmeno al Modello di inviare a Visualizza un messaggio per dire che il suo stato è cambiato.
Be 'quasi. Va bene, al layer Model non è consentito parlare direttamente con altri layer, poiché per farlo sarebbe necessario sapere qualcosa su quei layer e le regole MVC lo impediscono. Tuttavia, se un albero cade in una foresta e nessuno è in giro per ascoltarlo, emette un suono?
La risposta, vedi, è quella di creare un sistema di notifiche, fornendo al livello Modello un posto in cui non può annunciare a nessuno in particolare che abbia appena fatto qualcosa di interessante. Altri layer possono quindi pubblicare gli ascoltatori con quel sistema di notifica per ascoltare gli annunci a cui sono effettivamente interessati. Il layer Model non ha bisogno di sapere nulla su chi sta ascoltando (o anche se qualcuno sta ascoltando!); pubblica solo un annuncio e poi se ne dimentica. E se qualcuno ascolta quell'annuncio e ha voglia di fare qualcosa in seguito - come chiedere al Modello alcuni nuovi dati in modo che possa aggiornare il suo display su schermo - allora fantastico. Il modello elenca solo le notifiche che invia come parte della sua definizione API; e ciò che chiunque altro fa con quella conoscenza dipende da loro.
MVC è preservato e tutti sono felici. Il framework delle applicazioni potrebbe anche fornire un sistema di notifiche integrato, oppure puoi scrivere il tuo in caso contrario (vedi il "modello di osservatore").
...
Comunque, spero che ti aiuti. Una volta comprese le motivazioni alla base di MVC, le ragioni per cui le cose vengono fatte in questo modo iniziano a dare un senso, anche quando - a prima vista - sembrano più complesse del necessario.
Saluti,
ha