Как стать автором
Обновить

Комментарии 63

ну если использовать в MVC частичные шаблоны видов и репозитории, то большая часть описанных проблем исчезает сама по себе. А можно еще использовать серверную часть, например WCF на C#…
На практике обычно приходиться оперировать одновременно несколькими моделями, например: статьи, пользователи, комментарии. В принципе, это не критично, паттерн MVC это предусматривает, но это увеличивает количество зависимостей — вид и контроллер зависят более чем от одной модели, а от одной модели зависят более одного вида и контроллера.

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

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

В asp.net MVC это решается либо т.н. display templates, которые являются специализированными представлениями, предназначенными для однообразного отображения одних и и тех же моделей, либо просто хелперами, которые это отрисовывают. И опять-таки, никакой проблемы в этом нет, повторное использование подразумевает зависимость.

Иногда действия надо выполнить не над одной моделью, а над несколькими одновременно. Например, при удалении пользователя надо удалить все его статьи и комментарии. В результате приходится создавать контроллер, который описывает операции не только над моделью к которой он относится (в примере — пользователи), но над моделями к которым непосредственного отношения он не имеет.

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

В общем, ваши примеры «зачем это надо» пока как-то не убедили.
HMVC придумал не я, я лишь описал свои размешления о нем на основе своего личного опыта для того, чтобы те, кто впервые столкнулись с термином смогли понять зачем оно надо и с чем его есть.
Статью тоже не вы написали? Вот из нее пока (лично мне) не понятно, зачем оно надо.
MVC по первах тоже отвергали. Как и много других новшеств. Но я не пытаюсь никого убедить строить свои приложения на HMVC. Лишь делюсь тем, что мне бы в свое время очень помогло.
HMVC никто не отвергает, наоборот его уже достаточно давно используют и при том довольно удачно. Но вот пример с удалением неверен. За удаление и вообще управление данными должен отвечать не контроллер а сервисный слой. Контроллер должен только руководить, говорить что делать, а как это уже дело бизнес-логики.
Я согласен с тем, что по хорошему, большую часть логики работы с данными надо вообще возложить на СУБД. Но в случае когда веб-приложение должно иметь возможность работать на разных СУБД, это становиться крейне сложной задачей, и на нее возлагають исключительно хранение данных, а всю логику обеспечивает приложение. А сервисный слой должен обеспечить фреймворк, хорошо если это так, но мне пока такое не попадалось, в лучшем случае возможность организовать такое самому. Вероятно проблема в том, что я пишу на PHP.

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

Конечно, нет. Сервисный (он же прикладной) слой обеспечивает разработчик.
Сервисный (он же прикладной) слой обеспечивает разработчик.

Абсолютно согласен. Но дело ведь в том, что под сервисным слоем все подразумевают разное… Я имею ввиду набор классов, которые реализуют безнесс логику. Их можно дергать как угодно и откуда угодно. Хоть в контроллеры инжектировать.
Я под сервисным слоем понимаю системный класс обеспечивающий специфическое поведение. Как протостой случай, например, сервис обеспечивающий правильное функционирование деревьев. А то, что реализует логику — это модель (иногда это еще называется математическая модель, если она не просто хранит данные, а моделирует поведение объекта).
А то, что реализует логику — это модель

В рамках разговора о MVC это некорректное разделение.
За ссылку спасибо. Но именно из-за таких объяснений я и решился на написание данной статьи — чтобы показать а зачем оно нам надо и как это выглядит в жизни. Таков мой склад ума — из фрагмента программного кода я больше пойму чем из таких объяснений.
Я вас прекрасно понимаю, но все же терминологию кодом не рассказать. Суть в том что hmvc не предназначена для решения проблем описанных в статье (во всяком случае вопрос с удалением пользователей никак не относится к hmvc).
Все примеры — простейшие которые мне удалось придумать. Они предназначены только для того, чтобы без сложных теоретических соображений показать о чем речь.
А для решения каких именно проблем использовать HMVC — выбирать каждому самому.
У меня пока не возникало необходимости масштабировать приложение, а вот максимально изолировать подсистемы — да (последний раз их было более 20)
Масштабировать приложение в контексте вопроса означает расширять функционал, думаю вы сталкивались с этим. Как раз для упрощения этого и нужна изоляция.
Извините, не уточнил, во всех статьях о масштабировании веб-приложения при помощи HMVC говорилось не об увеличении функционала, а о масштабировании аппаратоной части — а именно о добавлении серверов: как пример, разнос веб-сервера и сервера БД. HMVC позволяет с минимальными затратами разнести по разным серверам и функционал приложения.
А вот теперь продемонстрируйте, чем изоляция подсистем через HMVC лучше изоляции через «традиционные» для ООП способы (например, интерфейсы и фасады).
Я не утверждаю, что HMVC лучше или хуже чего-либо.
В контексте данной статьи:
1. HMVC позволяет использовать http-кеширование, и таким образом снизить нагрузку на веб-сервер, а в некоторых случаях вообще исключить некоторые запросы за счет извлечения данных из кеша браузера.
2. HMVC позволяет при необходимости разнести части приложения на разные сервера. Именно такое масштабирование обычно подразумевается когда говорят о HMVC.
Вы так говорите, будто другие решения этого не позволяют.

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

