Javascript-форум (https://javascript.ru/forum/)
-   Оффтопик (https://javascript.ru/forum/offtopic/)
-   -   Архитектура server-side приложения (https://javascript.ru/forum/offtopic/28553-arkhitektura-server-side-prilozheniya.html)

B~Vladi 24.05.2012 16:13

Архитектура server-side приложения
 
Мир кодерам.

По долгу службы я бОльшую часть времени имею дело с client-side приложениями, поэтому возник такой вопрос.

Я делаю собственный проект, без использования фреймворков по идеологическим причинам. Архитектуру серверной части сайта продумываю сам и хотелось бы получить несколько советов от людей, разбирающихся в этом предмете, до того как начать её создавать.

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

1. Шаблон напрямую обращается к источникам данных (базе, например).
2. Шаблон дергает некую ручку (приложение), которое обращается к данным, формирует их в нужном формате и возвращает.
3. Приложение (а не шаблон), получает нужные данные из источников и передаёт их одной пачкой в шаблон.

Это самые частые механизмы генерации страниц, которые мне попадались.
Есть один важный момент, который мне нужно учесть: данные могут быть запрошены как для шаблона, так и в чистом виде. Например: на странице есть блок - ТОП10 мудаков сайта. Список мудаков нужно отдать в шаблон, при запросе содержащей её страницы. Затем, каждые 10 минут необходимо обновлять блок AJAX-ом, т.е. получить по-сути те же данные, которые отдаются в шаблон перед рендерингом.

Исходя из этого требования, становится понятно, что первый и третий варианты не подходят - придется дублировать агрегацию данных для шаблонов и AJAX-запросов. В первом варианте шаблон сам агрегирует нужные ему данные. Во втором этим занимается отдельное приложение. А кто будет это делать для AJAX? Не круто.

Второй вариант подходит. Но. Что, если шаблон не умеет дергать ручки? Например, dust, TSN. Да, они могут вызывать функции, но результат при этом должен вернуться синхронно, а в NodeJS (мой проект на ноде) этого практически никогда не бывает.

Поэтому я ничего лучше не придумал, как объединить второй и третий вариант. Алгоритм:
1. Приходит GET-запрос на роутер (в моем случае это nginx). Роутер определяет сервис (раздел или подраздел сайта, к примеру), который обрабатывает этот запрос и проксирует ему.
2. Сервис, получив запрос, определяет какой шаблон с какими данными необходимо вернуть.
3. Дергает нужные ручки, в надежде получить от них данные в JSON.
4. После получения всех данных рендерит шаблон и возвращает результат.

Для получения AJAX-ответа достаточно будет создать сервис AJAX, который будет дергать нужную ручку и возвращать полученные от неё данные.
Можно считать, что ручка - это модель, сервис - контроллер, шаблон - представление. Контроллер запрашивает только нужные данные, которые могут не нуждаться в представлении (как в сервисе AJAX).


Кто-нибудь имел дело с такой архитектурой?

Представьте, что вы устроились на работу в проект, где всё так устроено. Хотелось бы вам работать в таком окружении?

B~Vladi 24.05.2012 16:19

UPD: Буду рад услышать ваши варианты, но с аргументами.

Gozar 24.05.2012 20:22

Цитата:

Сообщение от B~Vladi
Алгоритм:

Если приложение сложное, то я делаю именно так.

У меня не nginx решает, а php куда дальше передавать запрос или исполнение задачи. Запрос разбивается на части и определяется раздел и прочие данные.

В самом простейшем случае подходит банальный switch, в сложном то, что описал ты. С более сложным не сталкивался.

B~Vladi 24.05.2012 20:40

Немного поясню про nginx. Там, собственно, никакой магии нет:
Код:

        location /serviceName/ {
                proxy_pass http://127.0.0.1:8001;
                # Этот порт слушает сервис, т.е. HTTP Server NodeJS.
                # Каждый сервис на своем порту и не доступны извне.
                # Далее идут параметры кеширования.
        }

Другими словами: я разделил url на хост/сервис/параметры_сервиса. Выбрал nginx из соображений производительности. Причем соображения разные, например, попытаюсь запилить такую схему на AJAX-ответы:
Код:

Request -> Nginx -> Memcached -> Nginx -> Response.
Т.е. без участия backend-а (у nginx есть необходимый модуль). Ответ в бинарном виде (Для этого и писал Buffer.js).

Gozar 24.05.2012 21:35

Цитата:

Сообщение от B~Vladi
попытаюсь запилить такую схему на AJAX-ответы

Ну и нормально :)

B~Vladi 25.05.2012 21:53

Больше никому нечего добавить? Хотя это не удивительно - здесь большинство клиентских кодеров. Но ведь должны же быть ещё знающие люди.

Vantedur 12.06.2012 09:04


very complexity

B~Vladi 12.06.2012 11:40

Vantedur, на картинке ничего не видно.

Vantedur 12.06.2012 12:26

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

B~Vladi 12.06.2012 12:41

И как это относится к теме поста?

Vantedur 12.06.2012 13:54

Цитата:

Сообщение от B~Vladi (Сообщение 176624)
Но ведь должны же быть ещё знающие люди.

Они есть... спрашивай в пм если что-то определённое интересует

B~Vladi 14.06.2012 13:36

Maxmaxmахimus, не умничай, сначала пойми о чем речь - потом комментируй.

B~Vladi 14.06.2012 17:36

Цитата:

Сообщение от Maxmaxmахimus
я те сказал как делать

Ты вообще не по теме написал. Ты не понял сути вопроса. И аргументов я не увидел.

B~Vladi 15.06.2012 15:55

Спасибо тебе, за старания и потраченное время.
А теперь прочитай название темы ещё разок: "Архитектура server-side приложения". Зачем ты сюда клиента прикрутил - для меня загадка.

На будущее: я в курсе как реализовать общение клиента с сервером, как реализовать API, в каком формате гонять данные, какие события вызывать.

Не стоит мне расписывать очевидные вещи. И не пиши больше в этой теме - ты мне точно ничем здесь не поможешь. Спасибо за понимание.

tadjik1 16.06.2012 14:01

B~Vladi,
всё, что могу посоветовать - напишите лучше на форумах по perl, php, etc. у нас целый отдел делает серверную часть, пишут на перле. это действительно сложный процесс =)

B~Vladi 16.06.2012 14:24

Цитата:

Сообщение от tadjik1
это действительно сложный процесс

Да ничего сложного там нет.

Цитата:

Сообщение от tadjik1
напишите лучше на форумах по perl, php, etc.

Ну да, только не на php. Вообще нода интересует.

DjDiablo 17.06.2012 00:45

В том что вы описали можно узреть аналогию с популярными патернами
================================================== ============

1) Шаблон напрямую обращается к источникам данных (базе, например).
Я думал так уже не пишут, с этого начилось программирование для web,
хотя нет пишут, DLE-engine так работает))

