Должна ли логика сортировки быть размещена в модели, представлении или контроллере? [закрыто]

157

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

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

РЕДАКТИРОВАТЬ : В ответ на вопрос Ларша: «Вы имеете в виду код, который определяет, какой порядок сортировки является желательным? Или код, который выполняет сортировку?», Я первоначально имел в виду код, который определяет, какой порядок сортировки является желательным.

Райан Кон
источник
6
Для разрешения разногласий в комментариях было бы полезно, если бы вы сказали, что вы подразумеваете под «логикой сортировки». Вы имеете в виду код, который определяет, какой порядок сортировки желателен? или код, который выполняет сортировку?
LarsH
9
Дизайн MVC не является чем-то особенным или волшебным - это просто отправная точка. сделайте так, чтобы она соответствовала вашим потребностям, и помните, что вы можете провести рефакторинг в любое время Я заметил, что разные поставщики будут пересматривать то, что входит в контроллер или представление, в зависимости от потребностей их инструментария, поэтому трудно найти какое-либо соглашение. Важно отделить вашу модель от вашего вида / контроллера. Вы также можете получить больше пробега от паттерна MVP, я думаю, что он немного более конкретен именно в этой области.
Билл К
9
Может быть, это следует перенести на программистов.
Альфредо Осорио
57
Определенно в контроллере. Либо это, либо модель. Или мнение.
моб
2
Определенно никогда, никогда, никогда, никогда в поле зрения.
contactmatt

Ответы:

49

(Примечание: эта цитата и цитата взяты из ответа @ dasblinkenlight , но мы не согласны с нашей интерпретацией. Прочитайте его пост и определитесь ).

Согласно описанию MVC ,

Контроллер может отправлять команды в свой связанный вид для изменения представления модели (например, путем прокрутки документа). Он может отправлять команды модели для обновления состояния модели (например, редактирование документа).

Логика сортировки (например, сортировочный компаратор / алгоритм сортировки) принадлежит модели, поскольку она содержит бизнес-правила и данные состояния. Поскольку изменение способа сортировки данных модели прямо попадает в категорию «изменить представление представления модели», контроллер отвечает за «выполнение сортировки» путем вызова метода model.changeSortedState ().

KyleM
источник
8
Что, если одни и те же данные должны отображаться в двух разных представлениях, отсортированных по-разному?
s4y
Это также должно быть сделано аналогичным образом, model.SortAscending () и model.SortDescending () и вызвано Controller.
Бридж
1
@Brij В правильном MVC, два представления не могут разделить ту же самую модель?
КОВИКО
@Sidnicious Если имеет смысл иметь один метод сортировки, который принимает другой параметр. Например public void Sort(bool sortByDescending = false), где если false, то сортируется по возрастанию. Или просто есть два разных метода сортировки, если логика сильно отличается.
MattMcGowan
У @Sidnicious есть две разные модели, которые делегируют все, кроме логики сортировки, одной третьей модели. docs.google.com/drawings/d/…
вправо
62

Кто контролирует порядок сортировки?

Простая схема MVC(Из Википедии )

1) Естественный порядок в самих данных:

Заказ является частью модели, поэтому он должен идти туда. Необработанное извлечение «всех данных» вернет данные в отсортированном порядке, и нет интерфейса для выбора порядка сортировки.

2) Пользователь должен контролировать, как они видят данные:

Представление предоставит интерфейс (такой как восходящие / нисходящие стрелки), который взаимодействует с Контроллером, и Модель понимает данные достаточно хорошо, чтобы выполнить запрошенную сортировку данных. Тем не менее, в отличие от (1), необработанные данные не обязательно должны быть отсортированы.

В любом случае,

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

Небольшое предостережение

Функциональность сортировки может идти исключительно в представлении, при одном обстоятельстве (что я могу придумать не по порядку; может быть больше):

«Тупая» сортировка, когда все данные уже находятся в представлении, и ей не нужно использовать какие-либо знания предметной области для выполнения сортировки. Например, очень простое сравнение строк или чисел. Это невозможно, например, в результатах поиска на веб-странице, когда результаты могут быть разделены на несколько страниц.

Izkata
источник
59
Вид может видеть пользователь !?
Фаржер
41
Модель обновляет вид !?
deceze
13
Эта статья в Википедии - отстой: раздел «Взаимодействие компонентов» конфликтует с диаграммой, показанной справа (которую вы только что разместили здесь). Во-вторых, модель не «обновляет» вид. Он уведомляет о том, когда произошло изменение состояния. Представление решает, как обновить. Тьфу. Вы удивляетесь, почему существует 1000 разных ответов на этот вопрос, когда вокруг так много неясной информации.
KyleM
4
@CHao Конечно. Мы можем согласиться с тем, что граф Википедии довольно странный, правда? :)
deceze
6
@StephenSarcsamKamenar и все остальные: нет, изображение имеет смысл: он показывает поток данных , а не кодовые соединения.
Изката
18

