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

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

Ничего хорошего из этого не выйдет :-)
А теперь предположим, что в html встречается последовательность символов [=[ или ]=]. И абстракция потекла…
Всё-таки для шаблонов нужен нормальный парсер.
Да, есть несколько неучтенных моментов, которые я в ближайшие пару дней поправлю и задокументирую.
Для более сложного можно использовать мой вариант. Он подстраивается под начинку. Но да, не «одной строкой».
Исправлено.
Причем тут спагетти-код? Исходно термин «спагетти-код», он же «макаронный код», означал код с запутанным потоком управления — многочисленными операторами GOTO (или избыточным использованием исключений). Также спагетти-кодом называют код со слишком обширными связями между модулями, когда формально независимые модули невозможно использовать раздельно.

Шаблоны в стиле php — не самая удачная конструкция исключительно из-за похожести символов <? и ?> на тэги HTML. Других недостатков у таких этих шаблонов нет, и называть их «спагетти-кодом» некорректно.
Есть, они смешивают логику и верстку из-за чего и верстать не удобно и за логикой сложно уследить.
А что, кто-то заставляет их смешивать? Можно же их и разнести: либо просто логику в начало файла передвинуть, либо даже по разным файлам — язык-то позволяет. Хоть убейте, не вижу никакой принципиальной разницы между
<? if ($foo) { ?>
    <div><?=$foo?></div>
<? } ?>
и
@if (foo != null) {
    <div>@foo</div>
}
кроме удобочитаемости.
Да, такой формат. Ты просто не сможешь ничего отрендерить, не применив циклы, ветвления и функции.
Оба примера содержат смешение логики и верстки. Правильный пример мог бы выглядеть так:

myViewList = {
	get content(){
		if( this.items ) {
			return this.items.map( item => new myViewItem( item ) )
		} else {
			return new myViewEmpty
		}
	}
}


<div type="myViewList">{content}</div>

<div type="myViewItem">
	<div type="myViewItem_title">{title}</div>
	<div type="myViewItem_count">{count}</div>
</div>

<div type="myViewEmpty">
	List is empty. Try to reduce filters.
</div>
Вот извините, но именно ваш пример и является спагетти-кодом (точнее, спагетти-версткой). О том, что myViewItem и myViewEmpty являются альтернативными вариантами разрешения {content} в myViewList, не сказано нигде — и догадаться об этом, читая верстку, невозможно.

Так зачем нужна «чистая от логики» верстка, если понять ее можно только глядя на логику?
{content} может разрешаться во всё, что угодно и на этапе вёрстки совершенно не важно во что. Задача верстальщика — предоставить кубики лего из которых программист может строить приложение любой сложности просто стыкуя их в разных комбинациях. Прежде чем оголтело кидаться минусами, я бы советовал вам попробовать — это реально гораздо удобней.
А пока подумайте над следующими проблемами так называемых «традиционных шаблонов» и над способами их решения:
1. рендеринг блоков разных типов одним списком (например, лента новостей)
2. перестановка блоков местами в зависимости от набора параметров (например, полей много, но заполнены только частично и нужно выводить их в компактном виде)
3. ленивая загрузка минимума данных, необходимого для рендеринга, а не всего подряд (в запросе надо указать какие поля моделей надо прогрузить)
4. возможность пользователя конфигурировать раскладку блоков на странице и переключать их видимость (например, дашборд)
5. реиспользование верстки (ссылка на пользователя, ссылка на метку, кнопка и тп)
Задача верстальщика — сверстать страницу, а не заставлять программиста играть в кубики. Тем более, что верстальщику гораздо проще напрямую сверстать страницу, чем сначала верстать ее, а потом нарезать на кубики.

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

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

Прежде чем оголтело кидаться минусами, я бы советовал вам попробовать — это реально гораздо удобней.
В разное время мне случалось редактировать шаблоны веб-страниц на движке Razor (который в ASP.NET MVC) и на укозе (там используются блоки, как вы предлагаете). Так вот — первая задача была выполнена за 15 минут, а вторую я бросил. Поэтому я возвращаю вам ваш совет: попробуйте делать так, как делают все нормальные люди — это реально гораздо удобней.

1. Для того, чтобы рендерить разные типы блоков одним списком, надо их получить одним списком. Рендеринг — наименьшая из проблем, которая решается оператором цикла и несколькими условными операторами.

2,4. Перестановка блоков местами и возможность конфигурировать раскладку блоков — да, они требуют выделения части верстки в отдельную сущность «блок». «Традиционные» шаблоны легко позволяют это сделать. Но, заметьте, выделять в автономный блок следует лишь то, что и правда должно быть выделено — при этом как общий макет страницы, так и внутренняя верстка блока могут быть сделаны так, как удобно верстальщику, а не так, как его ограничили вы.

3. Ленивая загрузка данных — это когда выполняется 100500 уточняющих запросов к БД при каждом формировании страницы? Спасибо, не надо! Лучше я по-старинке, одним-двумя запросами все необходимое вытащу.