2) Шаблон дергает некую ручку (приложение), которое обращается к данным, формирует их в нужном формате и возвращает

Такое поведение характерно для паттерна MVC, так работает джумла.
кстатии привет от Smarty, он тоже очень любит дёргать за всякие ручки.

3) приложение (а не шаблон), получает нужные данные из источников и передаёт их одной пачкой в шаблон.

Подобное поведение характерно для паттерна MVP, так работает YII.

Конечно эти сравнения с натяжкой но всё же похоже.

B~Vladi 17.06.2012 01:00

DjDiablo, спасибо, с DLE и YII не работал, но в курсе.

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

DjDiablo 17.06.2012 01:20

Я всё таки решил закончить мысль.
Я пока отлажу в сторону архитектуру, и сосредоточусь на ином вопросе.

Для начала, кто сказал что надо рендирить список мудаков и для клиента и для сервера. Помоему данное дублирование неразумно, это двойная работа при планировании, при разработке , при отладке, при доработке в следующих версиях.

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

1й) Рендерим json для клиента.
Это значит что на клиенте будет скрипт знающий какую ручку дёрнуть, скрипт будет регулярно запрашивать данные с сервера, соответственно на сервере будет контролёр который будет уметь эти данные отдавать.

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

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

2й) Рендерим html и для сервера, и для клиента.
в этом случае подразукмевается что данные на сервере превращаются в html а не JSON или XML.
Такой рендер удобен тем что он одинаков как для клиентской, так и для серверной части.
То есть, есть код который генерирует хтмл, который вы потом используете по усмотрению передавая его на клиент по ajax, либо вставляя шаблон.

