Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 17.06.2012, 14:42
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

У меня напрашивается определённые мысли по решению проблемы.
Спишу поделится.
Заранее извеняюсь за оффтоп. Разжовываю подробно и со всех сторон.
Который раз пишу про архитектуру, и всегда получается очень много . Словами большой кусок кода описать непросто


Итак напомню проблемы.
1)При возвращении данных в формате ajax у нас возникает проблема с поисковиками,
2)возвращая данные в html, мы обрекаем скрипт клиента работать с хтмл, что ему не всегда удобно

первую проблему можно решать делая рендер для сервера и клиента отдельно , что весьма трудозатратно.
Однако я сразу необратил внимание на то, что трудозатратно это только в том случае если на сервере и на клиенте разные языки,
к примеру PHP + JS.

Но ведь связки NODEJS+JS это не касается, тут то один язык !

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

================================================== =
Для начала назовём этот самый динамический фрагмент страницы виджетом, чтобы обзавестись терминологией.

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

Попробуем разбить виджет на части, чтобы подключать в разных ситуациях только нужные части. За принципам разбивания далеко ходить не будем, возьмём проверенный MVC.

Тогда получается следующая картина.
Каждый виджет состоит из трёх частей.

Модель - хранит данные и умеет с ними оперировать.
VIEW - умеет рендерить данные в хтмл.
Контролёр - поведение виджета (реакция на события).

К серверу подключать достаточно VIEW и MODEL
К клиенту VIEW,MODEL и контролёр.

То есть на сервере при рендеренге страницы,мы используем VIEW которая использует модель.
На клиенте используется тот же view с той же моделью, и контролёр в придачу (чтобы он мог реагировать на события).

То есть в виджите есть две части(модель и view ), существующие одновременно на двух физических разделённых слоях системы.

================================================== =
Как добится их применимости на клиенте и на сервере одновременно ?
================================================== =
Очевидно что нужно абстракироваться от платформы.

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

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


Представление (view) может отдалится при помощи шаблонизатора и какихнибудь хелперов для рендеринга.
Тоесть опять же особенности платформ мы пытаемся вынести в сторонние библиотеки, оставляя код виджета чистым
от тонкостей платформ.
================================================== =
как это приблизительно работает ?
================================================== =
Сервер
1) Генерируется страница, на странице обнаружен виджет
2) Подгружается модель и view виджета, в VIEW запускается метод rendeIndex, который рендерит виджет
3) VIEW в процессе рендеринга использует в качествке источника данных модель, модель для загрузки данных в себя,
обращается за помощью к прокси, который умеет работать с бд
4) Полностью отрендеренная страница отправляется клиенту.

клиент.
1) На страницу подгружаются все востребованные клиентом скрипты.(впрочем это может происходить паралельно с шагом 2)
2) Начинается процесс инициализации, сначало ищется тег в котором находится виджет, затем инициализируется
соответственный контроллёр, которому в качестве параметра передаётся ссылка на DOM элемент с виджетом.
3) контролёр, при инициализации может захотеть заполнить модель, в этом случает он даёт модели команду load,
модель обращается к прокси, который обращается к сервису на сервере, на сервере происходит проверка прав на доступ,
и если всё нормально то данные возвращаются прокси, и он заполняет данными модель.
4) дальше контролёр подписывается на все интерисующие его события.
5) Контролёр ждёт событий. Первый раз рендерить виджет не надо, так как он уже отрендерен на сервере.
Когда произойдёт события контролёр просто вызовет соответствующий метод у view для того чтобы он отобразил данные из модели.

================================================== =
Какой профит ?
================================================== =

1) Решили проблему с поисковиками. - Виджеты рендерятся на сервере, когда генерируется страница.
2) Сокращён срок разработки - Мы не дублируем код на сервере и на клиенте.
3) Сохранена функциональность клиентских скриптов, нет обязаловки в передачи клиенту HTML, клиент получает данные в формате JSON, которые попадают в модель, клиент этими данными распоряжается по своему усмотрению.
4) Мы получили возможность создавать очень сложные виджеты, за счёт разделение кода виджета на логические части.

