Что входит в "Контроллер" в "MVC"?

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

Давайте скажем, например, у меня довольно простое приложение (я специально думаю о Java, но я полагаю, что одни и те же принципы применяются в другом месте). Я организовываю свой код в 3 пакета под названием app.model, app.view и app.controller.

В пакете app.model у меня есть несколько классов, которые отражают фактическое поведение приложения. Эти extends Observable и используйте setChanged() и notifyObservers(), чтобы инициировать просмотр, когда это необходимо.

Пакет app.view имеет класс (или несколько классов для разных типов отображения), который использует компоненты javax.swing для обработки отображения. Некоторые из этих компонентов должны возвращаться в Модель. Если я правильно понимаю, представление не должно иметь ничего общего с обратной связью - это должно решаться контроллером.

Итак, что я на самом деле положил в контроллер? Я помещаю public void actionPerformed(ActionEvent e) в представление только с вызовом метода в контроллере? Если да, то должны ли быть какие-либо проверки и т.д. В контроллере? Если да, то как мне возвращать сообщения об ошибках обратно в представление - должно ли оно снова пройти через модель или контроллер должен просто отправить его обратно в режим просмотра?

Если проверка выполняется в представлении, что я помещаю в контроллер?

Извините за длинный вопрос, я просто хотел документировать свое понимание процесса и, надеюсь, кто-то может прояснить эту проблему для меня!

Ответ 1

В примере, который вы предложили, вы правы: "пользователь нажал кнопку" удалить этот элемент "в интерфейсе, в основном просто вызовет функцию" удалить "контроллера. Однако контроллер не имеет представления о том, как выглядит представление, и поэтому ваше представление должно собирать некоторую информацию, например," какой элемент был нажат?"

В форме беседы:

Просмотр: "Эй, контроллер, пользователь просто сказал мне, что хочет удалить элемент 4".

Контроллер: "Хм, проверив свои учетные данные, он может это сделать... Эй, модель, я хочу, чтобы вы получили пункт 4 и делаете все, что вы делаете, чтобы удалить его".
Модель: "Пункт 4... получил его, он удалил. Вернуться к вам, Контроллер".

Контроллер: "Здесь я собираю новый набор данных. Вернуться к вам, просмотрите".
Просмотр: "Круто, теперь я покажу новый набор пользователю".

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

Ответ 2

Проблема с MVC заключается в том, что люди считают, что представление, контроллер и модель должны быть как можно более независимыми друг от друга. Они не видят, что просмотр и контроллер часто переплетаются - подумайте об этом как M(VC).

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

Подумайте о радиоуправляемом роботе в поле обнаружения в закрытой коробке в качестве модели.

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

Подумайте о представлении без контроллера, например. кто-то в другой комнате в сети в другой комнате наблюдает за положением робота, так как (x, y) координирует поток вниз по прокручивающей консоли. Это представление просто отображает состояние модели, но у этого парня нет контроллера. Опять же, легко представить это представление без контроллера.

Подумайте о контроллере без вида, например. кто-то запер в шкафу с радиоконтроллером, настроенным на частоту робота. Этот контроллер отправляет входные данные и вызывает переходы состояния, не имея представления о том, что они делают с моделью (если есть). Легко представить, но не очень полезно без какой-либо обратной связи от представления.

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

Отвечал ли я на ваш вопрос?: -)

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

... если какая-либо проверка и т.д. сделано в контроллере? Если да, то каким образом Я возвращаю сообщения об ошибках обратно Вид - должен пройти через Модель снова, или контроллер должен просто отправьте его прямо на просмотр?

Если проверка выполняется в представлении, что я помещаю в контроллер?

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

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

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

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

Ответ 3

Вот хорошая статья об основах MVC.

В нем указано...

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

Другими словами, ваша бизнес-логика. Контроллер реагирует на действия пользователя, сделанные в представлении и отвечающие. Вы ставите валидацию здесь и выбираете соответствующий вид, если проверка не выполняется или не удается (страница ошибки, окно сообщения, что угодно).

В Fowler есть еще одна хорошая статья .

Ответ 4

Шаблон MVC просто хочет, чтобы вы отделили презентацию (= вид) от логики построения (= model). Часть контроллера есть только для того, чтобы вызвать путаницу.

Ответ 5

По вашему вопросу у меня создается впечатление, что вы немного туманны в роли Модели. Модель фиксируется на данных, связанных с приложением; если приложение имеет базу данных, то задание модели должно будет поговорить с ним. Он также будет обрабатывать любую простую логику, связанную с этими данными; если у вас есть правило, в котором говорится, что для всех случаев, когда TABLE.foo == "Ура!" и TABLE.bar == "Хузза!" затем установите TABLE.field = "W00t!", тогда вы хотите, чтобы модель позаботилась об этом.

Контроллер - это то, что должно обрабатывать основную часть поведения приложения. Поэтому, чтобы ответить на ваши вопросы:

"Я помещаю public void actionPerformed (ActionEvent e) в представление только с вызовом метода в контроллере?"

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

"Если да, то должны ли выполняться какие-либо проверки и т.д. в контроллере?"