Согласно описанию MVC ,

Контроллер может отправлять команды в свой связанный вид для изменения представления модели (например, путем прокрутки документа). Он может отправлять команды модели для обновления состояния модели (например, редактирование документа).

В соответствии с этим логика сортировки принадлежит контроллеру, поскольку изменение способа сортировки данных модели прямо попадает в категорию «изменение представления представления модели».

РЕДАКТИРОВАТЬ: Чтобы прояснить несколько недоразумений, высказанных в комментариях, «логика сортировки» не является кодом, который выполняет сортировку; это код, который определяет сортировку. Логика сортировки сравнивает отдельные элементы друг с другом, чтобы установить порядок (например, через экземпляр IComparator<T>) или содержит логику, которая создает объект, который будет использоваться для упорядочения внешней системой (например, через экземпляр IOrderedQueryable<T>). Эта логика принадлежит вашему контроллеру, потому что она требует знаний, связанных с «бизнес» стороной вашего приложения. Этого вполне достаточно для выполнения сортировки, но она отделена от кода, который фактически выполняетЭто. Код, который сортируется, может быть в вашем представлении, в вашей модели или даже на уровне персистентности, который поддерживает вашу модель (например, вашу базу данных SQL).

оборота
источник
12
-1 Как тебе удалось сделать вывод из этой цитаты? Было ли где-то сказано, что контроллер должен извлекать информацию из модели? Контроллер отправляет команды для изменения состояния. Там ничего не сказано о извлечении или манипулировании информацией.
tereško
3
@ tereško Как вам удалось из моего ответа сделать вывод, что контроллеру необходимо получить информацию из модели? Под «логикой сортировки» я подразумеваю только логику, необходимую для установления порядка - в терминах C #, которая обеспечивает реализацию IComparer<T>. Оставшаяся «стандартная механика» сортировки, включая извлечение данных из модели, остается на виду.
dasblinkenlight
3
«... логика сортировки принадлежит контроллеру ...» , что еще это значит?
tereško
3
«Контроллер может отправлять команды в свой связанный вид для изменения представления представления», на самом деле звучит так, будто вид будет выполнять сортировку в ответ на команду от контроллера.
Сэмюэль Эдвин Уорд
1
@KyleM Но представление не всегда обладает достаточными знаниями, чтобы содержать логику сортировки. Например, рассмотрим поле с числовым кодом, соответствующим одному из перечислений {Unknown, Pass, Fail}. Далее предположим, что Unknownсортировка всегда должна выполняться последней, независимо от того, какой пользователь выбрал возрастающий или убывающий порядок. Размещение этой логики в представлении слишком много скажет вашему представлению о деловой природе данных внутри codeполя. Представление не должно знать этого: все, что он знает, - это то, что пользователь выполнил жест «сортировки» (например, щелкнул заголовок); остальное зависит от контроллера.
dasblinkenlight
10

Ни один из вышеперечисленных. Сортировка - это бизнес-логика, а бизнес-логика не относится ни к одному из трех. Не каждый фрагмент кода в вашем приложении будет моделью, представлением или контроллером.

Что я обычно делаю в своих приложениях MVC, так это то, что у меня есть сервисный уровень, который выполняет всю бизнес-логику. Методы на уровне сервиса должны иметь чистый, простой API с хорошо именованными параметрами. Затем вы можете вызывать эти методы из вашего контроллера для манипулирования данными в моделях.

В этом смысле сортировка происходит «в контроллере», но сам код, который выполняет сортировку, не должен реализовываться в контроллере, а вызываться только оттуда.

Nont
источник
5
Недавно мне сообщили, что некоторые люди считают, что «сервисный уровень» (бизнес-логика) является частью модели.
Марво
@Marvo Я думаю, что в некоторых случаях определенные кусочки логики настолько тесно связаны с их типом данных, что имеет смысл объединить их вместе в одном классе. (функции времени и даты, например). В целом, однако, я считаю, что это работает лучше всего, когда объекты модели ничего не делают, кроме хранения данных.
не
Тогда где бизнес-логика «живет» в паттерне MVC?
Марво
2
То, что приложение использует шаблон MVC, не означает, что каждый фрагмент кода в приложении будет моделью, представлением или контроллером. Это воспринимает шаблоны дизайна слишком буквально. Например, ваше приложение, вероятно, имеет какой-то файл конфигурации. Этот файл конфигурации не моделирует пользовательские данные, не представляет представления и не управляет потоком данных через модели в представления. Это конфигурационный файл, который является своего рода вещью.
не
Можно так же легко рассмотреть конфигурационный файл как часть модели. Модель не должна быть базой данных. Я не говорю, что ты прав или неправ. Я просто предлагаю вам, как я недавно сделал (потому что я придерживался той же точки зрения, что и вы), немного погуглить тему и посмотреть, что говорят другие.
Марво
8