5. Те блоки верстки, которые должны быть переиспользуемы, легко становятся функциями. Важно, что решение сделать их повторно используемыми может быть принято верстальщиком единолично, без согласования с программистом или архитектором проекта.
Если речь о лендингах, то да, сверстал страницу и свободен. Если речь о полноценном сайте или даже веб-приложении, то важным становится реиспользуемость кода, легкость поддержки, выдержанность единого дизайна (как внешнего, так и внутреннего). Программисту проще писать без тестов, но поддерживать результат потом невозможно. Работа верстальщика не заканчивается на первичной верстке. Он должен иметь возможность править верстку без ковыряния в куче логики. Путь «верстальщик делает статический макет, программист разрезает его и натягивает на шаблонизатор, потом верстальщик поправил макет, программист заново его нарезает» — порочен.

В «традиционной модели» шаблон зависит от формата данных, которые должен сформировать программист. Никакого разделения не получится. В «непривычной модели» зависимости нет и верстальщик может компоновать блоки как угодно, причем выводить их сразу во всех возможных состояниях, а не заниматься ерундой вида «поправил код. перезагрузил страницу, подождал пока пройдет вся инициализация, накликал нужное состояние, увидел косяк и по новой».

Ещё раз — проблема не в «нарезании» — это однократная операция. Проблема в поддержке, которая нужна постоянно. И верстальщик, не имея должной квалификации и желания разбираться просто сделает копипасту сложного условия вместо того, чтобы рефакторить логику.

Можно пример укозового шаблона? В любом случае тезис похож на «я привык работать молотком, поэтому забиваю шурупы быстрее чем вкручиваю». За 8 лет, а перепробовал всё, что только можно, от говнокода на smarty до крупных проектов на xslt :-)

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

2, 4. В современных динамичных приложениях такие блоки — далеко не единичные случаи. Даже «общего макета страницы» может не быть.

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

5. Продвигаемая мной идея как раз и позволяет делать это легко и просто. О чём спор? :-)
В современных динамичных приложениях такие блоки — далеко не единичные случаи. Даже «общего макета страницы» может не быть.
Приведите пример сайта, у которого нечего вынести в общий макет (кроме одностраничных сайтов, где само слово «общий» теряет смысл). Я пока что из таких видел только одну CMS, работающую по принципу «создай все сам, редактируя БД через тот же интерфейс, который ты сейчас создаешь». Спасибо, но такая CMS должна отправиться в то же место, куда и мегаблочные спагетти-шаблоны.

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

Ещё раз — проблема не в «нарезании» — это однократная операция. Проблема в поддержке, которая нужна постоянно.
Вот мне надо исправить положение имени пользователя на странице. Допустим, я как веб-разработчик уже имею опыт, но на проекте впервые, так что ничего еще в нем не знаю (сравнивать поведение человека в знакомом проекте смысла нет, потому что в обоих случаях он найдет нужное место сразу же).
В традиционном шаблоне достаточно найти элемент в инспекторе (встроенная возможность браузера, 2 клика), запомнить его окружение — и найти похожий блок кода в шаблоне. Поскольку структура шаблона и результата совпадает — это несложно.
Теперь берем ваш шаблонизатор. Где искать блок, выводящий имя пользователя? Искать по файлу строку «username»? А если она называется «user_name» или «login»? Ну хорошо, блок с именем пользователя нашли — но проблема оказалась не в нем, а во внешнем блоке. Как найти внешний блок, не заглядывая в логику? А если в эту логику заглянуть — то зачем мы ее с такой кровью отделяли?
Да тот же google.ru (морда и результаты поиска)
Правда там смена раскладки сделана на css — гораздо менее гибким муторным способом.

Вы так и не привели примера укозного шаблона.

«запомнить его окружение»
«и найти похожий блок кода в шаблон»
Как-то всё это похоже на гадание на кофейной гуще.

«структура шаблона и результата совпадает»
Опять же только в лендингах она совпадает. В остальных же случаях — частично пересекается, не более.

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

image

Тут подробней описано как оно работает
На том же google.ru можно дофига чего вынести в общий макет — наличие нескольких выбивающихся из макета страниц этому ничуть не мешает.

Вы так и не привели примера укозного шаблона.

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

С идентификаторами элементов — ладно, выкрутились :) В таком виде действительно можно быстро найти нужное место.
Но и ничуть не способствует. Зачем искусственно вводить какой-то общий макет для совершенно разных по структуре страниц?

Ладно, не важно, не думаю, что в этом кривом сервисе было что-то вменяемое :-)
Более того, в moonscript есть возможность делать так
Скрытый текст
[list_users: "/users"]: =>
    users = Users\select! -- `select` all the users
    @html ->
      ul ->
        for user in *users
          li ->
            a href: @url_for("user", user.id), user.name


Я задавался задачей сделать что-то аналогичное etlua максимально просто.
MoonScript для генерации HTML хорош, уж по крайней мере не забудешь закрыть тег. Раздражает отсутствие некоторых тегов, из-за чего приходится писать так:

element 'table', ->
  element 'tr', ->
    element 'td', ->
      text 'Тут наконец содержимое первой ячейки'
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории