Perché tutti mettono i controller in una cartella e le visualizzazioni in un'altra?


36

Mi sto preparando per uscire da asp e entrare in un framework mvc, asp.net mvc o nancy. Ovunque vada, vedo cartelle per controller / moduli e cartelle per visualizzazioni. È solo un riflesso pavloviano di riordinare le cose per tipo o c'è qualche saggezza più profonda che opera? Ho un piccolo progetto di prova di concetto in cui memorizzo insieme i file che probabilmente aprirò insieme, un notevole conforto. Poiché è probabile che anche questi file si chiamino l'un l'altro, possono farlo con collegamenti relativi più brevi, meno fragili. Questo modello è sfidato da mvc, perché il percorso della cartella non corrisponde più automaticamente al percorso dell'URL e, in asp.net mvc, i modelli di progetto e il routing applicano le viste \ controller \ scisma.

Questa pagina di microsoft introduce il concetto di aree. Può essere letto come un'ammissione di quanto ingombranti app diventano grandi a causa di questa separazione artificiale.

Le persone si opporranno alla "separazione delle preoccupazioni", ma la separazione delle preoccupazioni è già ottenuta con file sorgente separati. Non c'è alcun guadagno concreto, mi sembra, dal prendere questi file sorgente che sono strettamente accoppiati e inviarli alle estremità opposte della struttura delle cartelle?

Qualcun altro sta combattendo questo? Qualche consiglio?


3
Non pensi che sia logico separare i file di codice back-end dai file di visualizzazione? Se stiamo già prendendo la direzione, perché non mettere anche i file CSS e JavaScript pertinenti nella stessa cartella?
Alternatex,

2
Se ottieni Resharper, F12 sulla chiamata a Viewnel controller ti porta alla vista e la prima opzione nel menu di scelta rapida sulla vista ti porta al controller e l'intero problema con la mancanza di navigazione scompare.
Pete Kirkham,

4
@Alternatex Mi dispiace ma non vedo come un controller sia "back-end". È strettamente accoppiato alle sue viste. La vista non va bene senza un controller, il controller non serve senza la vista. Un giorno vorrai eliminarli insieme. Questo per me è il miglior test di ciò che appartiene insieme in una cartella ?? A meno che qualcuno non possa mostrarmi un modo migliore?
bbsimonbb,

2
Le viste sono a livello di presentazione. I controller sono livelli che contengono servizi, che possono contenere oggetti del tuo dominio, che contengono la tua logica aziendale, che pertanto contiene la logica di back-end della tua applicazione. Le viste consistono solo in banali condizionali e semplici loop per l'iterazione sulle raccolte, se le tue viste contengono qualcos'altro, stai sbagliando. Come con la struttura regolare, hai separato il back-end e il front-end, che per me è una struttura migliore di quella che stai suggerendo.
Andy,

10
Quindi non mancano le persone a dirmi che un controller è stoviglie, quindi va nell'armadio delle stoviglie. I panorami sono bicchieri, quindi vanno nell'armadio di vetro. Io so che un controller è stoviglie, ma sto proponendo che sarebbe stato bello avere un armadio pranzo e un armadio cena, dal momento che stiamo parlando di cose che solo si abitua a pranzo o a cena.
bbsimonbb,

Risposte:


38

Vorrei dire che è la programmazione di culto del carico , ma ci sono ragioni tecniche per questa struttura. Asp.Net MVC ha preso una convenzione sull'approccio alla configurazione di quasi tutto. Per impostazione predefinita, il motore di visualizzazione Razor cerca nella Viewsdirectory per risolvere quale vista restituire dal controller. Esistono tuttavia alcuni hack per ottenere una struttura di progetto diversa e Microsoft fornisce persino una funzionalità MVC chiamata Aree per consentirci di creare una struttura di progetto più sana. È inoltre possibile implementare il proprio motore di visualizzazione per specificare dove cercare le visualizzazioni.

