Чи слід розміщувати логіку сортування в моделі, представленні даних або контролері? [зачинено]


157

У мене є випадаючий список, який відображає значення з таблиці для кінцевого користувача. Я хотів би, щоб ці значення були відсортовані за алфавітом.

Відповідно до належного дизайну MVC, на якому шарі я повинен розміщувати свою логіку сортування: модель, вигляд чи контролер?

EDIT : У відповідь на запитання LarsH, "Ви маєте на увазі код, який визначає, який порядок сортування бажаний? Або код, який виконує сортування?", Я спочатку мав на увазі код, який визначає, який порядок сортування бажаний.


6
Щоб вирішити незгоду в коментарях, було б корисно, якщо ви скажете, що ви маєте на увазі під "сортуванням логіки". Ви маєте на увазі код, який визначає, який порядок сортування бажаний? або код, який виконує сортування?
LarsH

9
Дизайн MVC не є чимось особливим чи магічним - це насправді лише відправна точка. зробіть це відповідно до ваших потреб і пам’ятайте, що ви можете рефактор в будь-який час. Я помітив, що різні постачальники переосмислюють те, що потрапляє в контролер або перегляд, виходячи з потреб їх інструментарію, тому важко знайти будь-яку згоду. Важливо - відокремити модель від перегляду / контролера. Ви також можете отримати більше пробігу від схеми MVP, я вважаю, що це трохи конкретніше саме в цій області.
Білл К

9
Можливо, це слід перенести на програмістів.
Альфредо Озоріо

57
Однозначно в контролері. Або це, або модель. Або вид.
моб

2
Однозначно ніколи, ніколи, ніколи, ніколи в огляді.
contactmatt

Відповіді:


49

(Примітка. Ця цитата і цитата взята з відповіді @ dasblinkenlight , але ми не погоджуємось з нашою інтерпретацією цього питання. Прочитайте його допис і зробіть свою думку).

Згідно з описом MVC ,

Контролер може надсилати команди до пов'язаного з ним перегляду, щоб змінити подання моделі в представленні даних (наприклад, прокручуючи документ). Він може надсилати команди моделі для оновлення стану моделі (наприклад, редагування документа).

Логіка сортування (наприклад, порівняльник сортування / алгоритм сортування) належить до моделі, оскільки вона містить бізнес-правила та дані про стан. Оскільки зміна способу сортування даних моделі прямо підпадає під категорію "зміни подання представлення моделі", контролер відповідає за "сортування" за допомогою виклику методу model.changeSortedState ().


8
Що робити, якщо одні й ті самі дані мають відображатися у двох різних видах, відсортованих по-різному?
s4y

Це також слід зробити так само, як model.SortAscending () і model.SortDescending () і викликається Controller.
Брій

1
@Brij У належному MVC, чи можуть два представлення не мати однакової моделі?
KOVIKO

@Sidnicious Якщо є сенс мати один метод сортування, який приймає інший параметр. Наприклад public void Sort(bool sortByDescending = false), де, якщо помилковий, він сортує за зростанням. Або просто мати два різні способи сортування, якщо логіка сильно відрізняється.
MattMcGowan

@Sidnicious мають дві різні моделі, які делегують все, крім логіки сортування, до однієї третьої моделі. docs.google.com/drawings/d/…
праворуч

62

Хто контролює порядок сортування?

Проста діаграма MVCВікіпедії )

1) Природний порядок в межах самих даних:

Замовлення є частиною Моделі, тому воно повинно туди йти. Неотримані "всі дані" повернуть дані в упорядкованому порядку, і немає інтерфейсу для вибору порядку сортування.

2) Користувач повинен контролювати те, як вони бачать дані:

Перегляд забезпечив би інтерфейс (такий як стрілки для висхідної / низхідної), який взаємодіє з Контролером, і Модель розуміє дані досить добре, щоб зробити потрібний сортування даних. Однак необроблені дані не обов'язково повинні бути відсортовані, на відміну від (1).

В будь-якому випадку,

