Тимлид в трёх лицах

Одна из вечных тем — что такое [хороший] teamlead? И вечные споры и дискуссии. Как водится, у меня своя точка зрения. Тимлид — набор из трёх ролей, который может быть хорошим в одной ситуации и плохим в другой. Эта неоднозначность и небинарность является, как считаю, причиной споров.

Психолог (люди). Решение психологических проблем команды, тонкая манипуляция, дипломатия, разнообразная мотивация, гашение конфликтов, подбор подходящих друг другу людей и т.д.
По сути это социальные навыки, soft skills. То, к чему должно быть расположение от природы, породы и анамнеза. Если у вас в быту не получается с эмпатией или вы непробиваемый эгоист (видящий всё сугубо через Я, Я, Я!), о роли психолога можно забыть. Тут прокачивать с нуля не получится, особенно уже сформированным личностям.
Примеры типичных задач:

  • Открыть рот и связно озвучить мысли так, чтобы было понятно, о чём речь. Без этого выше табуретки никак.
  • Открыть рот и звуками убедить кого-либо в чём-либо так, чтобы этот кто-либо понял, захотел, сделал. Первый шаг к тимлиду.
  • Подбор подходящих коллективу людей. Не запихивать тихонь в клетку с тиграми, не топить тигров в пруду тихонь.
  • Выслушивать. Очень важное умение, дающееся не всем. Слушать не себя, не перебивать, запоминать слова, интонации.
  • Объяснять, почему повышают или не повышают. Не самая приятная обязанность, но надо.
  • Донести критику или одобрение. Как, собственно, самому уметь принимать как одно, так и другое.
  • Управлять конфликтами. Они были, есть и будут. Люди не травоядные и некоторая доза конфликтов даже нужна. Задача психолога не допустить их перехода в системную проблему.
  • Определять человеческие факторы производства и понимать, что с ними делать дальше. Вася апатичен и вяло работает? Почему? Он изначально такой или есть внешняя причина? О, так он сова, а его запихнули в жёсткий утренний график. Давайте попробуем его на вторую половину дня. Попробовали, Вася начал отжигать напалмом и повеселел.
  • Внедрение мотивации в членов команды. Федя слабо работает. Если Феде доходчиво объяснить цели, выгоды и соответствие работы ценностям Феди, он будет работать сильнее. Или не будет. Феди всякие бывают.

Тимлид работает с командой и организует команду. Команда — люди. Человек, у которого психолог на нуле или даже в минусе, успешным тимлидом быть не может. Это просто невозможно.


Логистик (процессы). Понимание и выстраивание процессов производства. Спектр задач тут большой и включает в себя много всякого разного ранга: схема статусов у тикетов согласно проекту, элементы CI, распределение зон ответственности, протоколы безопасности, чеклисты реакции на мониторинг, организация нужных встреч, контроль планов и само планирование, и т.п., и т.д. Фактически всё, что является дорогой между пунктами A (задумка продукта) и Z (продукт в production’е).
По сути это навык организации, который начинается с самоорганизации. В какой-то мере тоже личностная характеристика в основе. У человека должно быть стремление к упорядочиванию окружающего, да и внутреннего. Чёт не верю я в раздолбаев, успешно спроектировавших и построивших сборочный цех софта. Подчеркну — речь о повторяемом процессе, а не про одноразовый [случайный] win.
Примеры типичных задач:

  • Организовать коммуникации внутри команды и команды с внешним миром. Живые встречи, каналы мессенджеров, рассылки, знакомство людей друг с другом.
  • Организовать отчётность (срезы статуса) как по отдельным задачам, так и всего в целом. В любой момент должно быть понятно состояние системы.
  • Организовать инфраструктуру производства. Где разработка, где тестирование, где боевые сервера, где сборочные фермы и т.п.
  • Определить зоны ответственности. Не должно быть кода, серверов, задач и любого иного, над чем не стоит конкретный человек с пониманием, что это его песочница, за успехи в которой хвалят, за поражения ругают.
  • Спланировать разработку продукта. Ох, планирование, да. Отдельная огромная тема.
  • Определять и убирать слабые звенья. Например, регулярные формальные встречи, на которых все зевают или играют в Тетрис под столом.

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