Perché dico che è una programmazione di culto del carico e che hai ragione su questo? Lo zio Bob mi ha convinto che la struttura delle directory del progetto non dovrebbe dirmi che si tratta di un'applicazione MVC. Dovrebbe dirmi che si tratta di una facciata del negozio, o di un sistema di richiesta di tempo libero o altro. La struttura e l'architettura di alto livello dovrebbero dirci cos'è questa cosa, non come è stata implementata.

In breve, credo che tu abbia ragione su questo, ma qualsiasi altra struttura di directory dovrebbe semplicemente combattere contro il framework e fidati di me quando dico che non vuoi provare a far fare al framework MVC Asp.Net qualcosa che non era non è progettato per fare. È un peccato che in realtà non sia più configurabile.


Per rispondere rapidamente alle problematiche dell'architettura, credo ancora che i modelli di business (business, non view) e DAL dovrebbero vivere in un progetto / libreria separato che viene chiamato dalla tua app MVC.

È solo che il controller è davvero strettamente associato alla vista e probabilmente può essere modificato insieme. Siamo tutti saggi a ricordare la differenza tra accoppiamento tramite dipendenza e accoppiamento logico. Solo perché il codice ha avuto le sue dipendenze disaccoppiate non lo rende meno logicamente accoppiato.


1
Il modo completo per controllare dove il rasoio cerca le viste è qui . Potrei perseverare.
bbsimonbb,

3
Ho visto lo zio bob, a x1.25 come suggerito. Mi viene da pensare che se gli architetti IT costruissero edifici, vivremmo tutti su piccoli gruppi di zattere legati insieme, galleggiando su un lago. La vita non sarebbe necessariamente più semplice.
bbsimonbb,

1
È un po 'più complicato. Per individuare realmente controller e viste, è necessario risolvere il percorso di visualizzazione in fase di esecuzione, per includere lo spazio dei nomi del controller. Ecco come farlo .
bbsimonbb,

1
Dai un'occhiata anche allo sviluppo di software orientato alle funzionalità ( fosd.net ), per la controparte accademica di ciò che lo zio Bob sta descrivendo.
ngm,

1
La legge di Conway al lavoro. Sono sicuro che funziona presso la tua azienda @Flater. Il layout MVC standard funziona in molte aziende, ma preferisco ancora raggruppare le cose in base alla semantica piuttosto che alla sintassi. Le aziende per cui lavoro sono state organizzate attorno a prodotti anziché a ruoli / funzioni lavorative. Credo che questa sia la radice delle mie preferenze qui.
RubberDuck,

9

Qualunque sia la ragione, questa è una cattiva pratica. È molto anti-OO perché i pacchetti o le cartelle (qualunque cosa tu voglia chiamarli), dovrebbero avere deboli interdipendenze. Le classi (o file) al loro interno dovrebbero avere forti interdipendenze.

Lanciando tutte le viste in una cartella e tutti i controller in un'altra cartella, si creano due pacchetti con un accoppiamento molto stretto. Ciò è contrario al principio di avere deboli dipendenze tra pacchetti.

Una vista e un controller sono le due metà di un tutto e dovrebbero appartenere l'una all'altra. Non avresti un disegno dell'armadio per le calze sul lato sinistro e un altro disegno per le calze sul lato destro.


6

Per rispondere al tuo "Perché tutti ...?" domanda: ecco alcuni potenziali motivi, anche se non sono del tutto sicuro di quale combinazione di essi sia una vera causa, dal momento che in realtà è una domanda soggettiva

  • Per replicare l'architettura logica (modello, vista, controller) con una cartella e una struttura dello spazio dei nomi corrispondenti

  • Per convenzione e convenienza seguire il modello di progetto ASP.net MVC

  • Per raggruppare per spazio dei nomi, poiché la Controllers/cartella porterà a uno .Controllersspazio dei nomi

  • Potrebbe abilitare alcuni scenari in DI / IoC in cui le classi di controller vengono interrogate / scansionate solo da uno spazio dei nomi che contiene / termina con "Controller" (questo potrebbe essere sbagliato)

  • Consentire la scansione dei modelli T4 e l'impalcatura di modelli e controller per generare viste