Перегляд не розуміє, що відбувається щось подібне, крім того, що можливість показувати, який напрямок сортування обрано. Не вкладайте туди логіки.

Невеликий застереження

Функціонал сортування може запускатися суто в Погляді, за однієї обставини (що я можу подумати назовні; їх може бути більше):

"Німий" сорт, де всі дані вже переглянуті, і для цього не потрібно використовувати будь-які знання домену. Наприклад, дуже просте порівняння рядків чи чисел. Це неможливо, наприклад, у результатах пошуку на веб-сторінці, коли результати, можливо, будуть розділені на кілька сторінок.


58
Перегляд може бачити користувач !?
Farzher

41
Модель оновлює вигляд !?
деге

13
Ця стаття у вікіпедії відстійна: розділ «Компонентна взаємодія» суперечить діаграмі, зображеній праворуч (яку ви тільки що опублікували тут). По-друге, модель не "оновлює" погляд. ВІДТВЕРДЖУЄ думку, коли відбулися зміни у стані. Перегляд визначає, як оновити. Тьфу. Вам цікаво, чому існує 1000 різних відповідей на це запитання, коли навколо стільки стільки незрозумілої інформації.
KyleM

4
@cHao Звичайно. Ми можемо погодитися, що графік Вікіпедії досить дивний, правда? :)
деге

6
@StephenSarcsamKamenar та всі інші: Ні, зображення має ідеальний сенс: воно показує потік даних , а не з'єднання з кодом.
Ізката

18

Згідно з описом MVC ,

Контролер може надсилати команди до пов'язаного з ним перегляду, щоб змінити подання моделі в представленні даних (наприклад, прокручуючи документ). Він може надсилати команди моделі для оновлення стану моделі (наприклад, редагування документа).

Згідно з цим логіка сортування належить до контролера, оскільки зміна способу сортування даних моделі потрапляє прямо у категорію "зміни подання подання про модель".

EDIT: Для уточнення декількох непорозумінь, висловлених у коментарях, "логіка сортування" не є кодом, який виконує сортування; саме код визначає сортування. Логіка сортування порівнює окремі елементи між собою для встановлення порядку (наприклад, через екземпляр IComparator<T>) або містить логіку, яка будує об'єкт, який буде використовуватися для замовлення зовнішньою системою (наприклад, через екземпляр IOrderedQueryable<T>). Ця логіка належить до вашого контролера, оскільки вона потребує знань, пов'язаних із "діловою" стороною вашої програми. Цілком достатньо для виконання сортування, але він є окремим від коду, який насправді виконуєце. Код, який сортує, може бути у вашому поданні, у вашій моделі або навіть у шарі стійкості, який підтримує вашу модель (наприклад, ваша база даних SQL).


12
-1 Як вам вдалося зробити висновок з цієї цитати? Чи десь там говорили, що контролер повинен отримувати інформацію з моделі? Контролер надсилає команди для зміни стану. Про вилучення чи маніпулювання інформацією нічого не сказано.
tereško

3
@ tereško Як вам вдалося зробити висновок із моєї відповіді, що контролеру потрібно отримати інформацію з моделі? Під "сортуванням логіки" я маю на увазі лише та логіку, яка необхідна для встановлення впорядкування - в термінах C #, що забезпечує реалізацію IComparer<T>. Залишилася «механіка котла» сортування, включаючи вилучення даних з моделі, до перегляду.
dasblinkenlight

3
".. логіка сортування належить до контролера .." , що ще це означає?
tereško

3
"Контролер може відправляти команди на його пов'язаний вигляд для зміни подання перегляду" дійсно звучить так, як подання робило б сортування у відповідь на команду контролера.
Samuel Edwin Ward

1
@KyleM Але погляд не завжди має достатньо знань, щоб містити логіку сортування. Наприклад, розглянемо поле, яке має числовий код, що відповідає одному з перерахунків {Unknown, Pass, Fail}. Далі припускаємо, що Unknownзавжди слід сортувати останнє, незалежно від порядку зростання чи зменшення, який користувач обрав. Якщо розмістити цю логіку у представленні, це занадто багато скаже вам про діловий характер даних усередині codeполя. Погляд не повинен цього знати: все, що він знає, це те, що користувач здійснив жест "сортування" (наприклад, натиснув на заголовок); решта - до контролера.
dasblinkenlight