Специалист (разработка). Глубокое знание предметной области, контроль качества реализации продукта. Пожалуй, самая очевидная и самая распространённая роль из-за обычая брать тимлидов из среды разработчиков.
Хоть я ниже допускаю вариант слабого специалиста (и его компенсации) в тимлидах, но это больше теория. На практике всё сложнее. Если тимлид тотально слабее в матчасти своих бойцов, он не может выполнять чуть ли не половину функций — не научит, не проверит, не проконтролирует. Как если первоклашку поставить ведущим разработчиком на уроках матана девятого класса, много он там со своими счётными палочками наводит, ага.
Но есть ещё нюанс. По миру ситуация меняется, а вот на просторах xUSSR команды разработчиков всё ещё в массе мужские со всеми приметами мужского коллектива. Разработчики не будут уважать тимлида, если он не является в какой-либо смежной области заметно более сильным специалистом. Не примерно равным, но заметно более — это важно. Может, всё-таки и будут, но не как разработчика. А без уважения всё становится сложнее. Хочешь не только по трудовой быть тимлидом? Изволь спросонья озвучить лекцию по булевой алгебре и вариантах рекурсии. Нет? Удачи.
Примеры типичных задач:

  • Разработка софта. Если программист не программирует, он теряет квалификацию.
  • Определение стратегии технического развития. Примитивный пример: вводить ли в стек новый язык?
  • Определение квалификации членов команды. Надо понимать, можно ли давать Петрову задачу по проектированию схемы данных из ста таблиц или Петров не знает, что такое primary key (очевидно, сам тимлид должен быть на уровне задачи).
  • Подтягивание квалификации членов команды. Как быть ориентиром (наш Вася крутой, я хочу стать крутым, учусь у Васи быть Васей), так и микролекциями, литературой, дискуссиями, кодом и т.д.
  • Ревью кода и решений. Тимлид должен понимать и уметь в хороший код, чтобы контролировать создание оного членами команды.
  • Обеспечение или контроль инфраструктуры производства и продукта в рамках компетенции. Оптимально ли настроена база данных? Те ли типы инстансов в облаке? Куда и как складываются логи? Почему так долго собирается билд?

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


И вот тут проблема: людей, совмещающих в себе все три роли на высоком уровне, [почти] не бывает. Хотел бы сказать, что их вообще нет, но остерегусь, мало ли. Общение с компьютером с детства развивает специалиста, но не способствует росту психолога. Психолог развивает с друзьями модные soft skills, пока на полке пылятся так и не открытые учебники по программированию. Логистик рождается в муках опыта, наблюдений, размышлений и снова учёбы.
Я пока видел только два действительно работающих способа решения.
Во-первых, в Яндексе боевые пары, которые забавно напоминают ролями семью. Менеджер (часто девушка) — психолог+логистик, тимлид (часто мужчина) — специалист+логистик. Соответственно, вдвоём они представляют собою универсального лида. Менеджер (мама) утирает слёзы, смягчает конфликты, обеспечивает социализацию команды, организует логистику продукта, организует само понимание продукта (а то эти роботы без тени сомнения напишут двумерного коня в кирпичном эфире), служит посредником между командой и внешним миром, напоминает команде о пользователях, вообще душа и человечное лицо команды. Тимлид (папа) организует разработку проекта, карает и поощрительно трогает плечо, сам укладывается под танк на амбразуру авралов, укладывает других, корректирует планы согласно уровням разработчиков. Если сработались, результат офигительный. Если нет, всё идёт на дно и по дну, в чём и риск такого варианта относительно единоличной диктатуры.
Во-вторых, подбор команды под тимлид(а|ов). Если нет умения или желания возиться с психологией, набор зрелых взрослых людей без явных проблем с головой — это делает ненужным развитого психолога. Если слабый специалист в лидах, набор строго сильных разработчиков, которых не надо контролировать или выращивать — лиду достаточно не вмешиваться. Если проблемы с логистиком, набор опытных (сильные не всегда опытные, потому набор выше из другой оперы) разработчиков, они сами организуются — слабый логистик там же и обучится.

