Czy logikę sortowania należy umieścić w modelu, widoku czy w kontrolerze? [Zamknięte]

157

Mam listę rozwijaną, która wyświetla wartości z tabeli do użytkownika końcowego. Chciałbym, aby te wartości były sortowane alfabetycznie.

Zgodnie z odpowiednim projektem MVC, na jakiej warstwie powinienem umieścić logikę sortowania: model, widok czy kontroler?

EDYCJA : W odpowiedzi na pytanie LarsH'a „Czy masz na myśli kod, który określa, jaki porządek sortowania jest wymagany? Czy kod wykonujący sortowanie?”, Odnosiłem się pierwotnie do kodu, który określa, jaki porządek sortowania jest pożądany.

Ryan Kohn
źródło
6
W celu rozwiązania sporu w komentarzach pomocne byłoby, gdybyś powiedział, co masz na myśli, mówiąc o „logice sortowania”. Czy masz na myśli kod, który określa, jaki porządek sortowania jest pożądany? lub kod, który wykonuje sortowanie?
LarsH
9
Projekt MVC nie jest niczym specjalnym ani magicznym - to tak naprawdę tylko punkt wyjścia. dostosuj go do swoich potrzeb i pamiętaj, że w każdej chwili możesz dokonać jego naprawy. Zauważyłem, że różni dostawcy na nowo określają, co trafia do kontrolera lub widoku na podstawie potrzeb ich zestawu narzędzi, więc trudno jest znaleźć jakąkolwiek zgodę. Ważne jest, aby oddzielić swój model od widoku / kontrolera. Możesz również uzyskać większy przebieg ze wzoru MVP, myślę, że jest trochę bardziej szczegółowy w tym obszarze.
Bill K,
9
Może to powinno zostać przeniesione do programistów.
Alfredo Osorio
57
Zdecydowanie w kontrolerze. Albo to, albo model. Albo widok.
mafia
2
Zdecydowanie nigdy, nigdy, przenigdy w zasięgu wzroku.
contactmatt

Odpowiedzi:

49

(Uwaga: ten cytat i cytat pochodzą z odpowiedzi @ dasblinkenlight , ale nie zgadzamy się z naszą interpretacją. Przeczytaj jego post i zdecyduj samodzielnie).

Zgodnie z opisem MVC ,

Kontroler może wysyłać polecenia do skojarzonego z nim widoku, aby zmienić prezentację widoku modelu (na przykład przewijając dokument). Może wysyłać polecenia do modelu, aby zaktualizować stan modelu (np. Edycja dokumentu).

Logika sortowania (np. Komparator sortowania / algorytm sortowania) należy do modelu, ponieważ zawiera reguły biznesowe i dane o stanie. Ponieważ zmiana sposobu sortowania danych modelu należy do kategorii „zmień prezentację widoku modelu”, kontroler jest odpowiedzialny za „sortowanie” przez wywołanie metody model.changeSortedState ().

KyleM
źródło
8
A co, jeśli te same dane mają być wyświetlane w dwóch różnych widokach, inaczej posortowanych?
s4y
Należy to również zrobić w ten sam sposób, model.SortAscending () i model.SortDescending () i wywołać przez kontroler.
Brij
1
@Brij Czy we właściwym MVC dwa widoki nie mogą mieć tego samego modelu?
KOVIKO
@Sidnicious Jeśli ma sens mieć jedną metodę sortowania, która przyjmuje inny parametr. Np. public void Sort(bool sortByDescending = false)Jeśli fałsz sortuje rosnąco. Lub po prostu użyj dwóch różnych metod sortowania, jeśli logika jest bardzo różna.
MattMcGowan
@Sidnicious ma dwa różne modele, które delegują wszystko oprócz logiki sortowania do jednej trzeciej modelu. docs.google.com/drawings/d/…
rightfold
62

Kto kontroluje porządek sortowania?

Prosty diagram MVC(Z Wikipedii )