10

Жоден з вищевказаних.Сортування - це бізнес-логіка, а ділова логіка не належить до жодної з цих трьох. Не кожен фрагмент коду у вашій програмі буде моделлю, переглядом або контролером.

Що я зазвичай роблю в своїх додатках MVC, це те, що у мене є сервісний рівень, який виконує всю логіку бізнесу. Методи в рівні обслуговування повинні мати чистий, простий API з добре названими параметрами. Потім ви можете викликати ці методи від свого контролера для маніпулювання даними в моделях.

У цьому сенсі сортування проводиться "в контролері", але сам код, який виконує сортування, не повинен бути реалізований у контролері, а лише звідти викликується.


5
Нещодавно мені повідомили, що деякі люди вважають "рівень обслуговування" (бізнес-логіка) частиною моделі.
Марво

@Marvo Я думаю, що є випадки, коли певні логіки настільки тісно пов'язані зі своїм типом даних, що має сенс інкапсулювати їх разом в одному класі. (наприклад, функції часу та дати). В цілому, однак, я вважаю, що це найкраще працює, коли об’єкти моделі не роблять нічого, крім даних.
неділя

Тоді звідки бізнес-логіка «живе» за схемою MVC?
Марво

2
Тільки тому, що програма використовує шаблон MVC, це не означає, що кожен фрагмент коду в додатку буде моделлю, переглядом або контролером. Це сприймає дизайнерські зразки занадто буквально. Наприклад, у вашій програмі, ймовірно, є якийсь файл конфігурації. Цей конфігураційний файл не є ні моделюванням даних користувачів, ні поданням представлень, ні керуванням потоком даних через моделі до представлень. Його конфігураційний файл, який є власною річчю.
неділя

Можна так само легко розглянути конфігураційний файл моделі. Модель не повинна бути базою даних. Я не кажу, що ти прав чи не прав. Я просто пропоную вам, як і я нещодавно (тому що я дотримувався такої ж точки зору, як і ви), трохи погуглити тему і подивитися, що говорять інші.
Марво

8

Однозначно не контролер: він надсилає повідомлення для перегляду та моделювання, але повинен робити якомога менше роботи. Якщо користувач може змінити сортування, цей запит обробляється контролером, повідомляючи модель або вид про неї.

Можливо, Погляд, якщо це чистий погляд. Якщо Додаток працює так само без сортування, сортування - це лише частина представлення і має проходити у поданому вигляді.

Якщо замовлення є притаманною частиною домену, воно повинно йти за моделлю.


Чи "надання компаратора чи дескриптора сортування" вважається "виконанням роботи"? Оскільки логіка сортування інкапсульована в компараторі чи дескрипторі сортування, навіть якщо "сортувальна робота" виконується методом сортування або задньої частини моделі.
dasblinkenlight

Залежить від того, що ви маєте на увазі, надаючи: вхід нормально. Але Компаратор повинен бути частиною моделі або перегляду, а не контролером.
Єнс Шодер

6
  • Погляди - це частина MVC, яка повинна містити логіку презентації.
  • Модельний шар - це місце, де міститься бізнес-логіка.
  • Контролери змінюють стан обох, виходячи з введення користувача.

Тож вибір - чи вважаєте ви, що це частина логіки бізнесу домену чи логіки презентації.

Якщо ви реалізували правильний MVC Model2 або класичний MVC шаблон, то я б сказав, що впорядкування даних, що надаються шаром моделі, повинно бути спровоковано запитом подання на рівень моделі. Перегляд запитує впорядковані дані, рівень моделі надає їх.

Але оскільки ви використовуєте інтерпретацію шаблону MVC ASP.NET MVC, яка дещо відрізняється, то ваш стандартний MVC - екземпляр ViewModel повинен запитувати впорядковану інформацію з рівня моделі (чомусь ASP.NET Framework вважає, що шаблони слід викликати "поглядів" і поглядів слід називати "viewmodels" .. це дивно).


