История CSSO, выводы

Так вот, выводы, коих я сделал множество. Отголоски вы можете найти в эссе этого блога, но корни в CSSO.

Во-первых, если вы не product owner, ничего вашего нет. Нет ваших решений. Нет вашего кода. Нет вашего продукта. Ни к чему не надо относиться лично. Сразу выстраивайте забор и действуйте профессионально. Профессиональная разработка — уведомить настойчивого заказчика о проблемах, убедиться, что мысль донесена и проигнорирована, зафиксировать факт и авторство, решить задачу максимально хорошо, пусть это задача категории «пилить сук, на котором сидим». Сук спилен, мы упали, лапки сломали. И что? Вы этого и хотели. Я вообще многое научился документировать хотя бы истории ради. И с большим интересом с тех пор смотрю на людей, которые ну прям настаивают на том, чтобы диалог никак не фиксировался.
Во-вторых, энтузиазм хорошо, но подменять им реальность не надо. Спустя пару лет я размышлял. Вот чем мы думали, представляя, что недавние верстальщики, едва перековываемые во фронтендеров, начнут понимать и писать не вёрстку на JavaScript? Да даже сейчас (спустя 8 лет Node.js!) встречаю множество фронтендеров, в упор не знающих и не хотящих знать Node.js. Им сайты делать, а не утилиты править. Хорошо, обнаружил Пупкин, что CSSO не так сжимает background. Один из ста Пупкиных даже до репорта дойдёт. Один из сотни дошедших в исходник посмотрит. Один из сотни посмотревших что-то там поймёт. Не потому, что тупой, но потому, что ИМ НЕ НАДО. Всегда, когда есть вероятность, что какой-нибудь аудитории не надо, считайте, что не надо никому.
В-третьих, ИМ НЕ НАДО. Нет, правда. В мире по разным оценкам от 10 до 20 миллионов разработчиков. Посмотрите список коммитеров проектов, которые вы считаете ну очень, очень популярными. На которые все должны молиться и каждую бажку забивать молотками за секунду репорта. Сюрприз. Каждый проект в пересчёте на масштаб делает очень небольшая команда людей, которым действительно не пофиг. Остальным пофиг. Всё, что вы будете начинать в одиночестве, вы будете делать в одиночестве, продолжать в одиночестве и завершать в одиночестве. Недавняя история MongoDB-драйвера на Go тому примером. Чувак 7 лет тянул на себе вполне хороший драйвер, все использовали, но драйвер закрылся потому, что чуваку надоело, а больше никого нет. Ха. Пользователей может быть миллион, но вы всё равно будете в одиночестве. Они потребители вашего продукта, не более.
В-четвёртых, чем выше порог входа вашего начинания, тем ниже вероятность соратников. Люди не читают, не учатся, не интересуются. Всё непонятное им кажется страшным. У CSSO были PEG и OmetaJS, у PhantomJS низкоуровневый код. При этом последний автор PhantomJS говорит:

Потому что, одно дело, когда есть какая-нибудь популярная библиотека, та же самая CSSO, написанная на JavaScript — популярном языке, и сейчас, что называется, каждый второй человек владеет им, — и прийти, почитать код, немного разобраться в проекте не составит труда

Ойнемогу. Виталий Слободин, что раньше CSSO разрабатывался одним человеком, что сейчас. По факту два (!) человека за 7 лет жизни утилиты. А вы говорите. Не надо в прогнозах учитывать (мечтать, фантазировать) пассионарность. Надо учитывать её отсутствие и радоваться, если с ней встречаетесь.