================================================== =
Можно ли для построения сайта использовать только плагины ?
================================================== =

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

Ниже я ещё допишу пару топиков с поянениями, и примерами кода.
Также жду ваших соображений по выше написанному.
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 17.06.2012 в 15:08.
Ответить с цитированием
  #22 (permalink)  
Старый 19.06.2012, 15:54
Интересующийся
Отправить личное сообщение для lsync Посмотреть профиль Найти все сообщения от lsync
 
Регистрация: 04.09.2010
Сообщений: 12

Вариант реализации
Доброго дня, предложу вариант, с которым обычно работаю:

1. Запрос получает фронт-контроллер, единая входная точка веб-приложения.

2. Он определяет, какая модель данных затребована (на шаблоны ему пока побоку), в данном случае - СписокМудаков.

3. Запрашивает у Model-слоя необходимую модель. По сути - набор объектов, в родном для системы формате (в вашем случае - JavaScript-массив Мудаки[] + отчет об ошибках, если нужен: Ошибки[]). Никаких потерь на сериализацию на данном шаге!

4. Определяется шаблон. Варианты:
- HTML, JSON, XML...;
- редирект (этому пользователю нельзя видеть список мудаков);
- сообщение об ошибке (вместо запрошенных данных) в нужном формате;
- ...etc;
Фишка определения шаблона именно на этом шаге (а не на первом-втором) в том, что мы адекватно можем отреагировать на ошибки формирования модели, ограничения прав доступа и т. д.

5. Модель отдается соответствующему шаблонизатору. Фишка, опять же, в том, что видов шаблонизаторов здесь можно подключить сколь угодно много (HTML, XML, JSON, ...).

6. Шаблонизатор сериализует модель должным образом и отдает клиенту.

Тип подключаемого шаблонизатора может определяться параметром запроса или урлом. Например, по умолчанию генерим HTML, при наличии в запросе &format=json - генерим легковесный JSON.

NGINX на входе становится не обязательным (и даже не желательным в контексте работы фронт-контроллера), но вполне может использоваться для выдачи статики.

В общем, ничего ничему не мешает. Успехов в серверном JS!
Ответить с цитированием
  #23 (permalink)  
Старый 20.06.2012, 18:08
Аватар для B~Vladi
Модератор Всея Форума
Отправить личное сообщение для B~Vladi Посмотреть профиль Найти все сообщения от B~Vladi
 
Регистрация: 14.05.2009
Сообщений: 4,021

Сообщение от DjDiablo
Всем хорош этот способ, вот только данные для клиентских плагинов, поисковики учитывать не будут
Ну он уже учтет то, что пришло на странице. При следующем посещении будут уже обновленные данные. Так что проблемы тут я не вижу.

Сообщение от DjDiablo
Когда клиентский скрипт нуждается в обновлении данных он запрашивает view "B" напрямую.
Это уже не view будет, а model - чистые данные.

Сообщение от DjDiablo
Если вы рендерете хтмл на стороне сервера то при таком подходе решается проблема с поисковиками, однако теряется гибкость клиентских скриптов.
Гонять AJAX-ом HTML не круто, так что не подойдет.

Сообщение от DjDiablo
Это значит что мы можем написать универсальный код который будет работать и на клиенте и на сервере.
Эмм, это уже лишнее. Всё-таки окружения разные, значит и код должен быть разным.

lsync, по поводу второго и третьего пунктов. При ajax-запросе всё просто, нужны одна модель - массив мудаков. При обычном запросе, помимо этого массива, нужен уже набор этих моделей. Так же и при ajax-запросах возможно понадобятся несколько моделей в одной пачке.

Если определение этих наборов переложить на контроллер - он будет сильно разрастаться. Поэтому я и разделил на несколько контроллеров и назвал их сервисы. Собственно, получается то, о чем я писал в первом посте.
__________________
Болтовня ничего не стоит. Покажите мне код. — Linus Torvalds
влад.куркин.рф