1) Naturalny porządek w samych danych:

Zamówienie jest częścią Modelu, więc powinno tam trafić. Surowe pobranie „wszystkich danych” zwróciłoby dane w kolejności posortowanej i nie ma interfejsu do wybierania kolejności sortowania.

2) Użytkownik powinien kontrolować sposób, w jaki widzi dane:

Widok zapewniłby interfejs (taki jak strzałki w górę / w dół), który współdziała z kontrolerem, a Model rozumie dane wystarczająco dobrze, aby wykonać żądane sortowanie danych. Jednak surowe pobieranie danych niekoniecznie musi być sortowane, w przeciwieństwie do (1).

W obu przypadkach,

Widok nie rozumie, że istnieje jakiś rodzaj, poza możliwością pokazania, który kierunek sortowania został wybrany. Nie umieszczaj tam logiki.

Małe zastrzeżenie

Funkcjonalność sortowania może działać wyłącznie w Widoku, w jednym przypadku (o którym myślę od ręki; może być więcej):

Sortowanie „głupie”, w którym wszystkie dane są już widoczne i nie musi wykorzystywać żadnej wiedzy o domenie do sortowania. Na przykład bardzo proste porównanie ciągów lub liczb. Nie jest to możliwe na przykład w wynikach wyszukiwania na stronie internetowej, gdy wyniki mogą być podzielone na wiele stron.

Izkata
źródło
58
Widok może zobaczyć użytkownika !?
Farzher
41
Model aktualizuje widok !?
deceze
13
Ten artykuł w Wikipedii jest do niczego: sekcja „Interakcja komponentów” jest sprzeczna z diagramem po prawej stronie (który właśnie opublikowałeś tutaj). Po drugie, model nie „aktualizuje” widoku. POWIADOMIA widok, gdy nastąpiła zmiana stanu. Widok decyduje o sposobie aktualizacji. Fuj. Zastanawiasz się, dlaczego istnieje 1000 różnych odpowiedzi na to pytanie, skoro wokół krąży tyle niejasnych informacji.
KyleM
4
@cHao Sure. Możemy się zgodzić, że wykres Wikipedii jest dość dziwny, prawda? :)
deceze
6
@StephenSarcsamKamenar i wszyscy inni: Nie, obraz ma sens: pokazuje przepływ danych , a nie połączenia kodu.
Izkata
18

Zgodnie z opisem MVC ,

Kontroler może wysyłać polecenia do skojarzonego z nim widoku, aby zmienić prezentację widoku modelu (na przykład przewijając dokument). Może wysyłać polecenia do modelu, aby zaktualizować stan modelu (np. Edycja dokumentu).

Zgodnie z tym logika sortowania należy do kontrolera, ponieważ zmiana sposobu sortowania danych modelu należy do kategorii „zmień sposób prezentacji modelu w widoku”.

EDYCJA: Aby wyjaśnić liczne nieporozumienia wyrażane w komentarzach, „logika sortowania” nie jest kodem, który wykonuje sortowanie; to kod definiuje sortowanie. Logika sortowania porównuje ze sobą poszczególne pozycje w celu ustalenia kolejności (np. Poprzez instancję IComparator<T>) lub zawiera logikę, która konstruuje obiekt, który ma być używany do porządkowania przez system zewnętrzny (np. Poprzez instancję IOrderedQueryable<T>). Ta logika należy do kontrolera, ponieważ wymaga wiedzy związanej z „biznesową” stroną aplikacji. Sortowanie jest całkowicie wystarczające, ale jest ono niezależne od kodu, który faktycznie wykonujeto. Kod, który sortuje, może znajdować się w Twoim widoku, w Twoim modelu lub nawet w warstwie trwałości, która stanowi kopię zapasową Twojego modelu (np. Twoja baza danych SQL).