Данный подход удобно реализуется паттерном HMVC.

Реализуем архитектурным паттерном HMVC.
Когда контролёр "A" вдруг обнаруживает что ему нужен результат работы контролёра "B", он просит контролёр "B" вернуть результат. Когда скрипт обновляет данные регулярно,то он обращается к контролёру "B" напрямую, get запросом. И вставляет HTML в нужное место.

Реализуем научив mvc вкладывать один view внутрь другого view.
Когда view "A" вдруг обнаруживает что ему внутри нужен отрендеренный "B", он рендерит B и вставляет его в себя. Когда клиентский скрипт нуждается в обновлении данных он запрашивает view "B" напрямую.

Если вы рендерете хтмл на стороне сервера то при таком подходе решается проблема с поисковиками, однако теряется гибкость клиентских скриптов.

Deff 17.06.2012 01:43

Цитата:

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

Ксать забавные тут идейки проскакивали - IP типовых Поисковиков не так уж и много
Вот почти весь перечень
Yandex,95.108.,77.88.,93.158.
Google,66.249.
Mail,94.100.,217.69.134.,217.69.136.
Rambler,81.19.
Yahoo!,67.195.,72.30.,74.6.,202.160.
Bing,207.46.,65.52.,65.55.,157.55.
Baidu,119.63.,123.125.,220.181.
Ask,66.235.
Ezooms,208.115.111.
Aport,194.67.

Ну дык вот - посколь как то делали многоаяксовый сайт, хотелось индексирование сохранить
Дык для поисковиков
Селектировали по IP и выделяли для них отдельный серв, цепляемый , как клиент/render к общему, который рендил и проксировал уже отренденное взятое от пользовательского серва для данных IP

DjDiablo 17.06.2012 14:42

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


Итак напомню проблемы.
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 с сервера, а весь динамически создаваемый контент в нём, могут создавать плагины. То есть страница будет просто рамкой в которую встроены плагины. Конечно всё вешать на плагины не обязательно, но идея на мой взгляд забавная.

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

lsync 19.06.2012 15:54

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

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

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

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

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

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

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

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

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

В общем, ничего ничему не мешает. Успехов в серверном JS!

B~Vladi 20.06.2012 18:08

Цитата:

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

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

Цитата:

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

Это уже не view будет, а model - чистые данные.

Цитата:

Сообщение от DjDiablo
Если вы рендерете хтмл на стороне сервера то при таком подходе решается проблема с поисковиками, однако теряется гибкость клиентских скриптов.

Гонять AJAX-ом HTML не круто, так что не подойдет.

Цитата:

Сообщение от DjDiablo
Это значит что мы можем написать универсальный код который будет работать и на клиенте и на сервере.

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

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

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

lsync 21.06.2012 12:16

Цитата:

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

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

Цитата:

Сообщение от B~Vladi (Сообщение 182785)
Если определение этих наборов переложить на контроллер - он будет сильно разрастаться. Поэтому я и разделил на несколько контроллеров и назвал их сервисы.

1. Разрастаться будет ничуть не более, чем конфиг роутера.

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

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

Цитата:

Сообщение от B~Vladi (Сообщение 182785)
Собственно, получается то, о чем я писал в первом посте.

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

B~Vladi 21.06.2012 13:05

Так, стоп.
Цитата:

Сообщение от lsync
внешний роутер не имеет алгоритма формирования древовидных моделей

Они и не должен его иметь, это же роутер, он только проксирует запрос на конкретный сервис, в зависимости от URL. Этим будет заниматся сервис...
Цитата:

Сообщение от lsync
в случае запроса двух и более сервисов

Такого в принципе быть не может, или ты что-то другое имел ввиду?
Цитата:

Сообщение от lsync
добавляя новый сервис вам недостаточно задеплоить его в приложение, нужно ещё поменять конфиг роутера и перезапустить его

Это да. Но такая задача не каждый день возникает...
Цитата:

Сообщение от lsync
Разрастаться будет ничуть не более, чем конфиг роутера.

Да, но параллельно, всё же легче будет потом править... Сам сервис может быть поделён ещё на более мелкие части. Модель так и останется независимой ни от сервиса ни от роутера.

lsync 21.06.2012 13:44

Цитата:

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

Вот поэтому и предлагаю вам более гибкую систему - добавить в роутер логику по разбору URL, и формированию дерева ответа. Он уже не будет называться роутером, но не суть.

Цитата:

Сообщение от B~Vladi (Сообщение 182985)
Такого в принципе быть не может, или ты что-то другое имел ввиду?

Если делаете исключительно веб-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, и принимает решение о выборе шаблона;
- Шаблонизатор рендерит модель в указанный контроллером шаблон.

lsync 21.06.2012 13:55

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

B~Vladi 21.06.2012 14:34

lsync, я понял, мы под разными терминами подразумеваем разные вещи. Я говорил о:
Цитата:

Сообщение от lsync

forum - сервис, остальное его параметры, по которым формируются те или иные данные.
Цитата:

Сообщение от lsync
Вызвали свои сервисы:
- getMenu;
- getUserData;
- getPosts;
- getAd;
- get...

Это "ручки" (модель), о которых я писал выше. Их дёрнет сервис forum (контроллер), получит данные и отдаст шаблонизатору (view).
Цитата:

Сообщение от lsync

api - сервис, дёрнет ручку getAd, вернёт ответ.

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

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

Цитата:

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

Согласен, но, опять же, с поправкой на терминологию: сервис -> модель, ручка. Фронт-контроллер -> сервис, контроллер.

Цитата:

Сообщение от lsync
добавить в роутер логику по разбору URL, и формированию дерева ответа

Получается, что это уже есть, но разделено: первое - роутер, второе - сервис.

Цитата:

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

Ога

Если такая терминология подходит, предлагаю переходить на неё. Если нет - объясни какие моменты считаешь нелогичными/непонятными.

lsync 21.06.2012 18:39

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

Цитата:

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

Роутер не нужен, NGINX (или прочее) в вашей цепочке не несет функциональной нагрузки, а значит, является лишним.

Цитата:

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

С оговорками, что сервис изначально определяет только модель, а шаблон определяется как результат её формирования, и только после шага 3 (не сейчас).

Цитата:

Сообщение от B~Vladi (Сообщение 183012)
3. Дергает нужные ручки, в надежде получить от них данные в JSON.

Данные ни во что внутри системы не сериализуются, этим занимается шаблонизатор.

Цитата:

Сообщение от B~Vladi (Сообщение 183012)
4. После получения всех данных рендерит шаблон и возвращает результат.

Тут не поспоришь :)

B~Vladi 21.06.2012 19:02

Цитата:

Сообщение от lsync
NGINX (или прочее) в вашей цепочке не несет функциональной нагрузки

Как быть со статикой и кешированием динамического контента?
Цитата:

Сообщение от lsync
сервис изначально определяет только модель

Согласен. Хотя от шаблонизатора тоже зависит. Если он умеет описывать View-логику, то и сам сможет разрулить какой в итоге собрать шаблон, в зависимости от принятых данных.
Цитата:

Сообщение от lsync
Данные ни во что внутри системы не сериализуются, этим занимается шаблонизатор.

Хорошо, напишу шаблон из одной строчки :)

lsync 21.06.2012 20:23

Цитата:

Сообщение от B~Vladi (Сообщение 183078)
Как быть со статикой и кешированием динамического контента?

Об этом я писал выше, вы невнимательны. Суть в том, что он не участвует в формировании страниц и ничего никуда не рулит при компоновке динамики. А вовсе не в том, что он бесполезен.

Цитата:

Сообщение от B~Vladi (Сообщение 183078)
Согласен. Хотя от шаблонизатора тоже зависит. Если он умеет описывать View-логику, то и сам сможет разрулить какой в итоге собрать шаблон, в зависимости от принятых данных.

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

Цитата:

Сообщение от B~Vladi (Сообщение 183078)
Хорошо, напишу шаблон из одной строчки :)

Для вывода JSON он и будет из одной строчки. А для веб-страниц, содержащих ту же модель данных - уже нет. А для мобильных страниц он будет третьим. В этом фишка: есть модель - как хотим, так и рендерим. Единожды и для клиента, но не внутри приложения.