Последний раз редактировалось B~Vladi, 20.06.2012 в 18:11.
Ответить с цитированием
  #24 (permalink)  
Старый 21.06.2012, 12:16
Интересующийся
Отправить личное сообщение для lsync Посмотреть профиль Найти все сообщения от lsync
 
Регистрация: 04.09.2010
Сообщений: 12

Сообщение от B~Vladi Посмотреть сообщение
При ajax-запросе всё просто, нужны одна модель - массив мудаков. При обычном запросе, помимо этого массива, нужен уже набор этих моделей. Так же и при ajax-запросах возможно понадобятся несколько моделей в одной пачке.
Не вижу в этом проблемы - формировать вы можете сколь угодно сложную модель из нужного количества субмоделей. По сути, мои модели древовидны, и в полной мере содержат запрошенный контент.

Сообщение от B~Vladi Посмотреть сообщение
Если определение этих наборов переложить на контроллер - он будет сильно разрастаться. Поэтому я и разделил на несколько контроллеров и назвал их сервисы.
1. Разрастаться будет ничуть не более, чем конфиг роутера.

2. Разделить на несколько контроллеров и назвать их сервисами - это супер, но то, что вы написали в первом посте, требует наличия внешнего роутера. Он ни к чему в данной цепочке - лучше сделать его внутренним. Причины:
  • внешний роутер не имеет алгоритма формирования древовидных моделей;
  • в случае запроса двух и более сервисов одновременно (а для формирования HTML-страниц всегда будет запрошен более чем один сервис) внешний роутер сделает два запроса к приложению. В худшем случае - это дважды и более "раскачать" тяжеловесный слой модели. Пример: на странице выводится список друзей пользователя и список его личных сообщений. Внешний роутер заставит модель дважды обратиться к БД за сущностью Пользователь. Конечно вы это можете кешировать (проблема есть - костыль готов), но можете просто положить в дерево ответа и не запрашивать повторно.
  • снижается переносимость приложения в целом - добавляя новый сервис вам недостаточно задеплоить его в приложение, нужно ещё поменять конфиг роутера и перезапустить его. Моими сервисами я могу динамически управлять через веб, независимо от того, за кем они находятся.

Хотя есть и серьезное преимущество - внешний роутер это плюс к легкости масштабирования. Так что надо взвешивать конкретную ситуацию.

Сообщение от B~Vladi Посмотреть сообщение
Собственно, получается то, о чем я писал в первом посте.
Совпадение с тем, что вы писали в первом посте, только по пункту 4, в остальных разница, сильно влияющая на функциональность.

Последний раз редактировалось lsync, 21.06.2012 в 12:38. Причина: Какой-то недружелюбный тон нечаянно получился. :)
Ответить с цитированием
  #25 (permalink)  
Старый 21.06.2012, 13:05
Аватар для B~Vladi
Модератор Всея Форума
Отправить личное сообщение для B~Vladi Посмотреть профиль Найти все сообщения от B~Vladi
 
Регистрация: 14.05.2009
Сообщений: 4,021

Так, стоп.
Сообщение от lsync
внешний роутер не имеет алгоритма формирования древовидных моделей
Они и не должен его иметь, это же роутер, он только проксирует запрос на конкретный сервис, в зависимости от URL. Этим будет заниматся сервис...
Сообщение от lsync
в случае запроса двух и более сервисов
Такого в принципе быть не может, или ты что-то другое имел ввиду?
Сообщение от lsync
добавляя новый сервис вам недостаточно задеплоить его в приложение, нужно ещё поменять конфиг роутера и перезапустить его
Это да. Но такая задача не каждый день возникает...
Сообщение от lsync
Разрастаться будет ничуть не более, чем конфиг роутера.
Да, но параллельно, всё же легче будет потом править... Сам сервис может быть поделён ещё на более мелкие части. Модель так и останется независимой ни от сервиса ни от роутера.
__________________
Болтовня ничего не стоит. Покажите мне код. — Linus Torvalds
влад.куркин.рф
Ответить с цитированием
  #26 (permalink)  