В-пятых, проекты одного разработчика — это всегда зона риска. Его сбивает автобус и всё. Ему надоело и всё. Он укатил на Карибы и открыл там кафе и всё. Если вам нравится библиотека X одного разработчика, а библиотека Y группы разработчиков чуть хуже, берите вторую.
В-шестых, проекты из компаний (а не сообщества) — это всегда зона риска. Компаниями управляют бюджеты, иерархии, прибыли, что-нибудь ещё. Компаниями не управляют (вы всё ещё верите маркетинговым брошюрам и статьям?) другие категории. Вы пользуетесь библиотекой, всё хорошо. Во вторник руководитель 5-го ранга решает, что разработка библиотеки не приносит прибыли. В среду команда разработки расформирована. В четверг вы думаете о том, чего дальше-то.
В-седьмых, soft skills важны и нужны, если вы хотите добиваться своего. Я конфликтен, злобен, меня раздражают многие категории населения. История CSSO научила меня тому, что разработка такого уровня в таких условиях состоит из soft skills чуть ли не на 50%. Из чего я сделал вывод больше никогда не начинать подобное в таких условиях. Право говорить людям то, что ты о них думаешь, стоит неначатого, закрытого, пошедшего не тем путём. Наиболее правильная позиция у Линуса Торвальдса. Делает нужный крутой продукт, всех посылает в лес, никому не улыбается насильно вежливо. Уважуха. Помните абзац про моё недопонимание с фронтендерами? Вот здесь оно вставало порою в полный рост.

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

История CSSO, завершение

Особняком от разработки как прошлый 2011 год CSSOv1, так и наступивший 2012 год оказались весьма насыщенными общением. Сначала вы общаетесь с десятками людей, чтобы начать проект и делать. После публикации о проекте вы общаетесь с десятками людей, объясняя вводную, собирая первые репорты и вообще торгуя вежливостью и готовностью. После популярности вы общаетесь уже с сотнями (GitHub, Twitter, mail, лично, Jabber, даже пара звонков была) людей. Такой вот постоянный поток, который надо держать [и продолжать быть вежливым]. Объём его достаточен, чтобы пойти к руководству и рассказать, мол, смотри, я 20% рабочего времени не код пишу, не думу думаю, но просто отвечаю на вопросы, даю ссылки на спецификации, выясняю детали репортов и лучусь оптимизмом. Было несколько свежим опытом.

2012 год
Январь — целый месяц багфиксов, снятия накопившегося техдолга, организационные правки. В следующие месяцы бываю в CSSO лишь набегами в среднем два-три дня в пару месяцев.
Октябрь — CSSO перешёл с парсера PeCode на Gonzales. Gonzales был очень интересным экспериментом. Я попробовал написать руками парсер, который был бы выдан воображаемым генератором парсеров воображаемой PEG. И ведь получилось. Скорость разбора увеличилась в 3..5 раз, код с позиции генератора вышел стройный и хорошо алгоритмизируемый.
Фактически это был шаг к разработке следующего поколения экосистемы вокруг идей OmetaJS. Также это был последний камень в надгробие CSSOv1.
За два года идеи и эксплуатации стало очевидным, что это поколение себя изживает. Надо избавляться от PEG. Надо писать менее монолитный продукт. Количество набранного опыта структурной минимизации следовало переделать в новое качество. Наконец, в голове накопилось немало фантазий о том, какой [крутой] стек утилит вокруг можно выстроить. Но требовался другой парсер с другим AST. Так CSSOv1 был поставлен на логическую паузу и я начал домашнюю проработку CSSOv2.
Также время, которое мне разрешали тратить на CSSOv1, неумолимо сокращалась и проект по приоритетам опустился на самое дно. Надо было писать другие утилиты.
Всплыл ещё один нюанс, который надеялись перевалить умом и сообразительностью, но в рамках CSSOv1 так и не получилось — gzip. Иногда CSSO жал файлы лучше gzip, иногда хуже. DEFLATE хорошо себя чувствует на избыточности, что в случае с CSS подарок. Это дало повод в дальнейшем ряду критиков говорить, что CSSOv1 хуже gzip, от чего я меланхолично фейспалмил и ставил галочку в чёрном блокнотике.