Стремящийся стать хорошим тимлидом понимает свои слабые и сильные роли. Плохой не понимает.
Плохой психолог устраивает показушные игры в «давай поговорим» или «вы можете подойти ко мне с любым вопросом». Хороший и так знает / чувствует, что происходит, а с вопросами к нему и без напоминаний подойдут. // Я, к слову, фиговый психолог, но все и так знают, что злобное бревно. Компенсирую тем, что пытаюсь выстроить процессы, при которых в психологе нет нужды — ясные правила поощрений, тщательный подбор адекватной команды, прозрачность всей работы всех и т.п.
Плохой логистик тащит всё хайповое как сорока в гнездо. Вчера у нас был водопад, сегодня скрам, завтра коворкинг на хакатоне с интенсивным митапом тренеров по TDD без ТЗ. Другой вариант плохого в силовом напяливании идеалистических схем на неподходящий коллектив. Да, отверстие круглое, а болт квадратный, зато я сильный. Хороший делает так, что именно эти люди делают продукты именно этой категории максимально эффективно с учётом ротации кадров, фазы Луны и законодательства Гаити. Если не получается, оставляет всех в покое и смотрит, какую схему выработает команда — сначала смотрим на народную тропинку, а потом на её месте асфальтируем дорожку.
Плохой специалист всем просто мешает. Арнольд два дня оптимизировал тяжёлый запрос к базе, а тимлид зарезал, так как не понял текст запроса (ридабилити пострадало! скорость нинужна!). Плохой специалист не может аргументировать решения, потому тупо насаждает свои субъективные вкусы. Хороший специалист не мешает команде, особенно если команда решает задачу по результату лучше, чем сам смог бы. Также он каждое своё решение объясняет так, что решение становится очевидным. В конце концов, если чего не знает, так и говорит: да хрен его знает, разберитесь сами, потом меня научите.

Безусловно, всё ещё сложнее на пару порядков, всегда есть исключения и всё такое. Но мне схема выше удобна простотой и практичностью модели, от которой я могу отталкиваться, не затрачивая недели на принятие решений или на понимание явлений.
PS. Тем, кто обратил внимание на то, что по тексту в Яндексе менеджеры девушки, скажу следующее (и это нередко упоминалось в беседах с коллегами) — в Яндексе [не]удивительно много умных, энергичных и красивых женщин. Мне приятно называть их именно девушками.

Python и попкорн

Не всегда получается донести до собеседников причину, по которой я смотрю на мир Python с попкорном в руках. Попробую тут.
Сразу две вводные.
Python — инструмент. Если в нём что-то не устраивает, скорее всего, вы применили инструмент не к той задаче. Oy vey iz mir! Я написал на Python прошивку к реалтаймовому процессингу на карточных чипах, а оно не работает! Плохой, плохой Python! Очевидно, дело не в языке, но в ДНК специалиста. У правильно применяющих всё хорошо. У них, впрочем, и с BASIC хорошо будет. Голова на плечах рулит.
Python — не универсальный инструмент и не панацея от криворукости (уже писал, что на самом деле писать хороший код на Python сложнее, чем на Java/C++), но из-за кажущейся простоты порога входа получил армию фанатов. Часть критики Python вызвана желанием потыкать палочкой этот вот детский сад, для которого нет большего счастья и радости, чем не указывать типы. Так вот, это эссе не критика, не замахивание на святое и не всё то, что желает читать стремительно наполняемый кровью мозг.

Потреблению попкорна способствует история Python 3 и поддержки оной версии сообществом. Сегодня у меня в очередной раз всколыхнулся потому, что хотел почитать логи MongoDB более цивилизованно (aka с помощью mtools). Открываю, вижу «mtools is not currently compatible with Python 3», закрываю.

Шёл 2006 год (12 лет назад он был). Гвидо создаёт PEP 3000. Или лучше назад отойти? Не понять, какой год считать годом появления Python 3, т.к. Гвидо о нём думал ещё раньше. Скажем, в 2004 году запостил флеймообразующий постик «Optional Static Typing to Python» (у питонистов тогда знатно глаза и пальцы разгорелись, понадобились умиротворяющие постики). Как ни крути, но если вам кажется, что Python 3 — что-то новое, ну вот пару-тройку лет назад появилось, то нет. Более того, уже в декабре 2008 года был выпущен Python 3.0 final.
Добавлю фона для сравнения.
Kotlin — разрабатывается с 2010 года (думаю, всё-таки раньше начали), первый релиз в 2011 году. Swift — разрабатывается с 2010 года, первый релиз в 2014 году. Go — разрабатывается с 2007 года, первый релиз в 2009 году. Rust — разрабатывается с 2006 года, первый релиз в 2010 году. Эти даты должны вам помочь увидеть живую практику других языков. За 2..4 года разработка, воодушевлённый народ начинает фигачить вовсю тоже уже через 2..4 года, хоть у Swift особенный кейс, там один вендорный язык для вендорной платформы заменяется другим, потому особо выбора не было.