12
Ви продовжували відмовлятися від кількох відповідей, застосовуючи власне припущення, що вони означають під "сортуванням логіки". Ваше припущення є абсолютно невірним - логіка сортування не включає і ніколи не включає пошук.
dasblinkenlight

1
@dasblinkenlight, так, я забороняю кілька тем, тому що всі вони мали на увазі, що контролер повинен виконувати сортування. Що неправильно І .. люди .. будь ласка, припиніть позначати мої коментарі лише тому, що ви не згодні.
tereško

Щоб було зрозуміло: я не спростував вашої відповіді, тому що вона невірна, і я ніколи не позначав жодних ваших коментарів, тому що я не вважаю, що я будь-яким чином зловживав. Чесно кажучи, я не знаю, як за вашу відповідь вдалося отримати стільки голосів: я думаю, що вони недоброзичливі.
dasblinkenlight

@dasblinkenlight naah .. Я бушував про мої коментарі, які в цій темі траплялися зниклими.
tereško

5

Зазвичай я б робив це в контролері, щоб залишатися у відповідності з шаблоном, як і в інших відповідях. Дивіться нижче для міркувань.

Я обмірковував це і читав відповіді та відповідний матеріал, і прагматично кажу, я б сказав, що це залежатиме від вашої заявки, наприклад:

Це середня / велика програма та / або з нею пов'язано декілька інтерфейсів (тобто додаток для Windows, веб-інтерфейс та телефонний інтерфейс).

  • У цьому випадку я б, мабуть, сконструював сервісний рівень і помістив його у бізнес-об'єкт, а потім викликав відповідний метод від контролера.

Якщо це чітко визначений веб-сайт єдиного інтерфейсу, і ви використовуєте щось на зразок коду EF спочатку, і ви не маєте або не маєте наміру створювати сервісний рівень і плануєте використовувати простий метод з розширення, який не використовується в коробці, щоб досягти його:

  • У цьому випадку я, мабуть, помістив його в контролер як прагматично найкраще підходить щодо часу / бюджету.

Якщо його збігається з вищевказаним, АЛЕ неможливо реалізувати методом розширення із скриньки.

  • Я цілком міг би вибрати його в класі Model (якщо він справді відповідає такому типу), як це було б більш доречно, ніж у контролері. Якщо сортування можна було застосувати до більш ніж одного класу, то я би реалізував його методом розширення, а потім викликав би його в контролері.

Підсумовуючи:

Догматична відповідь: Службовий шар

Прагматична відповідь: Зазвичай контролер


У якому визначенні контролер відповідає за "підготовку даних до перегляду"?
терешко

1
@ tereško: Де модель "пасивна", як описано тут, msdn.microsoft.com/en-us/library/ff649643.aspx у розділі варіантів. Дивіться "HTTP - приклад цього". Хоча пурист може спростувати це, початківцям може бути простіше, починаючи з MVC, де вони можуть використовувати EF або інші моделі безпосередньо в контролері, а не через BAL, щоб думати про це таким чином, знижуючи бар'єр для подальшого розуміння шаблону.
Люк Баген

1
про що ви говорите, це "анемічна модель".
терешко

Точка зауважила, що я видалив описи образи, як ви запропонували. Ура за вхід!
Люк Баган

3

Я б запропонував сортувати дані з таблиці, яка є достатньо малою, щоб бути корисною у випадаючому списку - повинна надходити з БД, вже відсортованої за запитом. Для мене це робить модель місцем, на яке застосовується сортування.

Якщо ви налаштовані робити сортування вручну, я думаю, що є хороші аргументи для використання або моделі, або контролера як вашого бажаного місця для логіки. Обмеження було б вашою конкретною рамкою. Я вважаю за краще керувати даними виключно в моделі. Я використовую контролер для одруження даних (моделі) та презентації (перегляду), як я вже був (самоуком).