Еще раз повторюсь, я всего лишь пытался показать как же работает HMVC в вебе, поскольку вот это определение лично мне ни о чем не говорит:
Согласно парадигме HMVC, каждая отдельная MVC триада используется в качестве слоя в иерархической структуре. При этом, каждая триада в этой иерархии независима от других, и может обратиться к контроллеру другой триады. Такой подход существенно облегчает и ускоряет разработку сложных приложений, облегчает их дальнейшую поддержку и масштабирование, способствует повторному использованию кода.
Если вы прочитаете вот этот коммент: habrahabr.ru/post/212065/#comment_7294763
То там имелся ввиду слой, который будет реализовывать логику. Как его назвать, это совсем другой вопрос. Хоть слой сервисов. Имелось ввиду что именно слой, реализующий бизнес логику или прикладной слой.
возложить на СУБД

Я не говорил про СУБД, вы несколько видимо не понимаете концепцию сервисов в парадигме mvc. По возможности вся логика приложения должна инкапсулироваться в сервисы, причем желательно что бы остальные части приложения знали только о его интерфейсе и завязывались только на него. Это позволяет сделать приложение гибким, заменять компоненты, менять логику…

Фреймворк же должен обеспечить определенные механизмы для минимизации рутинной работы, слои абстракции для работы с запросами, базой данных и т.д. Это то что будут использовать ваши сервисы, причем контроллеры и модели и даже сами сервисы не должны толком знать что внутри использует каждый отдельный сервис.

Суть hmvc именно в простом масштабировании приложения. Скажем у вас есть экшен контроллера, который выводит вам новостную ленту, а вы хотите вывести ее на странице статьи, так что вы просто делаете подзапрос приложения в нужном месте (обычно на уровне представления, если как в symfony) и таким образом избегаете лишней связанности и дублирования кода.
Всё нормально в PHP с сервисами. Просто вместо кода типа
$user = UserTable::loadByPK($id);
foreach ($user->comments as $comment) {
  $comment->delete();
}
$user->delete();

в методе удаления контроллера (если фреймворк/ОРМ не поддерживают каскадное удаление) пишем что-то вроде:
UserService::delete($id);

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

Сервис это не рокет сайенс, а просто обычный класс в общем случае, фасад для какой-то функциональности, которой в модели делать нечего, а в контроллере будет мешать (плюс повторное использование).
Подскажите почему этой функциональности нечего делать в модели.
Я всегда запихивал в модель. Чтобы
$user->delete()
удалял всё каскадно.
Проблемы какие-то надуманные. Занимаясь j2ee ничего подобного не встречал.
Статья не о проблемах MVC, а о том, как использовать HMVC на практике. Проблемы приведены лишь для того, чтобы показать, а чем не угодил MVC и зачем все усложнять.
На счет надуманости, то увелиличение количества зависимостей проблема вовсе не надуманная, большинство паттернов придуманы для решения именно этой проблемы.
А где вы реализуете бизнес логику приложения? Если у Вас толстые контроллеры, то понятно откуда ноги растут. Но ведь никто не мешает Вам перенести побольше логики в модель. Или реализовать слой аля неких сервисов, возложить на них всю реализацию бизнесс логики, а модель и контроллеры сделать тонкими.
Я приверженец толстой модели и тонкого контроллера, а еще лучше логику в СУБД засунуть. Но работать приходится с тем что есть, а есть Symfony 2, о котором Фабиан написал, что ему не нравиться MVC, и теперь там формально нет моделей, а есть только репозитарии которые могут только хранить данные. Зато есть сервисы, и да, с их помощью можно организовать все что угодно. А еще есть все необходимое для организации HMVC, первый раз который я огранизовал даже не подозревая об этом. Еще есть CMS Joomla, в ней есть класический MVC и возможность организовать толстую модель, но нет сервисов. А вообще озадачился исследованием HMVC после того как ее разработчики начали переделывать встроенную MVC и написали что в планах HMVC.
еще лучше логику в СУБД засунуть.

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

Это грустно…

Зато есть сервисы, и да, с их помощью можно организовать все что угодно.
Я не имел ввиду конкретно какие либо сервисы. Я имел ввиду слой, который можно назвать хоть сервисы, хоть менеджеры, хоть реализаторы бизнес лоигки.
Я о том же. Cервисом в Symfony может быть все что угодно: менеджер объектов, контроллер, или целая подсистема.
Я понятия не имею что у Вас там с Symfony. Но вот если вы имеете ввиду тоже что и я, то вот это высказывание:
Еще есть CMS Joomla, в ней есть класический MVC и возможность организовать толстую модель, но нет сервисов.
теряет всякий смысл.
и теперь там формально нет моделей,