dasblinkenlight
źródło
12
-1 Jak udało ci się to wyciągnąć z tego cytatu? Czy było gdzieś powiedziane, że kontroler ma pobierać informacje z modelu? Kontroler wysyła polecenia zmiany stanu. Nic nie mówi się o wydobywaniu lub manipulowaniu informacjami.
tereško
3
@ tereško Jak udało Ci się wywnioskować z mojej odpowiedzi, że kontroler musi pobrać informacje z modelu? Przez „logikę sortowania” rozumiem tylko logikę, która jest niezbędna do ustalenia kolejności - w języku C # jest to implementacja IComparer<T>. Pozostała „standardowa mechanika” sortowania, w tym odzyskiwanie danych z modelu, zależy od poglądu.
dasblinkenlight
3
„… logika sortowania należy do kontrolera…” , co jeszcze to oznacza?
tereško
3
„Kontroler może wysyłać polecenia do skojarzonego z nim widoku, aby zmienić prezentację widoku” w rzeczywistości brzmi tak, jakby widok wykonał sortowanie w odpowiedzi na polecenie ze sterownika.
Samuel Edwin Ward
1
@KyleM Ale widok nie zawsze ma wystarczającą wiedzę, aby zawierać logikę sortowania. Na przykład rozważmy pole, które ma kod numeryczny odpowiadający jednej z wyliczeń {Unknown, Pass, Fail}. Ponadto załóżmy, że Unknownzawsze należy sortować jako ostatnie, niezależnie od kolejności rosnącej lub malejącej, którą wybrał użytkownik. Umieszczenie tej logiki w widoku powiedziałoby zbyt wiele o biznesowym charakterze danych w codepolu. Widok nie powinien tego wiedzieć: wie tylko, że użytkownik wykonał gest „sortowania” (np. Kliknął nagłówek); reszta należy do kontrolera.
dasblinkenlight
10

Żadne z powyższych. Sortowanie jest logiką biznesową, a logika biznesowa nie należy do żadnego z trzech. Nie każdy fragment kodu w Twojej aplikacji będzie modelem, widokiem lub kontrolerem.

To, co zwykle robię w moich aplikacjach MVC, to warstwa usług, która wykonuje całą logikę biznesową. Metody w warstwie usług powinny mieć czyste, proste API z dobrze nazwanymi parametrami. Następnie możesz wywołać te metody ze swojego kontrolera, aby manipulować danymi w modelach.

W tym sensie sortowanie odbywa się „w kontrolerze”, ale sam kod, który wykonuje sortowanie, nie powinien być implementowany w kontrolerze, a jedynie wywoływany stamtąd.

nie
źródło
5
Niedawno zostałem poinformowany, że niektórzy ludzie uważają „warstwę usług” (logikę biznesową) za część modelu.
Marvo
@Marvo Myślę, że są przypadki, w których pewne elementy logiki są tak ściśle powiązane z ich typem danych, że sensowne jest zamknięcie ich razem w jednej klasie. (na przykład funkcje czasu i daty). Ogólnie jednak uważam, że działa najlepiej, gdy obiekty modelu nie robią nic poza przechowywaniem danych.
nie
W takim razie gdzie logika biznesowa „żyje” we wzorcu MVC?
Marvo
2
To, że aplikacja używa wzorca MVC, nie oznacza, że ​​każdy fragment kodu w aplikacji będzie modelem, widokiem lub kontrolerem. To zbyt dosłowne branie wzorców projektowych. Na przykład Twoja aplikacja prawdopodobnie ma jakiś plik konfiguracyjny. Ten plik konfiguracyjny nie służy ani modelowaniu danych użytkownika, ani prezentowaniu widoków, ani kontrolowaniu przepływu danych przez modele do widoków. Jest to plik konfiguracyjny, który jest czymś własnym.
nie
Równie łatwo można by rozważyć część modelu w postaci pliku konfiguracyjnego. Model nie musi być bazą danych. Nie mówię, że masz rację, czy nie. Sugeruję tylko, abyś, tak jak ostatnio (ponieważ utrzymywałem ten sam pogląd, co ty), wygooglowałam ten temat i zobaczyć, co mówią inni.
Marvo
8