Puoi sempre creare e seguire la tua convenzione se ha senso per il tuo progetto, nessuno può / ti fermerà. Ma ricorda che se lavori in un grande progetto e / o in un grande gruppo, allora la convenzione di default che tutti conoscono potrebbe essere una scelta migliore (non necessariamente quella giusta, però!)

Se la tua convention è più facile da seguire e non ostacola la produttività, allora fallo! e magari scriverne anche un post sul blog per socializzare con la comunità degli sviluppatori e ottenere feedback


2

Un motivo per mantenere visualizzazioni e controller in directory separate è quando gli sviluppatori front-end e back-end lavorano su un progetto. È possibile impedire agli sviluppatori front-end di accedere al codice back-end (ad es. Per aiutare con la conformità PCI, limitando chi ha accesso al codice sensibile).

Un altro motivo è rendere più semplice avere "temi" e cambiare tutti i modelli apportando una piccola modifica al percorso della vista.

Un terzo motivo è avere un modello di directory semplice quando si specificano le viste nel framework MVC. È più facile specificare la sottodirectory e il file piuttosto che un grande percorso lungo per ogni vista.

L'unico "accoppiamento stretto" dovrebbe essere:

  1. Variabili inviate nella vista dal controller.
  2. Campi modulo o azioni nella vista, rispediti al controller.

Uso un controller generico e provo a mantenere generici i nomi delle variabili nella vista, in modo che molte viste possano usare lo stesso controller e molti controller possano usare la stessa vista. Per questo motivo preferisco mantenere le viste completamente separate. Il modello è il punto in cui è possibile differenziare ogni "cosa" nella propria applicazione: possono essere oggetti con un elenco di proprietà e metodi per accedere / modificare queste proprietà.

Per un codice strettamente accoppiato, un approccio che potrebbe funzionare per te è quello di tenere tutti i file che fanno parte di un pacchetto o "modulo" insieme in una directory spaziale. Quindi è possibile utilizzare uno script per copiare o "compilare" i modelli non elaborati nella directory principale "viste". Per esempio:


    lib/my-namespace/my-package/
        -> controllers/
        -> models/
        -> views/
            -> theme/
               -> template-name1
    app/compiled_views/theme/
        -> url/path/template-name1

Sfortunatamente, se vuoi cambiare la struttura di un tema esistente, c'è più intreccio tra le directory dei pacchetti per aggiornare le viste.

Considera che le viste sono solo un modo per formattare i dati, siano essi json, xml, csv o html. Ciò è particolarmente utile se si desidera che l'applicazione funzioni anche come API. Prova a disaccoppiare la vista dai dati, utilizzando nomi di variabili generici, in modo da poter utilizzare lo stesso modello per molti controller o modelli (o utilizzare include per ridurre al minimo la quantità di codice che devi conservare).


1

Non necessariamente tutti lo fanno. Ad esempio, il framework Django di Python ha il concetto di un'app, in cui i sottomoduli dell'applicazione vivono nelle proprie directory con i propri modelli, viste e modelli (le viste sono essenzialmente ciò che Django chiama controller). Mi capita di preferire quel modo di fare le cose perché ciò significa che posso facilmente impacchettare un'app e riutilizzarla in tutti i progetti semplicemente includendola nell'elenco delle app nelle impostazioni dei miei progetti. È anche più facile scoprire dove sono le diverse parti. Se guardo il file urls.py e vedo qualcosa del genere url(r'^users/', include('my_site.users.urls')), so che il modulo my_site.userscontiene tutto il codice che gestisce gli utenti. Conosco i moduli my_site.users.viewse my_site.users.modelsquando voglio vedere come vengono creati e autenticati gli utenti. So che tutti i miei percorsi sono definiti in my_site.users.url.

Inoltre, se è abbastanza generico, posso probabilmente usare quel modulo in altri siti semplicemente cambiando la configurazione o impacchettandolo come libreria e pubblicandolo come OSS.


1

