Pull to refresh

Comments 28

>нет способа изолировать engine от запросов из внешеного мира (каждый может сделать запрос к FooController напрямую);
ИМХО это плюс.
Это вопрос инкапсуляции. Хорошо ли то, что в Ruby мы имеем доступ к private методам? С точки зрения ООП — плохо.
Если выгрузить приложение на нормальный сервер, то по идее в логах будет 127.0.0.1 только для внутреннего вызова, так можно и фильтровать логи и защитить от внешних вызовов. Но вообще что-то мне идея реализации HMVC через полноценные HTTP запросы не очень нравится, даже если необходим доступ к отдельным триадам извне.
Тогда не получится разбить приложение на несколько машин, для масштабирования, например.
Чтобы часть запроса исполнялась на одном сервере, а часть на другом? Насколько это востребовано?
А насколько было востребовано ООП, когда оно не было популярным? HMVC — это новая парадигма и она требует другой подход к проектированию.
Я HMVC рассматриваю прежде всего как средство логической декомпозиции, но не физической.
Ты сейчас суть вопроса затронул! Rails, внутренние http-запросы — это все конкретная реализация. Одна из — не более. Можно использовать что угодно.

Но конкретно в данной реализации важно, что в каждом MVC-компоненте мы работаем с обычным rails-приложением, в котором явно выражен каждый из этих M V C.
Почему просто из HomeController не вызывать FooController, не теряя явного выражения M, V и С, но теряя накладные расходы на HTTP?
Теоретически можно создать GoogleController, который крутится на сервере гугла, и отвечает на поисковые запросы.
Понятно, что это будет медленно, зато возможно.
Если речь идёт о крупном приложении вроде Github, появляется возможность контроллер blog вывести на другую машину (хотя это итак можно средствами того же nginx, но не суть), разгрузив приложение.
И обращаться к нему можно как «blog#index», (локально) или «5.5.5.5/blog/index», и суть по идее не меняется.
Не очень силён в рельсах и в исходники лень лезть, предполагаю что
foo = FooController.new
foo_response = foo.bar
text = response.body

не сработает. По аналогии с другими фреймворками могу предположить, что достаточно будет (не минимально достаточно, но сработает без задействования сетевого уровня) формирование фейкового запроса ActionDispatch::Request и его обработка. То есть почти как у вас, но без сети. Обычно такие запросы формируются для функционального тестирования

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

http = EM::HttpRequest.new("http://localhost:3000/foo/bar?text=#{params[:a]}").get

вместо localhost:3000 поставить балансировщик я думаю проблем с масштабированием не будет.

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

Как по мне HMVC сродни goto.
Хотите полноценное HMVC в Rails, используйте Cells.
А посылать HTTP-запрос из приложения в это же приложение — это, уж извините, извращение, а не HMVC.
Дело времени. В других решениях реализовано и так и так одним и тем же способом. Разумеется, внутренние вызовы делаются не через HTTP. Вот пример христоматийный (это руби, но не суть)
		// Internal request example
		$internal_request = Request::factory('controller/action/param')
			->execute();
 
		// External request example
		$external_request = Request::factory('http://www.ibuildings.com/controller/action/param')
			->execute();
</code>
В Rails кстати из за REST может частичное HMVC из-коробки получиться, если обращаться к /posts/add.json через POST или PUT, используя обёртку. Для получения данных /posts.json через GET. 
Не, ну может быть я чего-то не понимаю, но если у вас возникает необходимость вызывать собственное приложение через внешний HTTP-вызов, чтобы получить кусочек html или некую структуру данных, то это epic fail в архитектуре и «HMVC» призывается лишь с целью отвлечь внимание от проблемы.
Да, задачи должны быть другого характера. Компоненты HMVC — это веб-сервисы. И решать они должны соответствующие задачи. Это уже вопрос декомпозиции. В ООП тоже можно смешное применение классам найти.
Похоже мы говорим о разных вещах…
HMVC, в моем представлении, — это возможность из одного контроллера (или из его представления) вызвать другой контроллер и получить в качестве результата его представление, т.е. в любом случае либо кусочек html, либо plain text, либо некую структуру данных (не важно в xml, json, etc.), чего уж тут смешного… Это помогает решить проблему с чистотой MVC, когда представления состоят из разнородных блоков.
А вопросы коммуникации веб-сервисов, на мой взгляд, никакого отношения к HMVC не имеют.
Я говорю об обоих вещах. Для меня HMVC это возможность вызывать другой контроллер (как правило, именно из представления). Для моих задач это в подавляющем большинстве случаев означает синхронно вызвать другой контроллер в том же приложении (процессе/потоке) на том же сервисе. Хорошо, если фреймворк обеспечит прозрачную возможность так же вызывать произвольный веб-сервис без необходимости писать для него обёртку, плохо если ради такой возможности (а то и без неё) мой же контроллер доступный в том же процессе будет вызываться через полноценный HTTP-запрос.
Для того, чтобы синхронно вызвать другой контроллер в том же приложении (процессе/потоке) из представления другого контроллера Cells подходит идеально.