Основная часть вашей проверки действительно должна выполняться Контролером; он должен ответить на вопрос о том, действительны ли данные, а если нет, подавать соответствующие сообщения об ошибках в представление. На практике вы можете включить некоторые простые проверки здравомыслия в слой "Вид", чтобы улучшить работу пользователя. (Я думаю в первую очередь о веб-средах, где вы можете захотеть, чтобы сообщение об ошибке появилось в тот момент, когда пользователь нажимает "Отправить", а не ждет, пока весь процесс отправки → процесс → загрузит страницу, прежде чем сообщить им, что они напортачили.) Просто будь осторожен; вы не хотите дублировать усилия больше, чем вам нужно, и во многих средах (опять же, я думаю о сети) вам часто приходится обрабатывать любые данные, поступающие из пользовательского интерфейса, в виде пакета грязных грязных ложь, пока вы не подтвердите это на самом деле законным.

"Если да, то как мне возвращать сообщения об ошибках обратно в представление - должно ли это снова проходить через модель или контроллер должен просто отправить ее обратно в режим просмотра?"

У вас должен быть установлен какой-то протокол, где View не обязательно знает, что будет дальше, пока контроллер не сообщит об этом. На каком экране вы показываете их после того, как пользователь нажал эту кнопку? Просмотр может не знать, и Контроллер может не знать, пока он не посмотрит на данные, которые он только что получил. Это может быть "Перейдите на другой экран, как и ожидалось" или "Оставайтесь на этом экране и покажите это сообщение об ошибке".

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

"Если проверка выполняется в представлении, что я помещаю в контроллер?"

См. выше; реальная проверка должна быть в контроллере. И, надеюсь, у вас есть представление о том, что должно быть поставлено в Контроллер.: -)

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

Ответ 6

Практически, я никогда не считал концепцию контроллера особенно полезной. Я использую строгое разделение модели/представления в моем коде, но нет четко определенного контроллера. Это кажется ненужной абстракцией.

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

Ответ 7

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

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

Сервисно-ориентированный: это, где выполняется работа.

Ответ 8

Контроллер предназначен в первую очередь для координации между представлением и моделью.

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

Я предлагаю вам поставить:

public void actionPerformed(ActionEvent e)

в контроллере. Затем ваш слушатель действий в вашем представлении должен делегировать контроллер.

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

Я бы определенно рекомендовал взглянуть на пассивный просмотр и надзор за презентатором (что, по сути, разделено на Model View Presenter - по крайней мере, Фаулером). См:

http://www.martinfowler.com/eaaDev/PassiveScreen.html

http://www.martinfowler.com/eaaDev/SupervisingPresenter.html

Ответ 9

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

Я придумал это после работы с крупномасштабным webapp, написанным разработчиками, которые думали, что они поняли MVC, но на самом деле этого не делали. Их "контроллеры" сводятся к восьми линиям вызова статических методов класса, которые больше не называются нигде: -/делают их модели немного больше, чем способы создания пространств имен. Рефакторинг это правильно делает три вещи: сдвигает весь SQL в уровень доступа к данным (aka model), делает код контроллера немного более подробным, но гораздо более понятным и уменьшает старые файлы модели до нуля.: -)

Ответ 10

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

Ответ 11

также отметим, что каждый виджет Swing можно считать содержащим три компонента MVC: у каждого есть модель (например, ButtonModel), представление (BasicButtonUI) и элемент управления (сам JButton).

Ответ 12

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

В любом случае, правильная реализация MVC будет иметь только следующие взаимодействия: Модель → Просмотр Просмотр → Контроллер Контроллер → Просмотр

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

Ответ 13

Мы делаем это, используя контроллеры в основном для обработки и реагирования на пользовательские входные/действия (и _Logic для всего остального, кроме представления, данных и очевидных вещей _Model):

(1) (ответ, реакция - что делает webapp "в ответ на пользователя" ) Blog_Controller

- > Основной()

- > handleSubmit_AddNewCustomer()

- > verifyUser_HasProperAuth()

(2) ( "бизнес-логика", что и как думает webapp ") Blog_Logic

- > sanityCheck_AddNewCustomer()

- > handleUsernameChange()

- > sendEmail_NotifyRequestedUpdate()

(3) (просмотры, порталы, как отображается Webapp ") Blog_View

- > genWelcome()

- > genForm_AddNewBlogEntry()

- > genPage_DataEntryForm()

(4) (только объект данных, полученный в _construct() каждого класса Blog *, используемый для хранения всех данных webapp/inmemory вместе как один объект) Blog_Meta​​p >

(5) (базовый уровень данных, чтение/запись в БД) Blog_Model

- > saveDataToMemcache()

- > saveDataToMongo()

- > saveDataToSql()

- > LoadData()

Иногда мы немного путаемся с тем, где положить метод, в C или L. Но модель прочная, кристально чистая, и поскольку все данные в памяти находятся в _Meta, это не проблема там тоже. Наш самый большой шаг вперед заключался в использовании использования _Meta, кстати, поскольку это очистило всю руду от различных объектов _C, _L и _Model, сделало все это умственно легким в управлении, плюс одним махом, это дало нам то, что было "Инъекция зависимостей" или способ передачи всей среды вместе со всеми данными (чей бонус - простое создание "тестовой" среды).