Ricorda che è il modo consigliato da Microsoft per mantenere i controller e le visualizzazioni in cartelle diverse, quindi molti seguiranno la struttura consigliata,

  1. Un motivo potrebbe essere che i controller non hanno sempre una relazione uno a uno con le viste, in particolare le viste parziali possono essere condivise tra i controller.
  2. Un altro motivo potrebbe essere quando il tuo progetto cresce, potresti voler estrarre controller e unit test in un altro (i) progetto (i), ma è abbastanza difficile fare lo stesso per viste più viste / js / css che si uniscono mentre si riferiscono.

Detto questo, ci sono molti post su come farlo a modo tuo, come questo .


"è il modo consigliato da Microsoft" ... Puoi chiarire cosa intendi con quello? Esiste un vero e autorevole articolo MS su questo? Oppure è solo l'impostazione predefinita del progetto per un'app MVC? E, se stai basando questo su quest'ultimo, non è possibile che l'impostazione predefinita del progetto MVC sia quella che è perché è come "tutti" lo fanno ??
svidgen,

1
Sulla base dell'articolo msdn.microsoft.com/en-us/library/… dice "Controller, che è raccomandato" e così via per le visualizzazioni, ecc.
Low Flying Pelican

0

Per il record

Perché dico che è una programmazione di culto del carico e che hai ragione su questo? Lo zio Bob mi ha convinto che la struttura delle directory del progetto non dovrebbe dirmi che si tratta di un'applicazione MVC. Dovrebbe dirmi che si tratta di una facciata del negozio, o di un sistema di richiesta di tempo libero, o altro. La struttura e l'architettura di alto livello dovrebbero dirci cos'è questa cosa, non come è stata implementata.

Domanda: chi ha accesso al codice? I programmatori. Gli utenti finali si preoccupano del codice ?. No. E, cosa fa un programmatore, codifica. O più specificamente, classi basate sui tipi (controller, servizio, modello e così via). Quindi ha senso ed è facile eseguire il debug di un codice, se si è in grado di trovare un codice basato sul tipo di codice, anziché sul comportamento del codice. Inoltre, diciamo un progetto di squadra, uno è responsabile del controller, un altro del modello, un altro del dao e un altro della vista. È facile separare il progetto in parti. Un buon codice è un codice di cui è facile eseguire il debug, non un codice zucchero di sintassi. Lo zio Bob ha di nuovo torto.

Cercare di imitare il comportamento del progetto (una facciata del negozio) è un culto del carico.


3
Per quale codice mi occupo di più delle funzionalità, non dei tipi. Quando vedo una funzione che non funziona come previsto, so che qualcosa non va nel codice relativo a quella funzione mentre non so necessariamente quale tipo di codice sia.
Smetti di fare del male a Monica il

1
"Diciamo che un progetto di squadra, uno è responsabile del controller, un altro il modello, un altro il dao" Tale squadra avrà difficoltà a spedire qualsiasi cosa e quando lo farà avrà un costo molto maggiore in termini di costi generali di comunicazione e bug.
RubberDuck,

Come stabilito in una catena di commenti nella risposta accettata, hai un punto, ma solo in alcuni casi. Quando un'azienda si concentra su progetti MVC che vende a molti clienti diversi, mantenere una struttura MVC ha senso per la riusabilità. Quando un'azienda si concentra su una nicchia (ad esempio negozi online) e probabilmente utilizza molte tecnologie diverse, ha più senso avere una struttura orientata al negozio online. Questa è un'applicazione pratica della Legge di Conway . Il codice (e quindi anche la struttura del progetto) dovrebbe seguire la struttura dell'azienda.
Flater,

@RubberDuck: in ogni caso è possibile presentare un argomento per un costo aggiuntivo. Hai ragione quando persone diverse fanno componenti tecnici diversi, che hai aumentato la comunicazione della logica di business. Tuttavia, se si dispone di persone diverse che implementano appieno funzionalità diverse, è possibile che si verifichino costi aggiuntivi per assicurarsi che tutti siano a bordo (esperti + d'accordo) con lo stesso approccio tecnico. In entrambi i casi, è necessario un sovraccarico di comunicazione per assicurarsi che le persone lavorino insieme.
Flater,

Sì, i handoffs costano sempre di più che avere una sola coppia di sviluppatori che implementano un IME end-to-end.
RubberDuck,
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.