La logica di ordinamento deve essere posizionata nel modello, nella vista o nel controller? [chiuso]


157

Ho un elenco a discesa che mostra i valori da una tabella all'utente finale. Vorrei che questi valori fossero ordinati alfabeticamente.

Secondo il corretto design MVC, a quale livello devo posizionare la mia logica di ordinamento: il modello, la vista o il controller?

EDIT : in risposta alla domanda di LarsH, "Intendi il codice che determina quale ordinamento è desiderato? O il codice che esegue l'ordinamento?", Mi riferivo originariamente al codice che determina quale ordinamento è desiderato.


6
Al fine di risolvere il disaccordo nei commenti, sarebbe utile dire cosa intendi per "logica di ordinamento". Intendi il codice che determina quale ordinamento è desiderato? o codice che esegue l'ordinamento?
LarsH

9
Il design MVC non è niente di speciale o magico - è davvero solo un punto di partenza. adattalo alle tue esigenze e ricorda che puoi rifattorizzare in qualsiasi momento. Ho notato che diversi fornitori ridefiniranno ciò che entra nel controller o visualizzeranno in base alle esigenze del loro toolkit, quindi è difficile trovare un accordo. L'importante è separare il tuo modello dal tuo View / Controller. Potresti anche ottenere più chilometri dal modello MVP, credo che sia un po 'più specifico in questa area.
Bill K,

9
Forse questo dovrebbe essere migrato ai programmatori.
Alfredo Osorio,

57
Sicuramente nel controller. Quello o il modello. O la vista.
mob

2
Sicuramente mai, mai, mai, mai nella vista.
contactmatt

Risposte:


49

(Nota: questa citazione e citazione è presa dalla risposta di @ dasblinkenlight , ma non siamo d'accordo sulla nostra interpretazione di esso. Leggi il suo post e decidi ).

Secondo la descrizione MVC ,

Un controller può inviare comandi alla vista associata per modificare la presentazione della vista del modello (ad esempio, scorrendo un documento). Può inviare comandi al modello per aggiornare lo stato del modello (es. Modifica di un documento).

La logica di ordinamento (ad es. Il comparatore di ordinamento / algoritmo di ordinamento) appartiene al modello poiché contiene regole aziendali e dati sullo stato. Poiché la modifica del modo in cui i dati del modello vengono ordinati rientra esattamente nella categoria "modifica la presentazione del modello della vista", il controller è responsabile di "eseguire l'ordinamento" chiamando il metodo model.changeSortedState ().


8
Cosa succede se gli stessi dati devono essere visualizzati in due viste diverse, ordinate in modo diverso?
s4y,

Ciò dovrebbe essere fatto allo stesso modo, model.SortAscending () e model.SortDescending () e chiamato dal controller.
Brij,

1
@Brij Nel MVC corretto, due viste non possono condividere lo stesso modello?
KOVIKO,

@Sidnicious Se ha senso disporre di un metodo di ordinamento che accetta un parametro diverso. Ad esempio public void Sort(bool sortByDescending = false), dove se falso ordina in ordine crescente. O hai solo due diversi metodi di ordinamento se la logica è molto diversa.
MattMcGowan,

@Sidnicious ha due modelli diversi che delegano tutto tranne la logica di ordinamento a un solo terzo modello. docs.google.com/drawings/d/…
rightfold

62

Chi controlla l'ordinamento?

Diagramma MVC semplice(Da Wikipedia )

1) Ordine naturale all'interno dei dati stessi:

L'ordine fa parte del modello, quindi dovrebbe andare lì. Un pull grezzo di "tutti i dati" restituirebbe i dati nell'ordine ordinato e non esiste un'interfaccia per scegliere l'ordinamento.

2) L'utente dovrebbe controllare il modo in cui vede i dati:

La vista fornirebbe un'interfaccia (come frecce ascendenti / discendenti) che interagiscono con il controller e il modello comprende i dati abbastanza bene da eseguire l'ordinamento richiesto sui dati. Tuttavia, un pull grezzo dei dati non deve necessariamente essere ordinato, a differenza di (1).

In ogni caso,

La vista non capisce che c'è un ordinamento in corso, altro che la possibilità di mostrare quale direzione di ordinamento è stata scelta. Non mettere lì la logica.