Na pewno nie kontroler: wysyła komunikaty do przeglądania i modelowania, ale powinien wykonywać jak najmniej pracy. Jeśli użytkownik może zmienić sortowanie, to żądanie jest obsługiwane przez kontroler, informując o tym model lub widok.

Może Widok, jeśli jest to rzecz czysta. Jeśli aplikacja działa równie dobrze bez sortowania, to sortowanie jest tylko częścią reprezentacji i powinno być widoczne w widoku.

Jeśli porządkowanie jest nieodłączną częścią domeny, powinno znaleźć się w modelu.

Jens Schauder
źródło
Czy „udostępnienie komparatora lub deskryptora sortowania” liczy się jako „wykonywanie pracy”? Ponieważ logika sortowania jest zamknięta w komparatorze lub deskryptorze sortowania, nawet jeśli „sortowanie” jest wykonywane w metodzie sortowania lub na zapleczu modelu.
dasblinkenlight
Zależy, co masz na myśli, mówiąc: przekazanie jest w porządku. Ale Komparator powinien być częścią modelu lub widoku, a nie kontrolerem.
Jens Schauder
6
  • Widoki są częścią MVC, która ma zawierać logikę prezentacji.
  • Warstwa modelu to miejsce, w którym zawarta jest logika biznesowa.
  • Kontrolery zmieniają tylko stan obu na podstawie danych wejściowych użytkownika.

Wybór jest więc - czy uważasz, że jest to część logiki biznesowej domeny lub logiki prezentacji.

Jeśli implementujesz odpowiedni MVC Model2 lub klasyczny wzorzec MVC, to powiedziałbym, że kolejność danych dostarczanych przez warstwę modelu powinna być wyzwalana przez żądanie widoku do warstwy modelu. Widok pyta o uporządkowane dane, dostarcza je warstwa modelu.

Ale ponieważ używasz interpretacji wzorca MVC w ASP.NET MVC, która jest nieco inna niż standardowa MVC - wystąpienie ViewModel powinno żądać uporządkowanych informacji z warstwy modelu (z jakiegoś powodu struktura ASP.NET uważa, że ​​szablony powinny być wywoływane „widoki” i widoki należy nazywać „modelami widoków”… to dziwne).

tereško
źródło
12
Kontynuowałeś głosowanie w dół przy wielu odpowiedziach, stosując własne założenie, co oznaczają przez „logikę sortowania”. Twoje założenie jest całkowicie błędne - logika sortowania nie obejmuje i nigdy nie obejmowała pobierania.
dasblinkenlight
1
@dasblinkenlight, tak, głosuję przeciw wielu tematom, ponieważ wszystkie sugerowały, że kontroler powinien wykonać sortowanie. Co jest złe. I… ludzie… przestańcie zgłaszać moje komentarze tylko dlatego, że się z tym nie zgadzacie.
tereško
Dla jasności: nie odrzuciłem twojej odpowiedzi, ponieważ nie jest błędna, i nigdy nie zgłosiłem żadnego z twoich komentarzy, ponieważ nie uważam wtedy za obraźliwe. Szczerze mówiąc, nie wiem, w jaki sposób Twoja odpowiedź zebrała tyle negatywnych głosów: myślę, że są źle pomyślane.
dasblinkenlight
@dasblinkenlight nie ... szalałem z powodu moich komentarzy, które w tym temacie zniknęły.
tereško
5

Zwykle robiłbym to w kontrolerze, aby pozostać zgodnie ze wzorem, jak w innych odpowiedziach. Poniżej znajdziesz uzasadnienie.

Zastanawiałem się nad tym i czytałem odpowiedzi oraz związane z nimi materiały i mówiąc pragmatycznie, powiedziałbym, że zależy to na przykład od twojego wniosku:

Czy jest to średnia / duża aplikacja i / lub ma powiązanych z nią wiele UI (tj. Aplikacja Windows, interfejs sieciowy i interfejs telefonu).

  • W takim przypadku prawdopodobnie skonstruowałbym warstwę usługową i umieściłbym ją w obiekcie biznesowym, a następnie wywołałbym odpowiednią metodę ze sterownika.

Jeśli jest to dobrze zdefiniowana witryna internetowa z pojedynczym interfejsem użytkownika i używasz czegoś takiego jak EF Code First i nie masz lub nie masz zamiaru tworzyć warstwy usług i planujesz użyć prostej metody rozszerzenia, aby ją osiągnąć:

  • W tym przypadku prawdopodobnie umieściłbym go w kontrolerze, ponieważ pragmatycznie jest to najlepsze dopasowanie pod względem czasu / budżetu.

Jeśli jest taki sam jak powyższy, ALE nie można go zaimplementować z metodą rozszerzenia po wyjęciu z pudełka.

  • Mogę wybrać umieszczenie go w klasie Model (jeśli jest naprawdę dostosowany do tego pojedynczego typu), ponieważ byłby bardziej odpowiedni tutaj niż w kontrolerze. Jeśli sortowanie można zastosować do więcej niż jednej klasy, zaimplementowałbym je w metodzie rozszerzającej, a następnie wywołałbym w kontrolerze.

Podsumowując:

Odpowiedź dogmatyczna: warstwa usług

Pragmatyczna odpowiedź: Zwykle kontroler

Luke Baughan
źródło
W której definicji administrator jest odpowiedzialny za „przygotowanie danych do wglądu”?
tereško
1
@ tereško: Gdzie model jest „pasywny”, jak opisano tutaj msdn.microsoft.com/en-us/library/ff649643.aspx w sekcji odmian. Zobacz „HTTP to przykład”. Podczas gdy purysta może to kwestionować, początkującym początkującym w MVC, gdzie mogą używać EF lub innych modeli bezpośrednio w kontrolerze, a nie przez BAL, może być łatwiej myśleć o tym w ten sposób, obniżając barierę dla dalszego zrozumienia wzoru.
Luke Baughan
1
to o czym mówisz to „model anemiczny”.
tereško
Uwaga: zgodnie z sugestią usunąłem obraźliwe opisy. Pozdrawiam za wkład!
Luke Baughan
3

Sugerowałbym sortowanie danych z tabeli - dane, które są wystarczająco małe, aby były przydatne na liście rozwijanej - powinny pochodzić z bazy danych już posortowanej za pomocą zapytania. Dla mnie to sprawia, że ​​model jest miejscem, w którym stosowane jest sortowanie.

Jeśli jesteś zdeterminowany, aby sortować ręcznie, myślę, że są dobre argumenty za używaniem modelu lub kontrolera jako preferowanego miejsca dla logiki. Ograniczeniem byłby twój konkretny framework. Wolę zarządzać danymi wyłącznie w modelu. Używam kontrolera, aby poślubić dane (model) i prezentację (widok), tak jak zostałem (sam) nauczony.

B0nk3r
źródło
2

Chociaż zasadniczo zgadzam się z ideą, że sortowanie jest logiką biznesową, ponieważ rozkładając je na pochodzenie, otrzymamy coś w rodzaju: „Klient chciałby, aby strona produktu była wyświetlana z obrazami posortowanymi według daty”, wtedy staje się jasne, że porządek sortowania danych zazwyczaj nie jest arbitralny - nawet jeśli nie ma sortowania, ponieważ nadal jest to decyzja biznesowa przez pominięcie (pusta lista jest nadal listą).

ALE ... Te odpowiedzi nie wydają się uwzględniać postępu w technologii ORM, mogę mówić tylko w odniesieniu do Entity Framework (unikajmy dyskusji o tym, czy to jest prawdziwy ORM, nie o to chodzi) od Microsoft jako tego właśnie używam, ale jestem pewien, że inne ORMy oferują podobną funkcjonalność.

