Статьи

Основы MVC в Rails: все тощие

head1

Model-View-Controller (MVC) — это шаблон проектирования для структурирования программных систем. Шаблон MVC отделяет логику приложения от пользовательского интерфейса. MVC означает Model, View и Controller, три основных компонента архитектуры веб-приложений MVC. Каждый из этих компонентов должен работать как отдельные блоки. Дискретная природа компонентов MVC имеет решающее значение для обслуживания и тестирования приложений.

Мы часто слышим, что лучший способ написать ясный и лаконичный код в Rails — это следовать подходу «Толстые модели и тощие контроллеры», который относится к тому, как модель и контроллер в архитектуре MVC должны идеально работать вместе. Наличие «тощего» контроллера (что является обычной практикой) означает, что вся некритическая логика перемещается в модель; это упрощает тестирование и обслуживание. Тем не менее, мы рекомендуем сделать «тощий» подход еще на шаг вперед: сядьте на диету и ваших моделей, и ваших контроллеров. Часто мы фокусируемся на моделях и контроллерах, но как насчет View? Представление также может быть «толстым», и на самом деле мы считаем, что представление также должно придерживаться диеты.

Какова функция каждого компонента MVC?

image00

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

модели

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

Например, предположим, что пользователь хочет зарегистрироваться. Для этого они должны ввести свой адрес электронной почты, имя пользователя и пароль. Все эти атрибуты принимаются контроллером, который пытается создать нового пользователя (в архитектуре MVC этот пользователь концептуализируется как «запись модели»). Модель выполняет проверки: она проверяет, имеет ли введенный адрес электронной почты правильный формат, достаточно ли надежен пароль и уникальны ли адрес электронной почты и логин. Если проверка прошла успешно, Модель затем сохраняет данные в базе данных и after_save обратный вызов after_save . Примером обратного вызова является уведомление по электронной почте, которое отправляется зарегистрированному пользователю и администратору. Если проверка не пройдена, Модель возвращает объект ошибки, который можно отобразить и показать пользователю.

Контроллеры

Контроллеры несут ответственность за чтение входных данных (запросов), выбор соответствующих действий (бизнес-действий) и возврат итоговых выходных данных (ответов).

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

  • Аутентификация, когда Контроллер проверяет, работает ли вошедший в систему пользователь с приложением в данный момент.
  • Авторизация, когда Контроллер проверяет, авторизован ли пользователь для выполнения действия
  • Фильтрация входных параметров ( permitted_attributes ), когда контроллер действия предоставляет интерфейс для защиты атрибутов от назначения конечным пользователем.
  • Вызывает методы в моделях или сервисах.
  • Определяет, какой формат предоставлять информацию клиенту (JSON, HTML, PDF, XML) и выбирает правильный вид.

Взгляды

Представление — это визуализация присоединенного состояния модели. Проще говоря, представление — это то, что видит пользователь. Это единственный компонент MVC, с которым пользователи взаимодействуют напрямую.

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

Что произойдет, если компонент MVC кто-то еще работает?

  • Сложно поддерживать код в тех случаях, когда контроллер содержит большие методы, выполняющие несвязанные действия.
  • Тестирование становится практически невозможным, поскольку написание модульных тестов означает тестирование конкретных классов и модулей, отвечающих за определенные функции. Трудно отследить цепочку вызовов методов в «коде спагетти» (запутанный код, который включает в себя множество неструктурированных и сложных объектов и методов).
  • Каждый класс должен нести ответственность за одну часть всей функциональности, предоставляемой программным обеспечением. Но часто Контроллеры начинают включать бизнес-логику, которая не принадлежит, или даже формы логики View. В конечном итоге модель может содержать логику, не связанную с постоянством, а представления могут содержать вычисления, которые вообще не приветствуются.

Основное правило, которого мы должны придерживаться, чтобы избежать жирных компонентов MVC, сводится к следующему: «Каждый должен заниматься своим делом».

Как сделать компоненты MVC тонкими?

Чтобы получить тощие модели, представления и контроллеры, мы должны постоянно проводить рефакторинг. Рефакторинг — это процесс реструктуризации существующего кода. Хотя рефакторинг ничего не меняет с точки зрения конечного пользователя, он помогает поддерживать чистоту, удобство сопровождения и простоту тестирования, что полезно для разработчиков.

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

Мы можем использовать различные шаблоны проектирования, чтобы помочь нам в процессе рефакторинга, в том числе:

  • Сервисные объекты (и объекты Interactor)
  • Объекты значения
  • Объекты формы
  • Объекты запроса
  • Просмотр объектов (сериализатор / ведущий)
  • Объекты политики
  • Декораторы

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