Архитектура MVC - сколько контроллеров мне нужно?

54

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

Я надеюсь, что этот вопрос не слишком похож на « Рекомендации по архитектуре MVC », но, когда я прохожу несколько разных руководств, я заметил, что в некоторых есть несколько контроллеров для разных целей.

Сколько контроллеров нужно одному веб-приложению?

Я понимаю, что это будет трудно ответить без примера, поэтому я приведу один:

Заявка:

  1. Пользователь входит в систему.
  2. Пользователь может сделать одну из трех вещей:
    a) Загрузить файл (хранящийся в базе данных mongodb с метаданными).
    б) поиск файла.
    в) Выйти.

Мой вопрос носит общий характер, но я привел пример, чтобы помочь любому, кто пытается ответить.

Джефф
источник
8
Действительно приятно заданный вопрос.
Даниэль Холлинрейк

Ответы:

34

Для вашего примера я бы создал два контроллера:

  • Контроллер сеансов для входа и выхода из системы (создание и уничтожение сеанса для REST-подобного макета)
  • Контроллер файлов для всего, что есть в файлах (index = search and create = upload)

В целом подход RESTful, в котором вы рассматриваете все как ресурс, который можно отображать, создавать, редактировать и уничтожать, дает вам хорошее представление о том, как структурировать вещи. Как вы можете видеть из моих примеров, я не придерживаюсь слишком близко к каждому глаголу в REST.

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

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

Торстен Мюллер
источник
3
Возьмем пример администратора: расширит ли контроллер администратора обычного пользователя или полностью переопределит все методы? Например, может быть, все пользователи могут загружать и искать, но удалять могут только администраторы. Будет ли класс контроллера администратора наследовать все обычные методы пользователя?
Джефф
4
Это действительно во многом зависит от реальной функциональности. Но в целом я просто пишу второй контроллер без какого-либо наследования. Следуя принципу «тонкого контроллера», в контроллере не должно быть много кода. И контроллер администратора может быть особенно простым. Все важные функции входят в модель. (например, если удаление пользователя означает, что все его файлы также должны быть удалены, то модель это обрабатывает, для этого в контроллере нет ни одной строки)
thorsten müller
6

Это действительно зависит от веб-приложения. В вашем примере одного, вероятно, достаточно. Если бы вы внедрили полнофункциональное приложение для электронной коммерции, включающее доставку, налоги, управление запасами, многоуровневое ценообразование и т. Д., То вам может понадобиться еще пара.

Если ваш контроллер страдает от одного или нескольких запахов кода (особенно Large Class или God Object ), то вы знаете, что вы, вероятно, уже достигли точки, когда это сделает только один.

Дэн Пичельман
источник
5

Это действительно зависит от потребностей вашего приложения и архитектуры бизнес-модулей.

Общее правило: количество необходимых контроллеров зависит от количества модулей и субмодулей в веб-приложении.

В качестве дополнения было бы полезно организовать контроллеры в области . Концепция Areas встроена в инфраструктуру ASP.NET MVC и упрощает организацию контроллеров, обслуживающих один модуль.

Есть ряд связанных обсуждений:

Е.Л. Юсубов
источник
1
Отличные ссылки! Я обязательно проверю их!
Джефф
Конечно, нет проблем.
Е.Л. Юсубов
4

Мне нравится способ Apple сделать это.

Каждый вид контролируется только одним контроллером вида. ~ Руководство по программированию контроллера для iOS

Идея состоит в том, чтобы вы могли легко менять представления. ИМО, имея только 1 Controllerза Viewэто облегчает для достижения этой цели . Но я уверен, что у вас мог бы быть Контроллер с несколькими представлениями, и все же он мог бы спроектировать так, чтобы вы могли переключать представления без изменения логики программы.

Корей Хинтон
источник
Это хороший момент, но нужно ли вам иметь контроллер для каждого представления плюс дополнительные, чтобы заботиться о таких вещах, как пользователи? Я также думаю, что если бы мой проект был больше, было бы больше смысла иметь больше контроллеров.
Джефф
Модели должны отслеживать пользователей. Таким образом, при необходимости несколько контроллеров могут использовать один и тот же объект модели.
Корей Хинтон
2
Таким образом, контроллер имеет объект Model и объект View. Контроллер запрашивает информацию у объекта Model (например, о пользователе), а затем устанавливает представление соответствующим образом. Модель должна иметь большую часть программной логики, в то время как Контроллер просто имеет логику, позволяющую обмениваться данными между Представлением и Моделью.
Корей Хинтон
2
Один контроллер для каждого представления очень ограничен, так как ваш контроллер не сможет отображать разные модели представления для разных состояний модели.
Е.Л. Юсубов
1
@ElYusubov Я вижу, где это может сбить с толку. В iOS каждое представление имеет только один контроллер представления, и каждый контроллер представления имеет только 1 активное представление (и это представление может иметь вложенные представления), но этот контроллер представления также может содержать ссылки на любое количество представлений.
Корей Хинтон
2

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