2

Хоча я принципово погоджуюся з думкою, що сортування - це бізнес-логіка, оскільки, розбивши її до свого походження, ви отримаєте щось на кшталт "Клієнт хотів би, щоб сторінка продукту відображалася із зображеннями, відсортованими за датою", тоді стає зрозуміло, що порядок сортування даних, як правило, не є довільним - навіть якщо немає сортування, оскільки це все-таки ділове рішення за пропуском (порожній список все ще є списком).

Але ... Ця відповідь, здається, не враховує досягнень технології ORM, я можу говорити лише стосовно Entity Framework (давайте уникати аргументів про те, чи це правда ORM, це не суть) від Microsoft як саме цим я і користуюся, але впевнений, що інші ОРМ пропонують подібну функціональність.

Якщо я створять вигляд із сильним типом для продуктового класу за допомогою MS MVC та Entity Framework, і між таблицею Product і Image є зовнішній ключ (наприклад, FK_Product_Image_ProductId), я б поза межами поля змогла швидко сортувати зображення під час їх відображення, використовуючи щось таке у поданні:

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

Згадувалося про специфічний шар Business Logic, який я також використовую для виконання 80% своєї бізнес-логіки, але я не збираюся писати функціональність сортування у мій шар Business Logic, який імітує щось, що виходить із коробки з цілісних рамок.

Я не думаю, що на це питання є правильна відповідь, крім того, щоб сказати це; Ви повинні абстрагувати складну бізнес-логіку там, де це можливо, але не ціною, щоб винаходити колесо.


Я думав те саме, відповіді тут, схоже, не враховують ORM та методи розширення. У більшості випадків логіка сортування буде такою ж простою myList.OrderBy(x => x.CreationDate)- насправді немає необхідності вводити зайвий додатковий шар просто для цього. Щоб додати до цього, що б вони зробили, якби їм знадобилися підказка та сортування даних? Запитайте весь стіл, відсортуйте його та збережіть те, що їм потрібно? Можна просто зателефонувати, myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)і зайвих даних не буде отримано.
Балаж

1

Припустимо, що у вас є веб-сайт MVC, веб-сайт WebForms та мобільний додаток.

Якщо ви хочете, щоб сортування узгоджувалося між цими презентаційними шарами, тоді я б сказав сортувати поза шаром презентації. Служба була б хорошим кандидатом.

Інакше я б зберігав цю логіку у переглянутій моделі. Чому? Тому що це буде багаторазове використання та легко перевіряється.


0

З трьох перелічених вами я б сказав, що він належить до контролера. Мені не дуже подобається розміщувати таку логіку в контролері. Я зазвичай створюю сервісний рівень, з яким спілкується контролер, і буде відповідальним за зв'язок із сховищем даних та обробкою логіки сортування. Хоча для невеликих додатків добре сидіти в контролері.


2
Це може поставити логіку більше на стороні моделі, правильно?
Райан Кон

Так, моє розуміння "сервісного рівня" полягає в тому, що це частина моделі.
Марво

0

Це питання, задане на увазі asp.net, але оскільки хтось згадав про Rails, я подумав, що було б цікаво розглянути проблему в цьому контексті. У Rails закономірно і досить часто виконувати сортування разом із пошуком як дією контролера, оскільки рамки та програми для ActiveRecord / ActiveQuery для них. З іншого боку, можна визначити якийсь спеціальний порядок сортування для статичних елементів і поставити це в моделі, яка використовується контролером, щоб модель могла грати роль у логіці сортування, навіть якщо вона не виконує операція безпосередньо. Як би там не було, можна з упевненістю сказати, що розміщення логіки сортування у погляді, як правило, нахмуриться.

Я трохи розвеселений, що деякі відповіді категорично проти введення сортування або в контролер, або в модель, і я вважаю їх занадто педантичними на мій смак, але я вважаю, що це залежить від характеру використовуваної рамки та звичайних умов, пов'язаних з це. Я також погоджуюся з коментарем Білла К., що важливіше розлучення в першу чергу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.