Piccolo avvertimento

La funzionalità di ordinamento potrebbe andare puramente nella vista, in una circostanza (che posso pensare di sbrigativo; potrebbe essercene di più):

Un ordinamento "stupido" in cui tutti i dati sono già nella vista e non è necessario utilizzare alcuna conoscenza del dominio per eseguire l'ordinamento. Confronto di stringhe o numeri molto semplice, per esempio. Ciò non è possibile, ad esempio, nei risultati di ricerca su una pagina Web quando è probabile che i risultati vengano suddivisi su più pagine.


59
La vista può vedere l'utente !?
Farzher,

41
Il modello aggiorna la vista !?
Inganno

13
Quell'articolo di Wikipedia fa schifo: la sezione "Interazione componente" è in conflitto con il diagramma mostrato a destra (che hai appena pubblicato qui). In secondo luogo, il modello non "aggiorna" la vista. NOTIFICA la vista quando c'è stato un cambio di stato. La vista decide come aggiornare. Ugh. Ti chiedi perché ci sono 1000 risposte diverse a questa domanda quando ci sono così tante informazioni poco chiare che fluttuano intorno.
KyleM,

4
@cHao Certo. Siamo d'accordo sul fatto che il grafico di Wikipedia sia piuttosto strano, giusto? :)
ingannare

6
@StephenSarcsamKamenar e tutti gli altri: No, l'immagine ha perfettamente senso: mostra il flusso di dati , non le connessioni del codice.
Izkata,

18

Secondo la descrizione MVC ,

Un controller può inviare comandi alla vista associata per modificare la presentazione della vista del modello (ad esempio, scorrendo un documento). Può inviare comandi al modello per aggiornare lo stato del modello (es. Modifica di un documento).

In base a ciò, la logica di ordinamento appartiene al controller, poiché l'alterazione del modo in cui i dati del modello sono ordinati rientra direttamente nella categoria "modifica la presentazione del modello" della vista.

