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

HTML в веб-приложении

Что именно происходит в веб-приложении: в процессе генерации html-страницы данные постепенно "одеваются", обрастают всё большим количеством html-тэгов, или наоборот – гигантский шаблон запрашивает и, как спрут, вбирает, всасывает в себя данные из разных источников? В какой момент в разметке страницы появляется тэги <strong>, <p>, <a href="static/./">, <div id="catalog">?

В двух словах на этот вопрос можно дать только один ответ: происходит всё, и html смешивается с данными как попало. Сталкиваются две тенденции. Изначально данные физически не могут обходиться без своих собственных тэгов, являющихся частью семантики. Например, тэг em, делающий логическое ударение на некоторых словах. Или тэг sup, без которого невозможно написать ни одну формулу. Таки тэги являются частью данных.

Но розовый цвет фона, зелёные или серые ссылки (вместо классических синих), выравнивание текста по формату – это уже в голом виде свойства шаблона, а не данных, – украшательство, эстетика; данные ничего об этом не знают.

То есть можно пытаться ответить на этот вопрос в разрезе "необходимости": кому нужен конкретный набор меток – данным или шаблону? Если данным, то "данные одеваются"; если шаблону, то шаблон набивает данными своё брюхо. Но техническая реализация может отличаться от требования "необходимости". Цвет ссылок может быть указан прямо внутри данных. Это плохо. Предполагаем, что плохо и обратное – когда шаблон вмешивается в структуру данных. Впрочем, все эти крайние случаи не дают ответа на основной вопрос: на каком этапе работы веб-приложения лучше было бы заключать текст меню в тэги <div class="menu"> и </div>?

Тут нам никак не обойтись без уточняющего вопроса "а какая хрен разница?" и уточняющего ответа: "вариант б) безопаснее" (или "вариант а) удобнее"); после чего мы традиционно спросим: удобнее для кого? безопаснее от чего? – и традиционно всплывёт императив "повторного использования кода". (Да. А по безопасности ничего не всплывёт).

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

1) Контроллер готовит все данные: Данные Меню ($menu), Данные Страницы ($page), Данные Каталога ($catalog).

2) Шаблон забирает эти данные и подставляет в нужные места между соответствующими тэгами:

Но на практике всё выглядит гораздо менее гладко. Потому что все данные являются массивами (объектами):

Повторное использование слегка напрягается. Если нам понадобится "вот эти данные" упаковать в совсем другой шаблон, придётся писать очень много всяких "<?php" заново. Если даже мы захотим одно готовое (оформленное тэгами) меню перенести в другой шаблон, нам придётся искать цикл вывода именно этого меню и аккуратно вырезать маникюрными ножницами. Поэтому шаблон лучше бы выводить всё-таки по-другому, составлять из более мелких частей, что-нибудь вроде:

****************

Даже внутри самого шаблона не всегда ясно, что является данными. Например, вот это – "class='menu'" – вовсе не "конечный шаблон", а данные, предназначенные для обработки в подсистеме браузера CSS. Ну, а js и вовсе не является частью шаблона. Ведь работа приложения не заканчивается с отдачей страницы браузеру, – в браузере продолжается реализация логики приложения с помощью javascript, который тоже должен получать и обрабатывать данные. В CMS Бикубик данными для js являются идентификаторы элементов (id="menu", id="page"...).

*****************

На каждом конкретном участке фронта всё может происходить по-разному. Например, в двух важных подсистемах, компонентах Бикубика – Меню и Каталоге – шаблонизация происходит так.

Каталог. Здесь есть чётко выделенный шаблон – catalog_item (который в классическом варианте мог бы лежать в отдельном файле); данные подставляются в этот шаблон в цикле и полученный готовый HTML-фрагмент присоединяется к общей строке:

Меню – всё "на шарнирах", там нет "выделенного шаблона" для ссылки (который мог бы выглядеть примерно так: <span class="%s"> <a href="static/%s"><img alt="%s" src="%s"/></a> <span>). Потому что все кусочки одной ссылки формируются динамически, а там слишком много вариантов: с картинкой или без, со ссылкой или без (активный пункт меню – текущая страница), разная природа картинок – иконка меню или уменьшенное "главное изображение страницы", наконец, меню может быть с анонсами (для новостей) или без. Да, и ещё: ссылка может быть с текстом или без (только в виде картинки)! Итого 5 бит, 32 варианта. Делать 32 разных готовых шаблона западло. Ну, и наверное, с системной точки зрения не очень правильно.

Ещё один прикол: шаблонизатор уровня элемента в Бикубике – функция View::htpl, а не строка вида <div class="%s">%s</div> . То есть для одевания данных в html мы пишем не $div = sprintf($tpl['div'], $class, $text);, а $div = View::htpl(2, 'div', $attrs, $text); – таким образом мы а) обеспечиваем себе маневренность (можно создавать принципиально любой элемент, а не выбирать из набора готовых), б) успеваем внедрять элемент безопасности html-атрибутов перед собственно форматированием (экранируем кавычки).

Иногда это раздражает, и хочется применить "простой" шаблонный вывод. И мы пишем в том же Меню: $out .= '<li' . $class_li . '>' . $link['link'] . $next . '</li>'; – потому что там атрибут class формируется в предыдущей функции из готового набора из трёх слов, прямо "на глазах", и безопасность типа не нужна. Но в том же Меню, при формировании табличного вывода (а не списком) мы в аналогичном месте пишем:

– то есть применяем функцию-шаблонизатор tpl_td вместо простой "форматной" строки. Так кажется удобнее, потому что строка не простая: это может быть как элемент td, так и целый tr, в зависимости от уровня вложенности меню (на который указывает параметр $topline). "Какой придурок! Ну какой придурок!.." – возникает у вас мысль, – ведь, казалось бы, насколько проще было бы вывести Меню "классическим" шаблоном; или хотя бы сделать попросту два разных шаблона – на верхний уровень и остальные, вложенные. Ну, или даже написать прямо в основной функции, при наращивании строки:

Ну, вот жалко мне повторять два раза такие большие фрагменты, что сделаешь... Ну, и основная функция вывода меню выглядит удобнее, читаемее. Сейчас это, наверное, один из сильнейших двигателей, формирующих структуру Бикубика – стремление упрощать функции, "выносить за скобки" как можно больше фрагментов кода. "Скрывать сложность", как говорят некоторые специалисты. Отсюда и предельно "высушенный" вид главных шаблонов сайта – все крупные блоки типа Меню или Главного текста выносятся в отдельные функции-шаблонизаторы (или "компоненты", самостоятельно получающие и форматирующие данные). А почему на других уровнях мы стремимся "скрывать сложность", а шаблоны оставляем громоздкими и неуклюжими? Чем они хуже? Почему такая дискриминация?

Запрос пользователя

Можно попробовать поточнее расставить всё по местам, опираясь на начальную причину появления страницы в браузере. Эта причина – пользователь, который щёлкнул по ссылке. На ссылке было написано: "Контакты". И пользователь вообще-то ожидает увидеть телефон и адрес, что, собственно, и является данными. Пользователь хочет (и рассчитывает) увидеть всё-таки Данные, которые он запросил. Поэтому всё остальное в шаблоне является большей частью помехой, назойливой рекламой, спамом.

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

С этой точки зрения (пользователь дёргает именно данные), ведущей силой являются данные; они обрастают HTML по мере продвижения запроса в приложении и в конце выдаются пользователю в рамке шаблона. Шаблон – это именно просто рамка, красивое обрамление для полезной информации. И если эта рамка перевешивает данные своей толщиной и разнообразием узоров, сайт, в сущности, начинает свой путь превращения в так называемую сосальную сеть (или просто – говносеть, как её я называю), назначение которой – засасывать пользователей, мягко принуждать их тупо "сидеть" в своих уютных контактах и однофейсниках.

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

Дилетант

Комментарии