Что же произошло с 3.0? А ничего. Он сразу утонул под критикой. Вот удобная известная статья, в которой всё основное собрано. Шли годы. Вышел 3.1 (2009), 3.2 (2011), 3.3 (2012). Воз стоял на том же месте. Питонисты всё так же расползались по двум лагерям. В основном (я обгуглился переписок, интервью и прочего тех лет) война шла на трёх фронтах.
Во-первых, критиковали производительность. Бенчмарки, в которых 3.x был заметно медленнее 2.7, взывали к разуму. Но… матёрые сторонники прогресса (да и Python’а в целом) отбивались аргументом «нам и не надо!» С технической точки зрения аргумент настолько меня забавляет, что детализирую. Вот хороший пример — Python норм, проблема не в нём, а если в нём, напишите важное на C/C++ или юзайте Cython. Знаю немало питонистов. Живых таких реальных мужчин от 20 до 35 лет возрастом. С удовольствием представляю, как они пишут быстрокод на C/C++, ага. Гвидо, между тем, придерживался той же аргументации (говорящий заголовок статьи: «Van Rossum: Python is not too slow»):

It is usually much more effective to take that one piece and replace that one function or module with a little bit of code you wrote in C or C++ rather than rewriting your entire system in a faster language, because for most of what you’re doing, the speed of the language is irrelevant.

Я б добавил, что разумнее сразу писать на чём-то, что потом не потребует внедрения ещё одного-двух языков в стек, но это наверняка будет гораздо менее выразительно, чем писать на Python. В любом случае репутация 3.x была подмочена, т.к. столько лет делают, а везде и заметно быстрее не стало.

Во-вторых, несовместимость. За то, что 3.x не собирался поддерживать выполнение кода 2.x, Гвидо был виртуально бит задолго до релиза 3.0, но стоял на своём упорно. Мигрируйте и будет вам счастье, даже сделали 2to3, всех проблем не решавший, но всё же. Один фиг предполагалось, что вы просмотрите глазами весь свой исходник. И ладно бы, но как быть с мегатонной библиотек? Что вам радости, если 80% всех зависимостей совместимы с Python 3, а 20% нет? Должны быть 100%. Как итог, каждый уважающий себя питонист раз в неделю ходи(л|т) на py3readiness.org, проверяя, ну когда же, ну блин же. И если в Java/C++ 99.99% проблем миграции вам укажет компилятор, то в Python не так. При неудачном забеге звёзд вполне можно получить выстрел в рантайме просто потому, что в какой-нибудь уголок забытый не заглянул глазами, не потрогал руками.
В-третьих, нафига? Линейных разработчиков вопросы стратегии и legacy не волнуют. Их волнует, чтобы переход с X на Y был пыщ-пыщ. А Python 3 сумму пыщ-пыщ добрал лишь вот относительно недавно. Версия 3.6 (конца 2016 года) в сумме с возможностями предыдущих версий выглядит прям вот интересно и убедительно. Правда, с опозданием. Я не зря выше остановился на 3.3. Кажется, что это версия, на которой в умах произошёл надлом. Четыре года от первого релиза, а лучше не стало. Работает медленно. Никаких увлекательных свистелок-перделок, которыми можно заманить жаждущих хлеба со зрелищами. Планетарная миграция даже не началась, да и куда мигрировать, если вы сидите на версии Django, которую никто даже и чесать не собирается? В общем, всё плохо. И вот это «всё плохо» в головах устаканилось намертво.

И всё. Сообщество знатно затвердело. Как одни слепо за Путина, а другие слепо за Навального, так и тут. Можно хоть монтировку согнуть об иные лбы, но лбы совершенно искренне не будут понимать, зачем им Python 3. В их мире Python 2.7 вечен, Python 3 вечно медленный (это давно не так), не поддерживается (это давно не так), в нём нет прикольных фич (это давно не так). В 2018 году (спустя 10 лет релиза!) мир вовсю осваивает четыре новых языка, но мир питонистов до сих пор не может перейти на тройку. Ну вот никак. Это постоянный цирк и бардак. Самый распоследний 2.7.x вышел в конце 2016 года. Ветка не поддерживается, ветка не развивается. Всё равно будем держаться за неё до последнего!
В финале докину ещё примеров того, как в стороне от цирка развивается планета. С 2011 года по 2017 год вышли C++11, C++14, C++17. Вышел PHP7 в 2015 году. Вы [не] будете смеяться, но даже успели выпустить стандарт Fortran 2008 и вот-вот доработают Fortran 2018 (ранее Fortran 2015). Ужасный, медленный и кровавый мир Java успел выродить Java 7, 8 и 9 (позавчера и 10). А, да, первый релиз MongoDB вышел в 2009 году. Блокчейны… криптовалюты… квантовые процессоры…
А Python 2.7 (ветка началась в 2010 году, напомню) вовсю в production’е. И до фига живых людей не хотят от неё отказываться. Потому со стороны вся эта смешная история и смотрится с попкорном. Слишком уж в разрыве от общей практики происходит, слишком фанатично (aka не профессионально) воюет сама с собою эта часть сообщества, чтобы не превратиться в многолетний анекдот.
PS. Да, на собеседования приходят питонисты, которые заранее говорят, что Python 3 не знают совсем. Его нет в их текущей работе, а вне работы причин узнать не было. Радуюсь. Восхищаюсь.
PPS. Полтора года назад уже затрагивал тему, но чуть иначе и менее ссылочно. Не могу сказать, что всё кардинально изменилось. Не-а.