2013 год
Март — моё категорическое нежелание продолжать работу с руководителем группы, в которой оказался, закончилось намерением либо уволиться, либо ротироваться, если найдутся желающие. Желающие нашлись, но уходил (возвращался) я в мир Java на совсем другие задачи. Так CSSOv1 был поставлен уже на физическую паузу.
Апрель — объявляю на внутреннем форуме Яндекса, что больше не могу поддерживать проект. Разработка CSSO велась в рабочее время, а не была ночным хобби. Мне ясны были чувства пользователей, но после 10-часовых рабочих дней потом ещё фигачить и такой непростой проект — нет. CSSOv2 был прикопан, участвовать в играх «проект важный и полезный, но ресурс на него мы выделять не будем» я не собирался.
CSSO стремительно устаревает. Я уже занимаюсь другими задачами, поддержки проекта почти нет (лишь редкие багфиксы и несколько релизов Gonzales), желающих подхватить знамя нет ни внутри, ни снаружи, пусть и были многочисленные призывы.
В этот же период постоянно слышу от людей о том, что такой важный и интересный проект обязательно вот сейчас-сейчас кто-то возьмёт на себя и всё станет хорошо. Были попытки войти в код CSSOv1 (но входящие быстро ломались), были единичные случаи фиксов, даже нашёлся разработчик, выдавший серию фиксов, чем меня восхитил и подарил [короткую] надежду. Но и только. Стало ясно, что в текущем виде CSSO доживает своё время.
В этот же период я получил здоровенную прививку от излишнего оптимизма, доверия и прочих штук. Вроде и так был злым, а тут стал ещё злее и циничнее. Тогда было неприятно от ряда ситуаций и диалогов, но сейчас понимаю, что всё закономерно и это просто надо было пережить, чтобы больше не попадаться.
Если 2011 год был годом победы, 2012 год годом поддержки и развития, то 2013 год стал годом «да ну вас нафиг».
Август — последний коммит.

2014 год
Разработка не ведётся. CSSOv1 умирает. Прикольный период танцев на костях. То одни бенчмарки показывают, что конкуренты (а надо заметить, после выхода CSSO этот «рынок» оживился и за минимизацию взялись с новыми силами) впереди-впереди, то другие показывают, что CSSO позади-позади. И вот уже с задних рядов улюлюкают, а с передних осуждающе смотрят в моноколь.
Тогда мне демонстративно было пофиг. Ну… Кажется прям совсем вот очевидным, что проект надо было развивать, чтобы он не остался в хвосте. И если проект (любой) не развивают, он устаревает. Для этого не надо быть семи пядей во лбу, это аксиома. Божечки, неужели после года-полутора-лет заморозки конкуренты впереди?! Да неужели! Да как же это случилось-то?! Если вам не пофиг, напишите петицию, вручите рулон подписей руководству, пусть выделит бюджет на разработчика. Одного хватало же. И сейчас один, к слову. Но гораздо прикольнее было кидать тапками, пока я ходил то к одному начальнику, то к другому, выпрашивая куски рабочего времени на хотя бы багфиксы.
Надеюсь, эта история чему-то полезному научила не только меня, пусть и выводы каждый участник сделал свои, безусловно.

2015 год
В октябре за разработку берётся lahmatiy (Роман Дворнов из Авито) и CSSO получил новую жизнь. Офигенно, что нашёлся кто-то, кто уже третий год тянет хороший же проект вперёд, во всём разобрался и всё переписал. Роман, если ты это прочтёшь, знай, ты крутой.

История CSSO, продолжение