Теперь по поводу произвольности вызываемого контроллера…
На мой взгляд, разрешение вызова контроллера из представления — это серьёзное архитектурное решение и если фреймворк сам принимает это решение, разрешая подобный доступ к любому контроллеру, то это очень плохо. Только разработчик должен решать какие действия каких контроллеров можно так дёргать, что не отменяет возможности дёргать их и через обычный HTTP-запрос при желании.

Что касается веб-сервисов, то, на мой взгляд, они должны возвращать клиентскому коду только данные и ничего кроме данных. Для использования таких сервисов собственного сочинения отлично подходит ActiveResource, но это уже к вопросу о разнесении частей приложения по разным серверам…
Скажем прямо, подобный приём масштабирования действительно нужен крайне редко и, как правило, для узкоспециальных вещей. Потребности в неком универсальном решении для произвольного контроллера такие задачи не имеют.
Возможно да, имеет смысл разработчику явно указывать что такой-то контроллер можно вызывать из представлений напрямую и накладывать на них какие-то ограничения, поскольку, например, не очень понятно что делать, если, например, контроллер результат выполнения которого должен по идее отображаться в сайдбаре, вернет внешний редирект. С другой стороны, если контроллер доступен по HTTP, то ничто нам не помешает внедрить его в тот же сайдбар с помощью фреймов или XHR, то есть ограничения превращаются в профанацию.
Ну во-первых, с помощью Cells можно делать в том числе и контроллеры недоступные через HTTP. Другими словами можно просто не подключать к ним роутинг.

А во-вторых, ограничения — это контракт для разработчиков, работающих над проектом. А то Вы с такой позицией далеко в неправильное направление рискуете уйти, ведь ничто нам не помешает вызвать метод через var.send(:method), но это отнюдь не повод отказываться от объявления приватных методов; ведь ничто не помешает сохранить невалидную модель через raw SQL(если нет валидации на уровне СУБД), но это не повод не писать валидации и т.д. и т.п.
Да, практически любое ограничение можно нарушить, а изредка даже нужно, но в целом именно следование конвенциям в рамках ограничений в конечном итоге и отличает качественный код от лапшы.
>> Хотите полноценное HMVC в Rails, используйте Cells.
В Cells каждый компонент не является полноценным MVC.

>> А посылать HTTP-запрос из приложения в это же приложение — это, уж извините, извращение, а не HMVC.
Это всего лишь реализация, я думаю, что вполне реально делать эти запросы какими-то внутренними механизмами, как, например, в functional тестах
> В Cells каждый компонент не является полноценным MVC.

С чего вдруг? Cells-контроллеры наследуют AbstractController::Base из Rails, имеют доступ к моделям и могут рендерить любые views. Абсолютно полноценный MVC.

> я думаю, что вполне реально делать эти запросы какими-то внутренними механизмами

как, например, в Cells!
Rails engines могут вложенными, они существуют в отдельных namespace'ах. Но подсмотреть, как реализован request в cells — думаю, будет полезно.
Ну причём здесь Rails Engines? Они придуманы для повторного использования изолированных кусков приложения, а не для HMVC.
Те же namespace там используются для усиления изоляции, а Вы пытаетесь эту изоляцию нарушить, а это ни к чему хорошему не приведёт.
Я нарушить изоляци не хочу, я как раз считаю, что следует разработать механизм, который запретит всем обращаться ко всем.

Сейчас это можно сделать только административно: договориться не нарушать несвязность компонентов.

Для чего разрабатывались engines сейчас не так важно. Важно, что есть еще один способ, как их использовать.
Sign up to leave a comment.

Articles