Последние пару лет я разрабатываю интерфейсы и все это время у меня было две проблемы, для которых не удавалось найти решения. Для начала я постараюсь кратко изложить их суть, чтобы оставить только целевую аудиторию.
- Я всегда стремился к тому, чтобы мой код лекго читался и его удобно было использовать много раз (reusable). И благо, уже давно придуманы все эти ООП, модульности, etc. С чем, вроде, писать хороший код куда легче, и даже когда кажется, что сложно, все равно возможно. Но как я не старался, а код, который обеспечивал сколько-нибудь сложную работу с HTML, всегда превращался в простыню нечитаемого текста. Причем это касалось как самого HTML (и/или шаблонов), так и javascript'а.
- Вторая проблема более частная, и касается продуктовых компаний, которые поддерживают больше, чем один сервис (я всегда работал только в таких, из религиозных соображений). Проблема состоит в том, что таким сервисам присущий «корпоративный стиль», а код у них чаще всего разный. И тут возникают терзания, как правильно стоит разрабатывать, вроде, много схожего, но разного то больше.
Не так давно, я понял, что этих проблем в моих проектах больше нет, и осознав случившееся, я решил поделиться тем, какие концепции/методологии привели меня к этому. Не знаю много ли людей сталкивались с такими же проблемами, но от нескольких своих друзей я точно слышал схожие жалобы. Если вам интересно — добро пожаловать под кат.
Эпизод первый
Давайте начнем с первой и, пожалуй, более серьезной проблемы. Еще раз немного детальнее:
Если у вас среднестатистический проект, то в хорошем случае у вас есть какой-нибудь Angular/Backbone/whatever, в плохом — вы сами написали что-то похожее на коленке, или у вас нет фреймворков вовсе. И почти наверняка, вы используете jquery (чистый в хорошем случаи, с всякими странными plugin'aми — в плохом) для разных манипуляций с DOM'ом и может для чего-то еще. Да где-то такими и были мои предыдущие проекты.
Когда проект немного разрастался, чтобы как-то структурировать я максимально разбивал страницы на какие-то логические блоки (в зависимости от того, что использовать, терминологию можно немного править, но я буду стараться использовать наиболее общие понятия), иногда это давало свой эффект, а иногда все расползалось, и потом было тяжело отыскать, файлик с js'ом или css'ом, который обрабатывает этот блок (если учесть, что все это писали еще и разные люди). Это был первый неудачный момент, которого все же удавалось избегать, если держать дисциплину в команде.
Вторая большая проблема: если на блоке заложено достаточно много бизнес-логики, то файлик с его javascript'ом становился очень длинным (но это не беда), самое главное, что все его содержание — это какие-то бесконечные jquery-обработчики и if'ы. Здесь мой дух оптимизатора подсказывал, что надо вводить какие-то объекты и пытаться как-то жонглировать ими, но удавалось мне это как-то весьма слабо (здесь речь идет именно о привязке к DOM'у).
И если проект был весьма большим, то необходимость в каком-то лишнем слое абстракции для работы c HTML'ем ощущалась весьма сильно, но я никак не поддавался из-за своей травмы детства. Когда-то я разрабатывал используя большую часть продуктов из стека Microsoft (тут уж не желание меня сподвигло, а необходимость в получении стипендии в университете), с того времени я основательно опасаюсь лишних слоев абстракций в своих приложениях.
Исторической справедливости ради, стоит еще заметить, что поначалу в качестве серверного языка программирования я использовал PHP, тут, конечно, еще добавлялось сложностей, так как нельзя было использовать серверный код на клиенте. Но когда я все же пересел на node.js, легче то стало (кода ведь стало меньше), но от основных проблем я не избавился. Я ведь по-прежнему боялся сложных шаблонизаторов, и даже с нодой на сервере мои view'шки/template'ы были очень HTML'ные. Ведь, всякие jade'ы выглядели страшно и были не похожи на мой ламповый HTML.
Время шло, я мучился.
Конечно, как и все front-end'еры я ходил на конференции, читал статьи, и знал о том, что есть замечательная концепция абсолютно независимых блоков (АНБ), но все же мне казалось, что это больше о верстке (а верстать я старался меньше, я не видел там системы и меня это отпугивало), чем о программировании. Да крутая идея как можно верстать, но мои то проблемы она не решает (?).
Потом, конечно, я узнал и о БЭМ'е. Посмотрел, почитал.
Вроде, концепция — ок, именно та абстракция, которой мне не хватает. Инкапсулирует в себе работу с HTML, да еще и предоставляет монструозный набор технологий, которые, вроде, должны совсем облегчить жизнь.
Но дальше читва на выходные у меня не дошло, все тот же невалидный javascript меня отпугнул. Да и по правде говоря, за вечер ничего толкого сделать у меня не получилось. Но куда двигаться идеологически, я уже начал понимать.
Спустя еще какое-то время я узнал о BEViS.
Прочитав веселый учебник о нем (прочтения даже у самого внимательного читателя не займет более часа) я настолько вдохновился, что через полчаса я уже верстал на нем свой первый проект. Не знаю почему, но когда я попробовал верстать на привычном javascript, мне так понравилось, что я перестал испытывать от верстки какой-то дискомфорт.
Основное, что очень сильно подкупило меня — это простота и понятность. Очень очевидная концепция, просто сделать первые шаги, просто верстать, приятно разрабатывать. В общем, если вам интересно, то просто зайдите и почитайте, я уверен, что вам понравится. И еще одним преимуществом данного фреймворка есть то, что он написан и поддерживается ребятами из Яндекса, что уже накладывает на него некий стандарт качества.
Единственное, что стоит, наверное, добавить, это каким вообще образом данный выбор избавил меня от моей проблемы.
BEViS создает в моих проектах еще один уровень абстракции, инкапсулируя в себе работу с HTML'ем, и давая мне возможность писать на моем любимом javascipt'е, но делает это не в ущерб производительности. И для меня все блоки выглядят как функции. Внутри самих же блоков я могу производить любые операции над элементами этого блока использую предоставленное API.
Конечно, сам фреймворк накладывает на меня некоторые ограничения по возможности манипуляции блоками, но эта строгость и определяет полученную на выходе простоту. Первое впечатление, которое у меня появилось, когда я начал использовать BEViS — так это же модульная система для HTML'я. И мне показалось это очень круто.
Если же подумать более основательно, то сразу находятся схожести с Web Components, но когда они дойдут до того состояния, что их можно будет использовать в production'е неизвестно, а BEViS — уже работает.
Эпизод второй
Вторая же проблема, как я уже писал, более характерна для средних и крупных продуктовых компаний. Эта проблема возникла у меня, когда я разрабатывал еще на PHP, и как ее правильно решить в его рамках я и сейчас не до конца представляю. В основном из-за отсутствия адекватной модульной системы.
В рамках же node.js это хорошо решается созданием отдельного модуля, с условным названием «библиотека блоков». Идея этого модуля очень проста. Его единственной задачей будет предоставление блоков (блоком назовем некоторую самостоятельную сущность, например, блок поисковой формы). Каждую страницу сайта можно разбить на какие-то логические блоки (такие как header, footer, форма авторизации, etc), так вот если сравним эти блоки для разных сайтов нашей компании, то мы увидим, что многие из них или сильно похожи, или одинаковы.
Те из них, которые встречаются в разных проектах чаще других, мы и вынесем в этот модуль. И когда на странице какого-то сайта нам понадобится форма обратной связи, мы не пойдем писать новый блок, а просто позовем его из библиотеки блоков.
Плюсы такого подхода более, чем очевидны:
1) «корпоративный дизайн» лежит в одном месте, и чтобы его поменять, нам не нужно менять код всех наши проектов;
2) создать новое приложение куда быстрее, ведь надо всего лишь собрать нужные блоки в страницы, и что-то где-то «подпилить».
Как вообще эти две проблемы связаны, спросите вы. Зачем я решил объединить их в одну статью?
Ответ очень простой, когда я начал разрабатывать используя BEViS, я понял, что это идеальный инструмент для создания таких библиотек блоков. За счет того, что когда мы создаем какой-то блок в BEViS, наружу он доступен только как функция, которую можно вызвать с каким-то набором параметров. Инкапсуляция всех внутренностей — это очень хорошее поведение для любого API (каким есть библиотека блоков), поскольку именно это может гарантировать обратную совместимость минорных версий.
На этом, пожалуй, все. Спасибо всем, кто осилил.
Автор: alt-j