Навеяно топиком о смерти MVC.
Чтобы разобраться в том, что происходит, давайте пойдем от принципов ООП.
Класс объектов в ООП инкапсулирует данные объекта с его поведением.
Вся сложность в разделении предметной области на объекты.
Здесь под «предметной областью» я понимаю также техническое окружение (БД, сеть и т.д.)
Распространенной практикой в наши дни стало создание легковесных POJO-объектов и их proxy, нам которыми работает некоторая логика, разнесенная по всем частям MVC (по M, V и C соответственно).
Это удобно с точки зрения реализации различных технологий для M, V и C частей приложения соответственно. На выходе имеем M-framefork'и, V-framefork'и и C-framefork'и (иногда наблюдается смешение). В этой парадигме переносить логику в POJO-классы модели, которые отражаются (mapping) на БД, было бы самоубийством.
Какие у нас есть альтернативы?
Давайте пойдем из принципа, что объекты в ООП инкапсулирует данные объекта с его поведением. А также воспользуемся принципом единой ответственности.
«Что из этого следует? Переносить код работы с БД в сущности?» Конечно, нет.
Давайте разберемся. Эти самые POJO -объекты на самом деле несут четко определенную семантику — маппинг сущностей БД. Однако называть их классами некорректно. С точки зрения ООП это, скорее, просто структуры данных. И get/set методы тут не нужны — это просто слепок данных.
Это сбивает с толку. А где же тогда ООП? Давайте исходить из предметной области, а именно из операций, действий пользователя. Во-первых оставим view из MVC на своем месте — с ним более-менее все понятно, и вопросов обычно не возникает. Остается M и C. Что есть что?
Почти в любом web-приложении (рассмотрим web для примера, ладно? Остальное по аналогии) есть работа с внешним источником данных, интеграция с внешними системами как на вход, так и на выход, а также request/response-парадагма. Логично, что request и response у нас хорошо заворачиваются в объекты, этот путь давно пройден. Так же есть внешний (технический) интерфейс для внешней системы как на вход, так и на выход. Т.е. эти классы и объекты считаем уже определившимися. Также учтем удобство декларативного стиля.
Итак, допустим, у нас есть операция. допустим, один request. Диспетчер по шаблонам и данным определит конечный обработчик. Причем именно конечный — все ветвления, зависимые от структуры URL, привилегий и переданных данных должны быть сделаны диспетчером. При этом диспетчер может частично обеспечиваться framework'ом — но практически никогда полностью. Итак, диспетчер выделили, жестко отделили от остальной логики. При этом он оперирует либо данными запроса, либо объектами сущностей, т.е. структурами данных.
Далее происходит обработка запроса. Любую операцию можно разбить на примитивные CRUD-компоненты, выполняемые по различным условиям. Вопрос: а является ли операция объектом? Операция — это взаимодействие объектов. У нее нет своих данных — она их заимствует. Она обеспечивает взаимодействие объектов, которые сами по себе пассивны. А пассивны они потому, что ни одному из них не хватает знаний, чтобы выполнить операцию. Следовательно, нам нужен посредник, который примет на себя ответственность за взаимодействие объектов. Это НЕ контроллер. Это НЕ модель. Это другой паттерн.
А как же быть с M и C? Контроллер должен вызвать операцию и по ее результатам выбрать view для отображения. Вся логика уходит в операцию. А где же модель? Модель должна информировать view об изменениях, должна изменяться контроллером… Модель у нас — это БД. Сама БД является моделью. Причем без нотификации view. В web-разработке у нас ни один компонент не обновляет view по событиям от модели. Мы строим view на основании данных, полученных после выполнения операции.
Так MVC ли это?
В каконическом виде — нет. В web'е работает другой паттерн, где модель пассивна.
Не буду спорить о названиях, но структура взаимодействия и роли здесь другие.
А можно ли сделать полноценный MVC?
На эту тему, думаю, нужно написать отдельную статью.
Автор: Colwin