Старый 21.06.2012, 13:44
Интересующийся
Отправить личное сообщение для lsync Посмотреть профиль Найти все сообщения от lsync
 
Регистрация: 04.09.2010
Сообщений: 12

Сообщение от B~Vladi Посмотреть сообщение
Они и не должен его иметь, это же роутер, он только проксирует запрос на конкретный сервис, в зависимости от URL. Этим будет заниматся сервис...
Вот поэтому и предлагаю вам более гибкую систему - добавить в роутер логику по разбору URL, и формированию дерева ответа. Он уже не будет называться роутером, но не суть.

Сообщение от B~Vladi Посмотреть сообщение
Такого в принципе быть не может, или ты что-то другое имел ввиду?
Если делаете исключительно веб-API, то да, не может. Но ведь в исходном посте вопрос был о полноценном веб-приложении, умеющем как отвечать на API запросы, так и формировать HTML-страницы.

Обычно для формирования одной страницы сайта вам придется обратиться к нескольким своим сервисам (блочный дизайн, так?), отсюда и вызов нескольких сервисов на один HTTP-запрос. И отсюда же - необходимость логики для формирования всей страницы из кирпичиков независимых сервисов:

Пришло:
http://domain.com/forum/page=3

Вызвали свои сервисы:
- getMenu;
- getUserData;
- getPosts;
- getAd;
- get...
Положили все это в дерево ответа. Отдали шаблонизатору, отрендерили, вернули результат в виде HTML страницы.

Пришло:
http://domain.com/api?getAd=8

Вызвали:
- getAd;
Положили в дерево, отрендерили в JSON, вернули.

В примере выше "getAd" - ваш сервис, он независим от остального и всегда выдаёт одинаковую модель, хотя и вызывается из совершенно различных контекстов. А фронт-контроллер определяет, какой набор сервисов вызвать согласно запрошенному URL, и в каком шаблоне отрендерить результат.

Для простоты понимания я бы предложил ввести еще один термин - Flow (Поток). Тогда верны утверждения:
- URL определяет, какой Flow будет отработан;
- Flow содержит нужный набор сервисов;
- Фронт-контроллер выполняет Flow, вызывая нужные сервисы и сохраняя ответы в результирующую модель;
- Фронт-контроллер определяет, корректно ли выполнен Flow, и принимает решение о выборе шаблона;
- Шаблонизатор рендерит модель в указанный контроллером шаблон.
Ответить с цитированием
  #27 (permalink)  
Старый 21.06.2012, 13:55
Интересующийся
Отправить личное сообщение для lsync Посмотреть профиль Найти все сообщения от lsync
 
Регистрация: 04.09.2010
Сообщений: 12

В догонку добавлю, что несмотря на кучу терминологии и длинные объяснения принципов работы, на практике подобная система реализуется на любом языке за 15 минут (при условии наличия шблонизатора), без каких-либо фреймворков, и самое главное - весьма эффективно растет и масштабируется, без появления каши в системе.
Ответить с цитированием
  #28 (permalink)  
Старый 21.06.2012, 14:34
Аватар для B~Vladi
Модератор Всея Форума
Отправить личное сообщение для B~Vladi Посмотреть профиль Найти все сообщения от B~Vladi
 
Регистрация: 14.05.2009
Сообщений: 4,021

lsync, я понял, мы под разными терминами подразумеваем разные вещи. Я говорил о:
Сообщение от lsync
Пришло:
http://domain.com/forum/page=3
forum - сервис, остальное его параметры, по которым формируются те или иные данные.
Сообщение от lsync
Вызвали свои сервисы:
- getMenu;
- getUserData;
- getPosts;
- getAd;
- get...
Это "ручки" (модель), о которых я писал выше. Их дёрнет сервис forum (контроллер), получит данные и отдаст шаблонизатору (view).
Сообщение от lsync
Пришло:
http://domain.com/api?getAd=8
api - сервис, дёрнет ручку getAd, вернёт ответ.

Поэтому я и написал, что одновременно не могут быть вызваны несколько сервисов.

Перед сервисами - роутер (nginx), разруливает, на какой сервис пришел запрос.