B~Vladi 21.06.2012 21:20

Цитата:

Сообщение от lsync
Для вывода JSON он и будет из одной строчки.

Я про это и говорил.
Цитата:

Сообщение от lsync
Об этом я писал выше, вы невнимательны.

:-?
Цитата:

Сообщение от lsync
Суть в том, что он не участвует в формировании страниц и ничего никуда не рулит при компоновке динамики. А вовсе не в том, что он бесполезен.

Это понятно. Но я пока всё равно не вижу причин не использовать nginx в качестве роутера. Проксировать он умеет прекрасно, это его одна из основных возможностей, так почему бы ей не воспользоваться?
Цитата:

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

Конечно, используемый мной шаблонизатор это умеет.

devote 22.06.2012 09:18

B~Vladi,
раз уж тут такая пьянка, попробую рассказать о своей системе реализованной на собственном движке.

Реализация у меня такова, кратко:
1. Шаблон, выступает в качестве client-side/virtual-client-side приложения, никак не связанного c View и ни с чем другим. Собственно он дергает ручки контролера.
2. Контролер, занимается перенаправлением требований от client-side и не более того, то-есть client-side дергает ручку контрола, контрол дергает нужную модель, на основе запроса.
3. модель, собственно занимается формированием данных, обработкой запросов и т.д. Формирует данные и отдает их уже выходному view.
4. View, собственно отвечает за то в каком виде отдать клиентской части данные, в формате JSON ( тоесть по запросу AJAX ) либо уже сформированное view представление.

Вот собственно модель работы моего движка. Конечно нюансы есть где-то, но принцип примерно такой.

B~Vladi 22.06.2012 11:31

Цитата:

Сообщение от devote
либо уже сформированное view представление.

Т.е. прогоняет через шаблонизатор? А что тогда такое "шаблон" из п.1? Какая-то рекурсия получается :)

ЗЫ: немо 3 поста (!) написал и даже нахуй никого не послал :blink:
Походу настроение хорошее было...

devote 22.06.2012 13:18

Цитата:

Сообщение от B~Vladi
Т.е. прогоняет через шаблонизатор? А что тогда такое "шаблон" из п.1? Какая-то рекурсия получается

есть два типа шаблонизатора, один на клиенской части находится, другой на серверной... Общее у них лишь одно, это обработка тех же данных что отдала модель. Но на стороне клиента шаблонизатор строит структуру на основе того что у него есть, а у него есть в распоряжении браузер и шаблоны построенные именно для клиентской части. В серверной же части шаблоны имеют немного иной вид, так как там нет браузерного движка и нет возможности вставлять ноды прямо в середину структуры если таково нужно. Хотя с одной стороны подобное можно реализовать. Но лишняя нагрузка не всегда хорошо. Поэтому сервер строит шаблон в потоке. От того у меня и организована не MVC а получается MVCM

B~Vladi 22.06.2012 13:24

devote, понятно, но принципиальных отличий не заметил от того, к чему мы пришли выше.

devote 22.06.2012 13:27

ой, не MVCM а получается MVVC

devote 22.06.2012 13:29

Цитата:

Сообщение от B~Vladi
но принципиальных отличий не заметил от того, к чему мы пришли выше.

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

Shaci 22.06.2012 13:32

Цитата:

Сообщение от кто я?(4 буквы, первая н) (Сообщение 183222)
сверху вниз

Магазины, сети, качественные порталы.

генерируемая система для готовых решений

Модули->апи, контролеры, выходные файлы->css,js,csv lung, формы, модели->таблицы,плагины,настройк ->router,content,вьюшки помошники, вьюшки штмлки, виджеты,publick files, бустстрап, библиотеки.


особенности, отлично знать фронт, знать оптимизацию бд, алгоритмы.


качай готовый двиг и переделывайЮ ты с готовым замучаешься не то что делать кривой

вторая буква Е?

B~Vladi 22.06.2012 13:46

Цитата:

Сообщение от Shaci
вторая буква Е?

Других вариантов просто быть не может:
Цитата:

Сообщение от B~Vladi
немо 3 поста (!) написал



Часовой пояс GMT +3, время: 07:53.