На более старом аналоговом термостате вы можете изобразить такие вещи:

Вид - считыватель температуры, который отображает текущую температуру.

Контроллер - циферблат, на котором вы меняете температуру

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


Вы должны всегда придерживаться конструкций, которые допускают слабую связь и ограничивать модели и связанные с ними контроллеры для одной задачи , и вы должны использовать столько модулей / контроллеров, сколько вам нужно . В зависимости от размера вашего приложения у вас может быть гораздо меньше представлений, чем у моделей и контроллеров. Этого следует ожидать с любым приложением большого размера. Хорошее объектно-ориентированное программирование характеризуется слабой связью, инкапсуляцией, наследованием и полиморфизмом. Не все языки поддерживают полиморфизм в одинаковой степени (функция, метод, перегрузка / переопределение операторов).

Если вы хотите лучше понять, как правильно использовать архитектуру MVC, обратитесь к GoF «Шаблоны проектирования: элементы многоразового использования ... Программное обеспечение», которое использует, например, C ++ и SmallTalk. Эта книга не альфа и омега, но это, безусловно, начало!

Удачи!

Чарльз Аддис
источник
1

Я предполагаю, что ваш пример превратится в сложную систему.

Заявка:

Пользователь входит в систему:

  • LoginController

Его единственная обязанность - обрабатывать логины, перенаправлять или уведомлять пользователя о результате.

Загрузить файл

  • UploadController

Я предполагаю, что вы хотите загрузить любой тип файла. Если позднее вы решите загрузить MP3 и PDF, у меня будут базовый UploadController, MP3UploadController и PDFUploadController.

Поиск файла.

  • SearchFileController

Этого будет достаточно для основного требования. Позже вы можете иметь несколько контроллеров поиска в зависимости от сложности логики поиска. Последнее, что вам нужно - это отдельный SearchController с 20 методами действий, выполняющими разные поиски.

Выйти.

-LogoutController .

Кто-то может считать это излишним, но я не думаю, что это так. Я думаю, что это чисто и красиво отделено.

Если бы я взглянул на эту структуру проекта, я бы сразу узнал, что она делает и как она структурирована. Чтобы сделать это еще дальше, я бы поставил LoginControllerи LogoutControllerв отдельную область.

Я разработал что-то подобное раньше, и это сработало очень хорошо.

CodeART
источник
Спасибо за вклад! Есть какой-нибудь рабочий код? застрять на несколько вещей.
Джефф
Какие проблемы вы испытываете?
CodeART
Я могу загрузить тему и дату (в строковом формате), но не могу загрузить сам файл (см. Stackoverflow.com/questions/18344614/… ).
Джефф
Я разработчик .NET. Извините, я не могу вам помочь.
CodeART
1

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

Не совсем уверен, что я фанат разделения контроллеров на подтипы. Хотя вы должны поддерживать разделение проблем, я думаю, что подтипы зашли слишком далеко. Также вы должны быть осторожны в случаях, когда тяжелые объекты инициализируются в конструкторе или контроллере. Например: в вашем примере вы хотели бы, чтобы тяжелый объект, используемый только для поиска / загрузки файла, был выпущен, когда пользователь находится на странице входа в систему.

Лучше иметь контроллер для каждой логической единицы, например AccountController (вход в систему, регистрация, выход из системы), FileController (поиск, загрузка) и так далее.

Харша
источник
0

В общем, вы можете сказать, что у каждой МОДЕЛИ есть свои КОНТРОЛЛЕРЫ и специальные ВИДЫ. Под общим словом я подразумеваю, что это лучшая практика.

Аспекты приложения (например, управление пользователями) должны быть переведены в службу приложения и должны вызываться самим контроллером или для обертывания вашего контроллера (используя атрибуты, которые делают функциональность контроллера «видимой», например, согласно роли пользователя запроса).

Помните, что все контроллеры должны в основном обрабатывать операции CRUD над моделью и использовать разные представления для разных фильтров.

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

О примере, который вы добавили: я бы создал 2 контроллера: один для всех операций входа пользователя (регистрация, вход в систему, выход из системы и т. Д.), А второй для файловых операций (загрузка и поиск). обратите внимание, что первый также должен быть зарезервирован с некоторым аспектом, связанным с функциональностью входа в систему, а второй - обычный контроллер

Сатурн Технологии
источник
без объяснения этот ответ может стать бесполезным в случае, если кто-то постит противоположное мнение. Например, если кто-то публикует утверждение типа «Управление ролями пользователей и авторизация не должны быть в верхней части контроллера» , как этот ответ поможет читателю выбрать два противоположных мнения? Подумайте об изменении его в лучшую форму
комнат
1
@gnat Я принимаю ваш комментарий, смотрите отредактированный ответ
Saturn Technologies