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

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

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

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

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

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

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

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

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

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

Вид : «Эй, controller, пользователь просто сказал мне, что хочет удалить элемент 4».
Контроллер : «Хм, проверив свои верительные грамоты, он может это сделать … Эй, модель, я хочу, чтобы вы получили пункт 4 и делаете все, что вы делаете, чтобы удалить его».
Модель : «Пункт 4 … получил его, он удален. Вернемся к вам, Контролер».
Контроллер : «Здесь я собираю новый dataset. Вернуться к вам, просмотрите».
Вид : «Круто, теперь я покажу новый набор для пользователя».

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

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

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

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

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

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

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

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

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

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

… следует ли проводить проверку и т. д. в controllerе? Если да, то как мне возвращать сообщения об ошибках обратно в представление – должно ли это снова проходить через модель или же controller должен просто отправить ее обратно в режим просмотра?

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

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

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

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

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

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

Говорится …

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

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

В Фаулере есть еще одна хорошая статья .

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

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

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

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

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

«Если да, то должны ли быть какие-либо проверки и т. Д. В Контроллере?»

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

«Если да, то как мне возвращать сообщения об ошибках обратно в представление – должно ли это снова проходить через модель или если controller просто вернет ее обратно в« Просмотр »?»

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

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

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

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

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

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

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

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

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

Ориентирован на обслуживание: это то, где работа выполнена.

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

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

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

 public void actionPerformed(ActionEvent e) 

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

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

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

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

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

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

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

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

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

В любом случае, правильная реализация MVC будет иметь только следующие взаимодействия: Model -> View View -> Controller Controller -> View

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

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

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

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

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

-> handleSubmit_AddNewCustomer ()

-> verifyUser_HasProperAuth ()

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

-> sanityCheck_AddNewCustomer ()

-> handleUsernameChange ()

-> sendEmail_NotifyRequestedUpdate ()

(3) (представления, порталы, как появляется веб-приложение «)» Blog_View

-> genWelcome ()

-> genForm_AddNewBlogEntry ()

-> genPage_DataEntryForm ()

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

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

-> saveDataToMemcache ()

-> saveDataToMongo ()

-> saveDataToSql ()

-> LoadData ()

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

  • Как выполняется дифференциальное выполнение?
  • Является MVC в Swing Thread Safe
  • Уровень обслуживания JSF
  • Должен ли я получить запись базы данных на уровне слоев Struts2?
  • Дата проверки валидации продолжается
  • Что использовать? MVC, MVP или MVVM или ...?
  • Показать JDBC ResultSet в HTML на странице JSP с использованием шаблонов MVC и DAO
  • RESTeasy и возврат на страницу JSP с моделью
  • MVC Progress Bar Threading
  • Шаблон MVC и SWING
  • OWIN - Authentication.SignOut (), похоже, не удаляет файл cookie
  • Давайте будем гением компьютера.