Miscellanea XIX

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

Вот занятно. До последнего поколения у языков были авторы-люди. C++ создал Страуструп, C создали Ритчи и Томпсон, Python Гвидо, Java Гослинг и т.д. Сейчас время больших батальонов, что косвенно выражается в уходе личностей за ширму. Да, у любого языка есть конкретные авторы, но Go — это Google, Swift — Apple, Rust — Mozilla, Kotlin — JetBrains. И вроде объективно ничего не изменилось, раньше языки тоже появлялись или активно развивались внутри компаний, но вот.

Между тем, в мире разворачивается драма из высших уровней кровавого энтерпрайза. Раскручивать содержание темы можно от Phoenix Pay System, ленивым кратко перескажу. В 2009 году правительство Канады решило заменить свою 40-летней давности систему начисления и выплат зарплат, ну и вообще автоматизировать и экономить. Выбор пал на IBM с Oracle. Пацаны вроде крутые, опытные, будет счастье. В 2016 году систему запустили, с тех пор мечтают погасить, ибо бракобажище получилось лютейшее, что при общих тратах бюджета в $790M несколько фраппирует канадскую общественность. С другой половины планеты одобряюще улюлюкают австралийцы, наступившие на эту мину ранее. Оба кейса интересны тем, что большой бизнес может по контракту поставлять неработающие решения за огромные деньги и не пострадать. Совсем другие правила игры.

ALGOL любопытен тем, что этот язык очень, очень повлиял на развитие программирования, но при этом почти не использовался в разработке. Даже была шутка 60-х: ALGOL нужен для того, чтобы описать алгоритм, а потом реализовать его на FORTRAN. Одна из основных причин, если верить копипасте из статей в статьи — чуваки не стандартизировали I/O, что для промышленной разработки фу и кака. Ситуацию в какой-то мере выправляли диалекты (вроде ALGOL W), но язык это не спасло. Как был очень влиятельным, но академическим, так и остался.

Иногда встречаю разработчиков, которые считают, что знают Java, если у них опыт работы и знание Java 7, не дальше. Народ. Между Java 7 (2011 год) и Java 8 (2014 год) пропасть (стримы, лямбды, default и static в интерфейсах, новый Time API и т.д.). В 2018 году вообще уже пора Java 9 осваивать и про Java 10 думать. Хочется спросить, почему за 4 года вне работы, если она прибила семёрку гвоздями, не освоил изменения? Пофиг было? Тогда зачем «джавист»? Не надо так.

1Z0-808 (Java SE 8 Programmer I)

1Z0-808 (Java SE 8 Programmer I) — сертификация начального уровня от Oracle, без которой не допустят до остальной линейки. Хоть весной уже и Java 10 выйдет, тесты пока не обновляют, у Oracle с этим туго. Потом можно будет сдать отдельный update.
70 (не 77, как иногда пишут) рандомных вопросов, 150 минут, проходные 65%. Темы про основы самого языка без вопросов о множестве библиотек (это счастье на следующих уровнях), достаточно знать лишь десятка два распространённых в быту классов. Во время сдачи никаких гаджетов, интернета, IDE, компилятора и т.п. Вас даже рукава попросят закатать, проверяя отсутствие шпаргалок. Пользоваться только головой.
Хоть уровень и junior, без подготовки могут быть сюрпризы. Java местами не самый очевидный язык, есть как формально верные, но неиспользуемые части (про них спросят), так и то, что понять не получается, надо просто запомнить в идеале именно так, как в JLS сказано.