А куда они делись? O_o Что из репозитория приходит как не модель?
Не хочу об этом спорить. Лучше сами прочитайте что Фабиан об этом пишет: fabien.potencier.org/article/49/what-is-symfony2
Раздел «Is Symfony2 an MVC framework?»
Тем не менее на Symfony можно строить и MVC и HMVC (из коробки) и много чего еще
Все таки я не понимаю почему Вы сводите все к Symfony? Почему он вообще появился в обсуждении? Я вот люблю Asp.net MVC для .Net и Flask для Python. Но разговор ведь не о конкретной реализации, а о паттерне в целом? Или я чего то не понимаю? :(
Я не понимаю почему вообще обсуждение свелось к тому, на сколько я правильно дал обоснование применению HMVC. Я лишь хотел на элементарных примерах показать, зачем усложнять MVC, для многих и он слишком сложен.
Если уж на то пошло, то школьные учебники по физике и химии давно надо было выбросить в топку — там все неправильно.
Ну так Symfony 2 даёт полную свободу в реализации моделей, если есть желание следовать MVC. Если вы говорите про репозитории, то скорее всего имеете в виду Doctrine 2, которая предназначена для маппинга базы данных на объекты и эти объекты и есть модель в общепринятой трактовке.
Не хочу об этом спорить. Лучше сами прочитайте что Фабиан об этом пишет: fabien.potencier.org/article/49/what-is-symfony2
Раздел «Is Symfony2 an MVC framework?»
Тем не менее на Symfony можно строить и MVC и HMVC (из коробки) и много чего еще.
Не понимаю, почему все бросились обсуждать обоснование использования HMVC, хотя статья всего-лишь пытается наглядно показать как он в реальной жизни используется в веб-работке.
Вероятно, потому, что ваша статья оказалась не такой наглядной, как вам бы того хотелось.
Надеюсь все же нагляднее вот этого определения:
Согласно парадигме HMVC, каждая отдельная MVC триада используется в качестве слоя в иерархической структуре. При этом, каждая триада в этой иерархии независима от других, и может обратиться к контроллеру другой триады. Такой подход существенно облегчает и ускоряет разработку сложных приложений, облегчает их дальнейшую поддержку и масштабирование, способствует повторному использованию кода.
Нет, не нагляднее. У вас вообще иерархии не видно.
На 3-й, 4-й и 5-й илюстрациях покаханы иерархии.
Лично для меня приведенное объяснение (взято из Википедии) говорит не больше чем то, что это иерархический MVC (дальше можно было и не писать).
Это не иерархии, это направление запросов. В иерархиях есть (четко определенные) верхний и нижний уровень. А у вас направление движения произвольно.
Мне паттерн HMVC всегда виделся несколько иначе — так, как он был описан у Мартина Фаулера — контроллер более высокого уровня взаимодействует с контроллерами более низкого уровня, а те уже — в свою очередь — с моделью и представлением.
Можете ознакопиться с первоисточником (публикиция 2000-года которая считается первым упоминанием HMVC)
www.javaworld.com/article/2076128/design-patterns/hmvc--the-layered-pattern-for-developing-strong-client-tiers.html
Там показаны именно триады, которые иерархически связаны, а через контроллеры они взаимодействуют.
Так и в указанном Вами первоисточнике — все именно так, как я говорю: контроллеры иерархически связаны между собой. Связи — стрелки именно от контроллера к контроллеру идут.
В таком случае, мы друг-друга не правильно поняли. По вашему описанию получается, что у контроллеров высокого уровня нет своих моделей и видов, а это не так, они есть. Что касается взаимодейсвия, то принимать запросы должны исключительно контроллеры (в этом вся суть), отправлять их должны так же они, но если это сделает модель или вид, ничего страшного не произойдет. Может даже и лучше, если некоторые запросы будет оправлять не контроллер, потому что тогда он станет толстым, и ему придется знать о том, о чем ему не положено.
Тогда будет нарушаться иерархия. Вассал моего вассала не мой вассал. Модель и вид не должны знать о других контроллерах. Модель может знать о других моделях, вид о других видах, контроллер о других контроллерах, моделях и видах в обычном MVC и только о других контроллерах в HMVC.
В идеале, в MVC контроллер, модель и вид должны знать только друг о друге. Допустимо, чтобы модели знали друг о друге. Но на практике очень часто связей значительно больше. В HMVC в иделале друг о друге должны знать только контроллеры, и только о тех, которые в иерархии находяться на 1 уровень ниже (напрямую подчинены). Однако не случится ничего страшного, если о нижестоящем контроллере будут знать модель и вид. Иерархия при этом сохранится. Подчиненным контроллерам должно быть все равно от кого пришел запрос.
Модели как-то совсем неправильно знать о контроллере, разве что он сделан как сервис.
В данном случае, контроллер, по сути, выступает для модели сервисом.
Кто-то мне объяснит, что такого ужасного я написал в этом посте что каждый хаброжитель считает своим должгом поставить минус?
Так вам в комментах уже написали.
Т.е. минусовать можно просто из-за несогласия с мнением?
Я считал нормальным ставить минусы за оффтоп, оскорбление, и т.п.
Не скажу за данный случай, но часто минусуют неправильное мнение, неправильное употребление терминологии и т. п., чтобы показать другим, что на инфу в комменте внимания обращать не нужно, что она повредит если ею руководствоватьсся.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.