В Ruby on Rails Development (или MVC в целом), какое быстрое правило я должен следовать относительно того, куда поместить логику.
Пожалуйста, ответьте утвердительно: « Сделай это, поставь здесь» , а не « Не ставь» .
В Ruby on Rails Development (или MVC в целом), какое быстрое правило я должен следовать относительно того, куда поместить логику.
Пожалуйста, ответьте утвердительно: « Сделай это, поставь здесь» , а не « Не ставь» .
Ответы:
MVC
Контроллер : поместите здесь код, который связан с разработкой того, что хочет пользователь, и решением, что ему дать, выяснением, вошли ли они в систему, должны ли они видеть определенные данные и т. Д. В конце контроллер смотрит на запросы и определяет, какие данные (модели) отображать и какие представления отображать. Если вы сомневаетесь в том, должен ли код идти в контроллере, то, вероятно, этого не должно быть. Держите свои контроллеры худыми .
Представление : представление должно содержать только минимальный код для отображения ваших данных (модель), оно не должно выполнять большую обработку или вычисление, оно должно отображать данные, рассчитанные (или обобщенные) моделью или сгенерированные из контроллера. Если вашему представлению действительно требуется выполнить обработку, которую не может выполнить модель или контроллер, поместите код в помощник. Много Ruby-кода в представлении делает разметку страниц трудной для чтения.
Модель . Ваша модель должна соответствовать тому, где живет весь ваш код, связанный с вашими данными (сущности, составляющие ваш сайт, например, пользователи, почта, учетные записи, друзья и т. Д.). Если код должен сохранять, обновлять или суммировать данные, связанные с вашими сущностями, поместите его здесь. Он будет многократно использоваться в ваших представлениях и контроллерах.
Добавить к ответу Полифоника:
Помощник : функции, облегчающие создание представления. Например, если вы всегда просматриваете список виджетов, чтобы отобразить их цену, поместите его в помощник (вместе с частичным для фактического отображения). Или, если у вас есть кусок RJS, который вы не хотите загромождать видом, поместите его в помощник.
Шаблон MVC действительно касается только пользовательского интерфейса и ничего больше. Не следует помещать в контроллер какую-либо сложную бизнес-логику, поскольку она контролирует представление, но не логику. Контроллер должен заботиться о выборе правильного представления и делегировать более сложные вещи в модель предметной области (Model) или бизнес-уровень.
Домен-управляемый дизайн имеет концепцию сервисов - это место, где вы придерживаетесь логики, которая должна координировать множество различных типов объектов, что обычно означает логику, которая естественно не принадлежит классу модели.
Обычно я считаю уровень сервиса API-интерфейсом своих приложений. Слои моих сервисов обычно очень близко соответствуют требованиям приложения, которое я создаю, таким образом, сервисный слой выступает в качестве упрощения более сложных взаимодействий на нижних уровнях моего приложения, то есть вы можете достичь той же цели, минуя сервисные слои но вам придется потянуть гораздо больше рычагов, чтобы это заработало.
Обратите внимание, что здесь я не говорю о Rails, я говорю об общем архитектурном стиле, который решает вашу конкретную проблему.
Прекрасные объяснения здесь уже, одно очень простое предложение в качестве заключения и легко запомнить:
Нам нужны SMART-модели, THIN-контроллеры и DUMB Views.
Путь Rails состоит в том, чтобы иметь тощие контроллеры и толстые модели .
Поместите вещи, связанные с авторизацией / контролем доступа в контроллер.
Модели все о ваших данных. Валидация, Отношения, CRUD, Бизнес-логика
Представления о показе ваших данных. Отображение и получение только ввода.
Контроллеры предназначены для управления тем, какие данные передаются из вашей модели в ваше представление (и какое представление) и из вашего представления в вашу модель. Контроллеры также могут существовать без моделей.
Мне нравится думать о контроллере как о охраннике / регистраторе, который направляет вас клиента (запрос) к соответствующему счетчику, где вы задаете кассиру (просмотр) вопрос. Затем рассказчик (представление) идет и получает ответ от менеджера (модели), которого вы никогда не видите. Затем вы возвращаетесь к охраннику / администратору (контролеру) и ждете, пока вас направят к другому кассиру (представление), который скажет вам ответ, который менеджер (модель) сказал им в ответ на вопрос другого кассира (представление). ,
Аналогично, если вы хотите сказать кассиру (просмотреть) что-то, то в основном происходит то же самое, за исключением того, что второй кассир скажет вам, принял ли менеджер вашу информацию. Также возможно, что охранник / администратор (контролер), возможно, сказал вам, чтобы вы пошли в поход, так как вы не были уполномочены сообщить менеджеру эту информацию.
Таким образом, чтобы расширить метафору, в моем стереотипном и нереалистичном мире рассказчики (взгляды) симпатичны, но с пустыми головами и часто верят всему, что вы им говорите, охранники / администраторы минимально вежливы, но не очень осведомлены, но они знают, где люди должны и не должны уходить, а менеджеры действительно уродливые и подлые, но знают все и могут сказать, что правда, а что нет.
Одна вещь, которая помогает правильно разделить - это избегать анти-паттерна «передавать локальные переменные из контроллера для просмотра». Вместо этого:
# app/controllers/foos_controller.rb:
class FoosController < ApplicationController
def show
@foo = Foo.find(...)
end
end
#app/views/foos/show.html.erb:
...
<%= @foo.bar %>
...
Попробуйте переместить его в метод получения, который доступен как вспомогательный метод:
# app/controllers/foos_controller.rb:
class FoosController < ApplicationController
helper_method :foo
def show
end
protected
def foo
@foo ||= Foo.find(...)
end
end
#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...
Это облегчает изменение того, что помещается в "@foo" и как оно используется. Это увеличивает разделение между контроллером и представлением, не делая их более сложными.
foo
и из @foo
них одинакова - они оба ограничены парой <ControllerClass, request>. Кроме того, используя версию получателя, я могу изменить способ Foo
обнаружения / хранения / кэширования этого объекта без изменения способа доступа к нему.
Ну, это отчасти зависит от того, с чем связана логика ...
Часто имеет смысл добавлять больше вещей в ваши модели, оставляя контроллеры маленькими. Это гарантирует, что эту логику можно легко использовать из любого места, где вам нужен доступ к данным, которые представляет ваша модель. Представления не должны содержать почти никакой логики. Так что на самом деле, в общем, вы должны стремиться сделать так, чтобы вы не повторяли себя.
Кроме того, быстрый Google показывает еще несколько конкретных примеров того, что и куда.
Модель: требования проверки, отношения данных, методы создания, методы обновления, методы уничтожения, методы поиска (обратите внимание, что у вас должны быть не только общие версии этих методов, но и если вы что-то делаете, например, находите людей с красным волосы по фамилии, тогда вы должны извлечь эту логику, чтобы все, что вам нужно сделать, это вызвать find_redH_by_name ("кузнец") или что-то в этом роде)
Представление: это должно быть все о форматировании данных, а не обработке данных.
Контроллер: здесь идет обработка данных. Из Интернета: «Цель контроллера - ответить на запрошенное пользователем действие, принять любые параметры, которые пользователь установил, обработать данные, взаимодействовать с моделью, а затем передать запрошенные данные в окончательном виде на Посмотреть."
Надеюсь, это поможет.
Проще говоря, как правило, модели будут иметь все коды, связанные с таблицами, их простыми или сложными отношениями (представьте их как SQL-запросы, включающие несколько таблиц), манипулирование данными / переменными для получения результата с использованием бизнес-логики. ,
Контроллеры будут иметь код / указатели на соответствующие модели для запрашиваемой работы.
Представления будут принимать пользовательский ввод / взаимодействие и отображать полученный ответ.
Любое существенное отклонение от этого создаст нежелательную нагрузку на эту часть, и это может повлиять на общую производительность приложения.
Тестирование, тестирование ... Поместите в модель как можно больше логики, и тогда вы сможете правильно ее протестировать. Модульные тесты проверяют данные и способ их формирования путем тестирования модели, а функциональные тесты проверяют способ ее маршрутизации или управления с помощью тестирования контроллеров, поэтому из этого следует, что вы не можете проверить целостность данных, если они не находятся в модель.
J