Чтобы понимать всё дальнейшее в коде CSSOv1, надо принять следующее: за основу был взят OmetaJS и PEG. Регекспы спорны в поддержке, мы видели обработку CSS на их основе и глаз вываливается. Да и, напомню, нужна была совместимость на уровне AST.
Ни код, ни стоящие за ним идеи невозможно правильно понять, если не понимать, чем выбранная основа отличается от остального мира. Я потом неоднократно наблюдал, как приходит человек, смотрит исходник и убегает в ужасе с криками «что за бублец, это не код, это ад!» Да нет, не ад, но ведь даже Википедию сначала почитать ленились.
Потому основная работа с кодом всё время существования CSSOv1 делилась на две основных ветви.
Во-первых, парсеры CSS. На старте это не казалось прям сложным, но теперь понимаю, что задача «быстрый стабильный парсер CSS на JavaScript с учётом всех версий CSS и всех хаков CSS вместе с вендорными расширениями» — такое… При этом учитывайте, что V8 и Node.js тогда ещё не включали в себя нынешнее богатство оптимизаций. Именно эта ветвь стала самой интересной, проблемной и мозгоёмкой.
Во-вторых, поиск, каталогизация и изучение того бардака, что существовал и существует в вёрстке. Легко было выстрадать блок минимизации, обложить тюнингом, а после выпуска версии узнать, что в каком-то IE на какой-то платформе всё не так. Была переработана тонна информации, в курилках и вне оных пытались симферопольские фронтендеры (всегда с готовностью помогавшие, вспоминаю с благодарностью), обрабатывались репорты пострадавших. Шёл вечный бой.
Итак, до конца 2010 года велась подготовительная работа, которая в свою очередь разделилась на следующие этапы…
Во-первых, сбор, осмысление и описание того, что, собственно, собираемся минимизировать. Понятно, также должны были уметь то же, что конкуренты, потому и их методы были собраны воедино, а в дальнейшем и улучшены.
Во-вторых, писались разные прототипы. Надо было быстро обнаружить тупиковые пути и нащупать нормальные решения. Например, один из скриптов был создан только для того, чтобы посмотреть, как Node.js ведёт себя на тысячах и миллионах узлов дерева (фигово вёл, надо заметить).
В-третьих, собирался meta CSS — «язык», состоящий из всех спецификаций и диалектов CSS, ведь именно его и надо было парсить со всеми-всеми чудесами. Кажется, в какой-то момент во всём Крыму я был единственным человеком, который совершенно не умел верстать, но CSS знал чуть ли не лучше авторов.
Таким макаром пришли к точке, после которой уже можно писать продукт.

2011 год
Февраль — первый коммит работающего CSSP. Несколько наивная и прямолинейная реализация парсера, который даже в таком виде работал быстрее, чем созданный через OmetaJS. Тогда же было принято решение писать код, который с минимальными изменениями будет работать на всех JavaScript движках. Это позволило позже сделать и вебовую версию CSSO.
Март — интенсивное наращивание мяса на кости. В общем, ничего особо интересного или интригующего. Архитектура ясна, ТЗ понятное, прототипы обстреляны, бери и делай. Некоторое заметное время отобрали сотни тестов, в будущем себя это оправдало.
Апрель — релиз ранней беты и пост на Хабре. Приняли хорошо, дальше пошла рутина и началось общение с пользователями. Заодно пришла нужда отключать (!) структурные оптимизации. Если код, который минимизировал механически, работал понятно и без багов (потому его хотели использовать), то другой пока был с багами и открытыми вопросами.
Август — упоролся и написал пробный генератор парсеров. Назвал PeCode. CSSP себя изжил, с ним можно было запускаться, но в долговременной перспективе он был слабоват. Потому появился PeCode. Честно говоря, сейчас я уже не понимаю, что именно получилось. В одном проекте я проверял много разных идей, писал очень хардкорный код и в итоге решил, что ЭТО можно считать генератором. В любом случае он был быстрее и лучше CSSP, что двинуло нас вперёд.
Сентябрь — наконец-то CSSO действительно научился работать в режиме строго без структурных изменений. Месяц интересен ещё и тем, что он был последним в непрерывной работе именно над CSSO. Дальше перерыв на три месяца, я переключился на BEM plugin к IntelliJ IDEA.
Год был замечателен тем, что CSSO зашагал по планете. Его использовали на всех континентах, его начали пробовать в production’ах уровня Yahoo! и Google. Количество установок било всё новые рекорды. Чувство (и опыт) win’а такого уровня задают в дальнейшей жизни другую, новую планку целей. Могу совершенно точно сказать, что именно CSSO дал мне основу для развития и переосмысления. Ничего не было. Приходит один чувак с идеей. Приходит другой чувак с руками. Бац, сделали. Бац, сотни тысяч установок. Ы. Дикий Запад какой-то.

История CSSO, начало