Литературная подготовка включала в себя только чтение OCA Java SE 8 Programmer I Certification Guide — чтение унылое, скучное, но обязательное. Книга хороша тем, что настраивает голову на нужный лад. Вы многократно повторяете материал и знакомитесь с примерами вопросов для того, чтобы привыкнуть (это важно) к характеру сертификации. С этим управился за 18 дней.
Также купил mock exams у Enthuware. 600+ вопросов, потому развлечение эдак на 10..12 часов. Подспорье крутое, тут претензий нет, очень советую не пожалеть почти 600 рублей (ага, по рублю за задачку).
Во-первых, повторение материала, но с другого угла. Некоторые темы после марафона подготовки у меня от зубов отлетают — на задачу не более 15 секунд тратил.
Во-вторых, некоторые задачи там специфические. Их не должно быть на экзамене, т.к. нет в списке разделов от Oracle, но людям попадались.
В-третьих, смирение. Невозможно не впасть в оное после десятков задач, «сложность» которых сугубо механическая и на внимательность. Плохое форматирование, нетрадиционный порядок кода, запутанность имён, череда арифметики в циклах. Легко можно выбрать неверный ответ только потому, что в варианте не заметили замены двойной кавычки на одинарную.
В-четвёртых, уровень. Задачи качественно и количественно сложнее, чем на сертификации — часть времени и сил потратите на то, чего не будет в бою. Но если даже с учётом этого уверенно во всех тестах набрали проходной процент, значит, можно двигать на настоящую сдачу.

Проходил 15 марта в Softline. Сдал успешно на 95% за полтора часа. Боевой экзамен оказался настолько лёгким после подготовки, что я каждый вопрос раз пять вычитывал, выискивая хитрые подвохи. Но нет, подвохов почти и не было. Те три вопроса, в которых ошибся, сугубо из-за лени — влом было зазубривать прям вот до пуговки Time API, за что и поплатился.

22 дня на подготовку, в среднем полтора часа в сутки. 700 страниц учебника, около 750 тестовых задач, около 100 страниц дополнительного материала (JLS, статьи, Javadoc к JDK), почти 14000 рублей.

Книги: OCA Java SE 8 Programmer I Certification Guide

oca
Mala Gupta.
OCA Java SE 8 Programmer I Certification Guide.
Manning Publications, 2016.
Очень специфический 700-страничный талмуд. Это не учебник. Это не мануал. Не шпаргалка. Не справочник. Это многократный унылый пересказ поднабора основ языка Java, который включается в темы первой сертификации Oracle. Прописные истины и базовые знания вам будут на каждой странице повторять, повторять, повторять, повторять, повторять.
Иными словами, текст заточен на то, чтобы заточить вас ровно на сдачу сертификации, не более. И в немалой мере задачу решает. Вы вспомните / узнаете некоторые неочевидные штуки, прорешаете 140+ тестовых вопросов (включая финальный экзамен в конце), привыкнете к мысли, что ЭТО просто надо пережить, а потом забыть как страшный сон. Как минимум, узнаете, как может выглядеть упоротое тестирование.
Фигня в том, что действительно все темы глубоко не покрываются, как мне показалось, или же не был сделан акцент. При прохождении mock exams от Enthuware эти лакуны всплывают, потому не рекомендую использовать Guide как единственный источник подготовки. Обязательно в комплексе с чем-нибудь ещё.
Книга полезна только тем, кто готовится к сертификации. Остальных она может отвратить как от чтения в целом, так и от языка.

История 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, и многое другое. Так всё и завертелось. Виталя с коллегами вовремя увидел возможность, набрались разработчики, ну и целина начала вспахиваться.
Тут надо упомянуть ещё одну «тонкость», без которой фон некоторых решений в дальнейшем не будет полным. Код писался бекендером для фронтендеров на языке фронтендеров в стиле бекендеров. Хоть меня и убрали от живых людей и процессов (уже успел поругаться с важным в песочнице человеком), это нисколько не спасало от влетающих со стороны хотелок и поправок. Некоторые были хорошими, некоторые глупыми, но всё надо было учитывать и не всегда у меня получалось сделать правильный выбор или отстоять его. Также как по природной конфликтности, так и по объективным (как сейчас оцениваю атмосферу, причины и следствия) причинам разработка велась не всегда ровно — как тогда, так и сейчас мне непросто общаться с фронтендерами, это какой-то совершенно другой мир и совершенно другая школа разработки, от которой меня знатно морщит (подозреваю, им тоже не всегда было приятно иметь со мною дело). Запомните этот абзац, он будет особо упомянут в финальной части серии в выводах.