EDIT: per chiarire molteplici malintesi espressi nei commenti, la "logica di ordinamento" non è il codice che esegue l'ordinamento; è il codice che definisce l'ordinamento. La logica di ordinamento confronta i singoli elementi tra loro per stabilire un ordine (ad esempio attraverso un'istanza di IComparator<T>) o contiene una logica che costruisce un oggetto da utilizzare per l'ordinamento da un sistema esterno (ad esempio attraverso un'istanza di IOrderedQueryable<T>). Questa logica appartiene al controller, poiché necessita di conoscenze relative al lato "aziendale" dell'applicazione. È del tutto sufficiente eseguire l'ordinamento, ma è separato dal codice effettivamente eseguitoesso. Il codice che ordina può essere nella tua vista, nel tuo modello o persino nel livello di persistenza che supporta il tuo modello (ad esempio il tuo database SQL).


12
-1 Come sei riuscito a concludere questo da quella citazione? È stato detto da qualche parte che il controller dovrebbe recuperare informazioni dal modello? Il controller invia comandi per modificare lo stato. Non si dice nulla sull'estrazione o la manipolazione delle informazioni.
tereško,

3
@ tereško Come sei riuscito a concludere dalla mia risposta che il controller ha bisogno di recuperare informazioni dal modello? Per "logica di ordinamento" intendo solo la logica necessaria per stabilire un ordinamento - in termini di C #, che fornisce un'implementazione di IComparer<T>. Le restanti "meccaniche della caldaia" dell'ordinamento, compreso il recupero dei dati dal modello, sono all'altezza della vista.
dasblinkenlight,

3
".. la logica di ordinamento appartiene al controller .." , che altro significa?
tereško,

3
"Un controller può inviare comandi alla vista associata per modificare la presentazione della vista" suona davvero come se la vista eseguisse l'ordinamento, in risposta al comando del controller.
Samuel Edwin Ward,

1
@KyleM Ma la vista non ha sempre una conoscenza sufficiente per contenere la logica di ordinamento. Ad esempio, si consideri un campo che ha un codice numerico corrispondente a uno degli enum {Unknown, Pass, Fail}. Supponi inoltre che Unknowndebba sempre ordinare per ultimo, indipendentemente dall'ordine crescente o decrescente che l'utente ha scelto. Se si posiziona questa logica nella vista, si direbbe troppo alla vista sulla natura aziendale dei dati all'interno del codecampo. La vista non dovrebbe saperlo: tutto ciò che sa è che l'utente ha eseguito un gesto di "ordinamento" (ad esempio facendo clic su un'intestazione); il resto spetta al controller.
dasblinkenlight,

10

Nessuno dei precedenti. L'ordinamento è una logica aziendale e la logica aziendale non appartiene a nessuno dei tre. Non tutte le parti di codice nella tua applicazione saranno un modello, una vista o un controller.

Quello che faccio generalmente nelle mie app MVC è che ho un livello di servizio che esegue tutta la logica aziendale. I metodi nel livello di servizio dovrebbero avere un'API pulita e semplice con parametri ben definiti. È quindi possibile richiamare tali metodi dal proprio controller per manipolare i dati nei modelli.

In tal senso, l'ordinamento è "nel controller", ma il codice stesso che esegue l'ordinamento non deve essere implementato nel controller, ma solo invocato da lì.


5
Sono stato recentemente informato che alcune persone considerano un "livello di servizio" (logica aziendale) parte del modello.
Marvo

@Marvo Penso che ci siano alcuni casi in cui alcuni pezzi di logica sono così intimamente legati al loro tipo di dati che ha senso incapsularli insieme in una classe. (ad esempio funzioni di data e ora). In generale, tuttavia, trovo che funzioni meglio quando gli oggetti modello non fanno altro che conservare i dati.
nont

Quindi, dove la "logica aziendale" "vive" nel modello MVC?
Marvo,

2
Solo perché un'applicazione utilizza un modello MVC, non significa che ogni parte di codice nell'applicazione sarà un modello, una vista o un controller. Questo sta prendendo i modelli di design alla lettera. Ad esempio, l'applicazione probabilmente ha un file di configurazione di qualche tipo. Quel file di configurazione non sta modellando i dati dell'utente, né presentando le viste, né controllando il flusso di dati attraverso i modelli verso le viste. È un file di configurazione, che è il suo genere di cose.
nont

Si potrebbe facilmente considerare un file di configurazione parte del modello. Il modello non deve essere un database. Non sto dicendo che hai ragione o torto. Sto solo suggerendo che tu, come ho fatto di recente (perché ho avuto la stessa opinione che hai), apri un po 'l'argomento e vedi cosa dicono gli altri.
Marvo,

8

Sicuramente non il controller: invia messaggi da visualizzare e modellare ma dovrebbe fare il minor lavoro possibile. Se l'utente può modificare l'ordinamento, la richiesta viene gestita dal controller informando il modello o la vista al riguardo.

Forse il View se è una cosa View pura. Se l'applicazione funziona altrettanto bene senza l'ordinamento, allora l'ordinamento è solo una parte della rappresentazione e dovrebbe andare nella vista.

Se l'ordinamento è parte integrante del dominio, dovrebbe andare nel modello.


"Fornire un comparatore o un descrittore di ordinamento" conta come "fare lavoro"? Poiché una logica di ordinamento è incapsulata in un comparatore o in un descrittore di ordinamento, anche se il "lavoro di ordinamento" viene eseguito nel metodo di ordinamento o nel back-end del modello.
dasblinkenlight,

Dipende da cosa intendi fornendo: passare è ok. Ma il comparatore dovrebbe far parte del modello o della vista, non del controller.
Jens Schauder,

6
  • Le viste sono la parte di MVC che dovrebbe contenere la logica di presentazione.
  • Il livello del modello è dove è contenuta la logica aziendale.
  • I controller cambiano solo lo stato di entrambi, in base all'input dell'utente.

Quindi la scelta è: pensi che questo sia parte della logica aziendale del dominio o della logica di presentazione.

Se steste implementando un modello MVC o un modello MVC classico corretto, direi che l'ordinamento dei dati forniti dal livello del modello dovrebbe essere attivato dalla richiesta della vista al livello del modello. La vista richiede i dati ordinati, il livello del modello fornisce.

Ma poiché stai usando l'interpretazione di ASP.NET MVC del modello MVC, che è un po 'diversa rispetto al tuo MVC standard - l'istanza di ViewModel dovrebbe richiedere informazioni ordinate dal livello del modello (per qualche ragione il framework ASP.NET pensa che i modelli debbano essere chiamati "viste" e le viste dovrebbero essere chiamate "modelli" ... è strano).


12
Hai continuato a effettuare il downvoting di risposte multiple applicando il tuo presupposto su ciò che significano per "logica di ordinamento". La tua ipotesi è assolutamente errata: la logica di ordinamento non include e non ha mai incluso il recupero.
dasblinkenlight,

1
@dasblinkenlight, sì, ho declassato più argomenti perché tutti hanno implicato che il controller dovrebbe eseguire l'ordinamento. Quale è sbagliato. E .. persone .. per favore, smettete di segnalare i miei commenti solo perché non siete d'accordo.
Tereško,

Giusto per essere chiari: non ho votato in negativo la tua risposta perché non è errata, e non ho mai segnalato alcun tuo commento, perché non trovo che sia in alcun modo offensivo. Onestamente, non so come la tua risposta sia riuscita a ottenere così tanti voti negativi: penso che siano mal concepiti.
dasblinkenlight,

@dasblinkenlight naah .. stavo imperversando per i miei commenti che in questo argomento sono svaniti.
tereško,

5

Di solito lo farei nel controller per rimanere in linea con lo schema secondo le altre risposte. Vedi sotto per il ragionamento.

Ho riflettuto su questo e letto le risposte e il materiale correlato e parlando pragmaticamente direi che dipenderà dalla tua applicazione, ad esempio:

È un'applicazione medio / grande e / o ha più UI associate (ad esempio un'app di Windows, un'interfaccia Web e un'interfaccia del telefono).

  • In questo caso probabilmente costruirò un livello di servizio e lo inserirei nell'oggetto business e quindi chiamerei il metodo appropriato dal controller.

Se si tratta di un sito Web dell'interfaccia utente singola ben definito e stai utilizzando qualcosa come EF Code First e non hai o non hai intenzione di creare un livello di servizio e pianifichi di utilizzare un semplice metodo di estensione pronto all'uso per ottenerlo:

  • In questo caso, probabilmente l'avrei inserito nel controller in quanto pragmaticamente è la soluzione migliore in termini di tempo / budget.

Se è uguale al precedente MA NON può essere implementato con un metodo di estensione predefinito.

  • Potrei anche scegliere di inserirlo nella classe Model (se è veramente su misura per quel singolo tipo) in quanto sarebbe più appropriato qui che in un controller. Se l'ordinamento potesse essere applicato a più di una classe, lo implementerei in un metodo di estensione e lo chiamerei nel controller.

Per riassumere:

Risposta dogmatica: livello di servizio

Risposta pragmatica: di solito il controller


In quale responsabile della definizione è responsabile della "preparazione dei dati per la visualizzazione"?
tereško,

1
@ tereško: dove il modello è "passivo" come descritto qui msdn.microsoft.com/en-us/library/ff649643.aspx nella sezione varianti. Vedi "HTTP ne è un esempio". Mentre un purista può contestarlo, può essere più facile per i principianti iniziare a MVC, dove potrebbero usare EF o altri modelli direttamente nel controller e non attraverso un BAL per pensarlo in questo modo abbassando la barriera per comprendere ulteriormente il modello.
Luke Baughan,

1
di cosa stai parlando è "modello anemico".
tereško,

Punto notato, ho rimosso le descrizioni offensive come mi hai suggerito. Saluti per l'input!
Luke Baughan,

3

Vorrei suggerire l'ordinamento dei dati da una tabella-dati che è abbastanza piccolo da essere utile in un elenco a discesa-dovrebbe provenire dal DB già ordinato tramite la query. Per me, questo rende il modello il posto in cui viene applicato l'ordinamento.

Se sei determinato a fare l'ordinamento a mano, penso che ci siano buoni argomenti per usare il modello o il controller come punto preferito per la logica. La limitazione sarebbe il tuo quadro particolare. Preferisco gestire i dati esclusivamente nel modello. Uso il controller per sposare dati (modello) e presentazione (vista) come mi è stato (auto) insegnato.


2

Sebbene io sia d'accordo in linea di principio con l'idea che l'ordinamento sia una logica di business perché suddividendola alla sua origine si finirà con qualcosa del tipo "Il cliente vorrebbe che la pagina del prodotto fosse visualizzata con le immagini ordinate per data", quindi diventa chiaro che l'ordinamento per i dati non è in genere arbitrario, anche se non esiste un ordinamento in quanto si tratta ancora di una decisione commerciale per omissione (un elenco vuoto è ancora un elenco).

MA ... Queste risposte non sembrano prendere in considerazione i progressi della tecnologia ORM, posso solo parlare in relazione al Entity Framework (evitiamo un argomento sul fatto che questo sia vero ORM, non è questo il punto) di Microsoft come è quello che uso, ma sono sicuro che altri ORM offrono funzionalità simili.

Se creo una vista fortemente tipizzata per una classe di prodotto utilizzando MS MVC e Entity Framework e esiste una relazione di chiave esterna tra la tabella Product e Image (ad es. FK_Product_Image_ProductId), sarei immediatamente in grado di ordinare rapidamente le immagini durante la loro visualizzazione usando qualcosa di simile nella vista:

@foreach(Image i in Model.Image.OrderBy(e => e.DisplayOrder)){ //etc etc... }

È stato menzionato uno specifico livello di Business Logic, che utilizzo anche per eseguire l'80% della mia logica di business, ma non scriverò funzionalità di ordinamento nel mio livello di Business Logic che imita qualcosa che è pronto all'uso dal Entity Framework.

Non credo che ci sia una risposta corretta a questa domanda, oltre a dirlo; dovresti astrarre complesse logiche aziendali ove possibile ma non a costo di reinventare la ruota.


Stavo pensando la stessa cosa, le risposte qui non sembrano prendere in considerazione gli ORM e i metodi di estensione. Nella maggior parte dei casi, la logica di ordinamento sarà semplice come myList.OrderBy(x => x.CreationDate): non è necessario introdurre alcun livello aggiuntivo non necessario solo per fare ciò. Per aggiungere a ciò, cosa farebbero se avessero bisogno di dati paginati e ordinati? Interroga l'intero tavolo, ordinalo e mantieni ciò di cui hanno bisogno? Si potrebbe semplicemente chiamare myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)e non vengono recuperati dati non necessari.
Balázs,

1

Supponiamo di avere un sito Web MVC, un sito Web WebForms e un'applicazione mobile.

Se vuoi che l'ordinamento sia coerente tra questi livelli di presentazione, direi l'ordinamento al di fuori del livello di presentazione. Il servizio sarebbe un buon candidato.

Altrimenti, memorizzerei quella logica in un modello di vista. Perché? Perché sarà riutilizzabile e facilmente testabile.


0

Dei tre che hai elencato, direi che appartiene al controller. Tuttavia, non mi piace molto inserire questo tipo di logica nel controller. Di solito creo un livello di servizio con cui comunica il controller che sarà responsabile della comunicazione con l'archivio dati e della gestione della logica di ordinamento. Per applicazioni di piccole dimensioni, tuttavia, è possibile utilizzare il controller.


2
Ciò metterebbe la logica più sul lato del modello, giusto?
Ryan Kohn,

Sì, la mia comprensione di un "livello di servizio" è che fa parte del modello.
Marvo

0

Questa è una domanda posta con asp.net in mente, ma dato che qualcuno ha menzionato Rails, ho pensato che sarebbe stato interessante considerare il problema in quel contesto. In Rails, è naturale e abbastanza comune eseguire l'ordinamento insieme al recupero come azione del controller, poiché il framework e ActiveRecord / ActiveQuery api lo prevedono. D'altra parte, è possibile definire una sorta di ordinamento personalizzato per gli elementi statici e inserirlo nel modello per essere utilizzato dal controller, in modo che il modello possa svolgere un ruolo nella logica di ordinamento anche se non esegue l'operazione direttamente. Qualunque cosa sia, si può dire con certezza che mettere la logica di ordinamento nella vista è generalmente malvisto.

Sono un po 'divertito dal fatto che alcune risposte siano assolutamente contrarie a mettere l'ordinamento nel controller o nel modello, e li trovo troppo pedanti per i miei gusti, ma suppongo che dipenda dalla natura del framework utilizzato e dalle convenzioni convenzionali associate esso. Concordo anche con il commento di Bill K secondo cui la separazione in primo luogo è più importante.

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.