В новостях похоронили PhantomJS, пошёл листать его историю, долистал до интервью, встретил CSSO и решил поднять старые записки. С каждым годом что-то забывается, а зря.
Наблюдаю за судьбой CSSO, мне нравится происходящее, но не нравится, что стартовую кодовую базу могут понять не так, как понимаю её я. Потому вот вам история. Как водится, это взгляд с одной стороны, с других сторон всё может выглядеть иначе (более того, не может, но и выглядит).
Для альтернативно читающих сразу обозначу следующее прямым текстом…
К той версии, что вы используете, я не имею никакого отношения. Она лучше CSSOv1, быстрее, написана иначе (фактически это на 95% другой продукт). Мой последний коммит был в августе 2013 года, после чего разработка временно заморозилась и продолжилась уже другими.
Эссе о том, почему CSSOv1 такой «странный», заодно байки о том как писался. Если вам покажется, что текст о другом, не надо меня об этом уведомлять, справляйтесь самостоятельно.

2010 год
Node.js существует всего год. Едва появился npm. Мира небраузерного JavaScript почти и нет. На этом фоне Виталий Харисов поднимает тему, о которой думает не первый раз (только лишь со мною была пробная попытка на C написать хоть прототип в 2007 году) — структурный минимизатор CSS. Популярные на тот момент минимизаторы представляли собою простые «выгрызатели пробелов», потому идея была богатая: в CSS овердофига избыточности, которую можно убирать, «понимая», какие свойства перекрываются, какие блоки объединяются и т.п.
Нюанс был в том, что 1) этим никто не занимался, 2) я чистый бекендер и про CSS знал лишь то, что это ужас и содомия.
Виталя добыл добро на разработку долгостроя, поставил технические требования, а я засел за спецификации, комбинаторику, теорию парсеров (в основном вокруг PEG) и трансляторов, ну и вообще стал активно вливать в себя чарующий мир вёрстки. После первых набросков стало ясно, что таки да, реализовать это можно.
В этот момент и были заложены архитектурные решения, которые сначала подняли CSSOv1, а потом похоронили. В итоге жарких споров решили, что AST должен быть удобным для OmetaJS (потому и упомянутая выше PEG) — на массивах. Эту точку считаю поворотной.
С продуктовой точки зрения решение верное. CSSO таким образом мог быть частью цепи преобразований, звеньями которой разные утилиты на базе OmetaJS трансляторов. Тут у нас валидация, здесь обработка метаязыков, там минимизация. С технической точки зрения такой AST как сам по себе стал тормозом, так и остальные операции тормозил. Мне не удалось тогда доказать это двум главным решающим фронтендерам, но какие сложные эмоции обуревали, когда потом уже другой разработчик в CSSOv2 напрочь выпилил совместимость, сделал нормальный AST и всё стало лучше.
Но… 2010 год. Можно сказать, что никто не пишет «серверное» на NodeJS, да и вообще JavaScript. Утилиты для фронтендеров похожи на свалку хлама в непонятном состоянии на разных языках для разных операционных систем. Какого-либо open source продукта, сделанного в единой идеологии, прошедшего кровавый production, состоящего из семейства полезных инструментов, просто не было. Фактически мы стояли на целине, что в разработке очень редко бывает.
Потому тогда сложно было сказать, что правильно, а что нет. Желания и энтузиазм точно были правильными. В эти настроения корнями уходят и будущие SVGO (начинал deepsweet в 2012 году) с IMGO (начинал banzalik в 2011 году), и первые утилиты для BEM, и многое другое. Так всё и завертелось. Виталя с коллегами вовремя увидел возможность, набрались разработчики, ну и целина начала вспахиваться.
Тут надо упомянуть ещё одну «тонкость», без которой фон некоторых решений в дальнейшем не будет полным. Код писался бекендером для фронтендеров на языке фронтендеров в стиле бекендеров. Хоть меня и убрали от живых людей и процессов (уже успел поругаться с важным в песочнице человеком), это нисколько не спасало от влетающих со стороны хотелок и поправок. Некоторые были хорошими, некоторые глупыми, но всё надо было учитывать и не всегда у меня получалось сделать правильный выбор или отстоять его. Также как по природной конфликтности, так и по объективным (как сейчас оцениваю атмосферу, причины и следствия) причинам разработка велась не всегда ровно — как тогда, так и сейчас мне непросто общаться с фронтендерами, это какой-то совершенно другой мир и совершенно другая школа разработки, от которой меня знатно морщит (подозреваю, им тоже не всегда было приятно иметь со мною дело). Запомните этот абзац, он будет особо упомянут в финальной части серии в выводах.