Сообщение от lsync
Для простоты понимания я бы предложил ввести еще один термин - Flow (Поток). Тогда верны утверждения:
- URL определяет, какой Flow будет отработан;
- Flow содержит нужный набор сервисов;
- Фронт-контроллер выполняет Flow, вызывая нужные сервисы и сохраняя ответы в результирующую модель;
- Фронт-контроллер определяет, корректно ли выполнен Flow, и принимает решение о выборе шаблона;
- Шаблонизатор рендерит модель в указанный контроллером шаблон.
Согласен, но, опять же, с поправкой на терминологию: сервис -> модель, ручка. Фронт-контроллер -> сервис, контроллер.

Сообщение от lsync
добавить в роутер логику по разбору URL, и формированию дерева ответа
Получается, что это уже есть, но разделено: первое - роутер, второе - сервис.

Сообщение от lsync
блочный дизайн, так?
Ога

Если такая терминология подходит, предлагаю переходить на неё. Если нет - объясни какие моменты считаешь нелогичными/непонятными.
__________________
Болтовня ничего не стоит. Покажите мне код. — Linus Torvalds
влад.куркин.рф
Ответить с цитированием
  #29 (permalink)  
Старый 21.06.2012, 18:39
Интересующийся
Отправить личное сообщение для lsync Посмотреть профиль Найти все сообщения от lsync
 
Регистрация: 04.09.2010
Сообщений: 12

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

Сообщение от B~Vladi Посмотреть сообщение
1. Приходит GET-запрос на роутер (в моем случае это nginx). Роутер определяет сервис (раздел или подраздел сайта, к примеру), который обрабатывает этот запрос и проксирует ему.
Роутер не нужен, NGINX (или прочее) в вашей цепочке не несет функциональной нагрузки, а значит, является лишним.

Сообщение от B~Vladi Посмотреть сообщение
2. Сервис, получив запрос, определяет какой шаблон с какими данными необходимо вернуть.
С оговорками, что сервис изначально определяет только модель, а шаблон определяется как результат её формирования, и только после шага 3 (не сейчас).

Сообщение от B~Vladi Посмотреть сообщение
3. Дергает нужные ручки, в надежде получить от них данные в JSON.
Данные ни во что внутри системы не сериализуются, этим занимается шаблонизатор.

Сообщение от B~Vladi Посмотреть сообщение
4. После получения всех данных рендерит шаблон и возвращает результат.
Тут не поспоришь
Ответить с цитированием
  #30 (permalink)  
Старый 21.06.2012, 19:02
Аватар для B~Vladi
Модератор Всея Форума
Отправить личное сообщение для B~Vladi Посмотреть профиль Найти все сообщения от B~Vladi
 
Регистрация: 14.05.2009
Сообщений: 4,021

Сообщение от lsync
NGINX (или прочее) в вашей цепочке не несет функциональной нагрузки
Как быть со статикой и кешированием динамического контента?
Сообщение от lsync
сервис изначально определяет только модель
Согласен. Хотя от шаблонизатора тоже зависит. Если он умеет описывать View-логику, то и сам сможет разрулить какой в итоге собрать шаблон, в зависимости от принятых данных.
Сообщение от lsync
Данные ни во что внутри системы не сериализуются, этим занимается шаблонизатор.
Хорошо, напишу шаблон из одной строчки
__________________
Болтовня ничего не стоит. Покажите мне код. — Linus Torvalds
влад.куркин.рф
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
JavaScript client и server side игры Москва 110 000 Yanazavr Работа 0 25.03.2012 14:16
Помогите с архитектурой приложения epson Общие вопросы Javascript 6 09.02.2012 16:32
ВАКАНСИЯ:Сlient side developer СПБ ElenaJMK Работа 25 19.11.2010 16:24
ошибка XMLHttpRequest при запросе ис-под Isa Server poison jQuery 5 14.04.2010 13:38
Архитектура расширяемого приложения. DeveloperRu Библиотеки/Тулкиты/Фреймворки 2 16.03.2010 23:52