Определенно не контроллер: он отправляет сообщения для просмотра и моделирования, но должен выполнять как можно меньше работы. Если пользователь может изменить сортировку, этот запрос обрабатывается контроллером, информируя модель или представление об этом.

Может быть, View, если это чистая вещь View. Если приложение работает так же хорошо, без сортировки, то сортировка является лишь частью представления и должна идти в представлении.

Если порядок является неотъемлемой частью домена, он должен идти в модели.

Йенс Шаудер
источник
Считается ли «предоставление компаратора или дескриптора сортировки» «выполнением работы»? Потому что логика сортировки инкапсулирована в компараторе или дескрипторе сортировки, даже если «работа по сортировке» выполняется в методе сортировки или бэкэнде модели.
dasblinkenlight
Зависит от того, что вы подразумеваете под предоставлением: передача в порядке. Но Comparator должен быть частью модели или представления, а не контроллера.
Йенс Шаудер
6
  • Представления являются частью MVC, которая должна содержать логику представления.
  • На уровне модели содержится бизнес-логика.
  • Контроллеры только изменяют состояние обоих, основываясь на пользовательском вводе.

Таким образом, выбор - вы думаете, что это является частью бизнес-логики домена или логики представления.

Если бы вы реализовывали правильный MVC Model2 или классический шаблон MVC, то я бы сказал, что упорядочение данных, предоставляемых уровнем модели, должно инициироваться запросом представления к уровню модели. Вид запрашивает упорядоченные данные, модельный слой предоставляет их.

Но, поскольку вы используете интерпретацию шаблона MVC в ASP.NET MVC, которая немного отличается от вашей стандартной MVC - экземпляр ViewModel должен запрашивать упорядоченную информацию из уровня модели (по какой-то причине платформа ASP.NET считает, что шаблоны следует вызывать "Представления" и представления должны называться "представлениями" .. это странно).

tereško
источник
12
Вы продолжали опровергать несколько ответов, применяя свое собственное предположение о том, что они подразумевают под «логикой сортировки». Ваше предположение совершенно неверно - логика сортировки не включает и никогда не включала поиск.
dasblinkenlight
1
@dasblinkenlight, да, я обсуждаю несколько тем, поскольку все они подразумевают, что контроллер должен выполнять сортировку. Что не так. И .. люди .. пожалуйста, прекратите отмечать мои комментарии только потому, что вы не согласны.
tereško
Просто чтобы прояснить: я не понизил ваш ответ, потому что он не является неправильным, и я никогда не отмечал ни одного из ваших комментариев, потому что я не нахожу в этом случае оскорбления. Честно говоря, я не знаю, как ваш ответ смог получить так много отрицательных голосов: я думаю, что они непродуманны.
dasblinkenlight
@dasblinkenlight naah .. Я бушевал по поводу моих комментариев, которые в этой теме исчезли.
tereško
5

Я обычно делал бы это в контроллере, чтобы оставаться в соответствии с шаблоном согласно другим ответам. Смотрите ниже для рассуждений.

Я обдумывал это, читал ответы и связанный материал, и, прагматично говоря, я бы сказал, что это будет зависеть, например, от вашей заявки:

Это среднее / большое приложение и / или с ним связано несколько пользовательских интерфейсов (т. Е. Приложение Windows, веб-интерфейс и интерфейс телефона).

  • В этом случае я бы, вероятно, создал бы сервисный уровень и поместил бы его в бизнес-объект, а затем вызвал бы соответствующий метод из контроллера.

Если это четко определенный веб-сайт с пользовательским интерфейсом, и вы используете что-то вроде EF Code First, и у вас нет или нет намерения создавать сервисный уровень и вы планируете использовать простой готовый метод Extension для его получения:

  • В этом случае я бы, вероятно, поместил его в контроллер, так как он прагматически лучше всего подходит с точки зрения времени / бюджета.

Если он такой же, как указано выше, НО не может быть реализован с помощью метода расширения «из коробки».

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

Подводить итоги:

Догматический ответ: Сервисный уровень

Прагматичный ответ: обычно контроллер

Люк Боуган
источник
В каком определении контроллер отвечает за «подготовку данных для просмотра»?
tereško
1
@ tereško: где модель "пассивна", как описано здесь. msdn.microsoft.com/en-us/library/ff649643.aspx в разделе вариантов. Смотрите «HTTP является примером этого». Хотя пурист может оспорить это, новичкам легче начать с MVC, где они могут использовать EF или другие модели непосредственно в контроллере, а не через BAL, думать об этом таким образом, снижая барьер для дальнейшего понимания паттерна.
Люк Боуган
1
то, о чем вы говорите, это «анемичная модель».
tereško
Точка отметил, я удалил оскорбительные описания, как вы предложили. Приветствия для входа!
Люк Боуган
3