Jeśli utworzę widok z silną typizacją dla klasy produktu przy użyciu MS MVC i Entity Framework i istnieje relacja klucza obcego między tabelą produktu i obrazu (np. obrazy podczas ich wyświetlania za pomocą czegoś takiego w widoku:

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

Wspomniano o konkretnej warstwie logiki biznesowej, której używam również do wykonywania 80% mojej logiki biznesowej, ale nie zamierzam zapisywać funkcji sortowania w mojej warstwie logiki biznesowej, która naśladuje coś, co pojawia się po wyjęciu z pudełka z Entity Framework.

Nie sądzę, że istnieje poprawna odpowiedź na to pytanie, poza tym, że tak. jeśli to możliwe, powinieneś ująć abstrakcyjną logikę biznesową, ale nie kosztem ponownego wynalezienia koła.

Obrabować
źródło
Myślałem o tym samym, odpowiedzi tutaj nie wydają się uwzględniać ORMów i metod rozszerzających. W większości przypadków logika sortowania będzie tak prosta, jak myList.OrderBy(x => x.CreationDate)- naprawdę nie ma potrzeby wprowadzania żadnych niepotrzebnych dodatkowych warstw, aby to zrobić. Aby dodać do tego, co by zrobili, gdyby potrzebowali stronicowanych i posortowanych danych? Zapytaj całą tabelę, posortuj ją i zachowaj to, czego potrzebują? Wystarczy zadzwonić myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)i nie zostaną odzyskane żadne niepotrzebne dane.
Balázs,
1

Załóżmy, że masz witrynę MVC, witrynę WebForms i aplikację mobilną.

Jeśli chcesz, aby sortowanie było spójne między tymi warstwami prezentacji, powiedziałbym, że sortuj poza warstwą prezentacji. Służba byłaby dobrym kandydatem.

W przeciwnym razie zapisałbym tę logikę w modelu widoku. Czemu? Ponieważ będzie można go ponownie użyć i łatwo przetestować.


źródło
0

Z trzech, które wymieniłeś, powiedziałbym, że należy do kontrolera. Nie podoba mi się jednak umieszczanie tego rodzaju logiki w kontrolerze. Zwykle tworzę warstwę usług, z którą komunikuje się kontroler, która będzie odpowiedzialna za komunikację z magazynem danych i obsługę logiki sortowania. Jednak w przypadku małych aplikacji dobrze jest siedzieć w kontrolerze.

Zwolnij
źródło
2
To postawiłoby logikę bardziej po stronie modelu, prawda?
Ryan Kohn
Tak, rozumiem, że „warstwa usługowa” jest częścią modelu.
Marvo
0

Jest to pytanie zadane z myślą o asp.net, ale ponieważ ktoś wspomniał o Railsach, pomyślałem, że byłoby interesujące rozważenie problemu w tym kontekście. W Railsach sortowanie wraz z pobieraniem danych jest wykonywane jako akcja kontrolera w sposób naturalny i dość powszechny, ponieważ struktura i interfejs API ActiveRecord / ActiveQuery obsługują to. Z drugiej strony można zdefiniować niestandardowy porządek sortowania dla elementów statycznych i umieścić go w modelu używanym przez kontroler, aby model mógł odgrywać rolę w logice sortowania, nawet jeśli nie wykonuje operację bezpośrednio. Cokolwiek to jest, można śmiało powiedzieć, że umieszczanie logiki sortowania jest generalnie niezadowolone.

Jestem trochę rozbawiony, że niektóre odpowiedzi są absolutnie przeciwne umieszczaniu tego rodzaju w kontrolerze lub modelu i uważam je za zbyt pedantyczne jak na mój gust, ale przypuszczam, że zależy to od natury używanego frameworka i zwykłych konwencji związanych z to. Zgadzam się również z komentarzem Billa K., że ważniejsze jest przede wszystkim rozłąka.

prusswan
źródło