Я бы предложил сортировать данные из табличных данных, которые достаточно малы, чтобы быть полезными в раскрывающемся списке - должны поступать из БД, уже отсортированной по запросу. Для меня это делает модель местом, где применяется сортировка.

Если вы полны решимости выполнить сортировку вручную, я думаю, что есть хорошие аргументы для использования либо модели, либо контроллера в качестве предпочтительного места для логики. Ограничение будет вашей конкретной структурой. Я предпочитаю управлять данными исключительно в модели. Я использую контроллер, чтобы объединить данные (модель) и представление (представление), как меня (само) учили.

B0nk3r
источник
2

Хотя я в принципе согласен с идеей, что сортировка - это бизнес-логика, потому что, разбив ее на ее происхождение, вы получите что-то вроде «Клиент хотел бы, чтобы страница продукта отображалась с изображениями, отсортированными по дате», тогда становится ясно, что порядок сортировки данных, как правило, не является произвольным - даже если сортировка не выполняется, так как это все еще является бизнес-решением по причине пропуска (пустой список по-прежнему остается списком).

НО ... Эти ответы, кажется, не учитывают достижения в технологии ORM, я могу говорить только в отношении Entity Framework (давайте избегать споров о том, является ли это истинным ORM, это не главное) от Microsoft как это то, что я использую, но я уверен, что другие ORM предлагают аналогичную функциональность.

Если я создам строго типизированное представление для класса Product, используя MS MVC и Entity Framework, и между таблицей Product и Image (например, FK_Product_Image_ProductId) есть связь по внешнему ключу, то я смог бы быстро выполнить сортировку из коробки. изображения во время их отображения, используя что-то вроде этого в представлении:

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

Было упомянуто о конкретном слое бизнес-логики, который я также использую для выполнения 80% своей бизнес-логики, но я не собираюсь вписывать функциональность сортировки в свой слой бизнес-логики, который имитирует что-то из коробки из Entity Framework.

Я не думаю, что есть правильный ответ на этот вопрос, кроме как сказать это; Вы должны абстрагироваться от сложной бизнес-логики, где это возможно, но не за счет изобретения колеса.

обкрадывать
источник
Я думал о том же, ответы здесь, кажется, не принимают во внимание ORM и методы расширения. В большинстве случаев логика сортировки будет такой простой, как myList.OrderBy(x => x.CreationDate)- на самом деле нет необходимости вводить какой-либо ненужный дополнительный слой просто для этого. Чтобы добавить к этому, что они будут делать, если им нужны разбитые на страницы и отсортированные данные? Запросить всю таблицу, отсортировать ее и сохранить то, что им нужно? Можно просто позвонить, myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)и никакие ненужные данные не будут получены.
Balázs
1

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

Если вы хотите, чтобы сортировка была согласованной между этими уровнями представления, то я бы сказал, сортировка вне уровня представления. Служба будет хорошим кандидатом.

В противном случае я бы сохранил эту логику в модели представления. Зачем? Потому что он будет многоразовым и легко проверяемым.


источник
0

Из трех перечисленных я бы сказал, что он принадлежит контроллеру. Мне не очень нравится размещать такую ​​логику в контроллере. Я обычно создаю сервисный уровень, с которым взаимодействует контроллер, который будет отвечать за связь с хранилищем данных и обработку логики сортировки. Для небольших приложений это хорошо, сидя в контроллере, хотя.

Dismissile
источник
2
Это позволило бы поставить логику на сторону модели, правильно?
Райан Кон
Да, я понимаю "уровень обслуживания", что это часть модели.
Марво
0

Этот вопрос задан с учетом asp.net, но, поскольку кто-то упомянул Rails, я подумал, что было бы интересно рассмотреть проблему в этом контексте. В Rails вполне естественно и довольно часто выполнять сортировку вместе с извлечением в качестве действия контроллера, поскольку для этого предусмотрены инфраструктура и API-интерфейсы ActiveRecord / ActiveQuery. С другой стороны, можно определить какой-то пользовательский порядок сортировки для статических элементов и поместить его в модель, которая будет использоваться контроллером, чтобы модель могла играть роль в логике сортировки, даже если она не выполняется. операция напрямую. Что бы это ни было, можно с уверенностью сказать, что представление логики сортировки, как правило, осуждается.

Я немного удивлен, что некоторые ответы абсолютно против использования сортировки в контроллере или модели, и я считаю их слишком педантичными на мой вкус, но я полагаю, что это зависит от природы используемой платформы и обычных соглашений, связанных с Это. Я также согласен с комментарием Билла К. о том, что разделение в первую очередь важнее.

prusswan
источник