Микросервисы — отчуждение от результатов труда
Дисклеймеры
- Кому-то данная статья покажется стёбом. Если вдруг вы обнаружили себя в этой категории, попробуйте вспомнить старый афоризм “В каждой шутке есть доля шутки”. Может быть, это поможет вычленить ту самую долю.
- Было бы интересно подискутировать с кем-то по сути, а от споров по частностям (в том числе описанным в статье) буду дистанцироваться.
В общем, кого мог — предупредил. Приступим…
Поветрия
Я наблюдаю за развитием IT в течение приблизительно четверти века, и с каждым днём меня всё сильнее удручает происходящее.
Постоянно мы слышим, что какой-нибудь паттерн или язык становится всё более модным, а что-то, напротив, — уходит в историю. А ещё различные поветрия о “хорошо или плохо” будто волнами перекатываются через это вот всё.
Кто-нибудь скажет, что это — естественный ход событий — просто одна технология заменяет другую. И он будет прав и неправ одновременно.
Увы, новые вещи (коих не так чтобы вообще есть1 всё чаще приносят с собой и очевидно деструктивные, будто навязываемые извне, паттерны.
В прошлом частота таких деструкций была невысокой, но выглядит так, что она нарастает по экспоненциальной кривой.
В этой статье я хотел бы поговорить о причинах происходящего.
Однако, чтобы обсуждать предпосылки, нужно сперва сформулировать или описать само явление. Поэтому начнём со сравнительно далёкого прошлого.
В общем, как-то раз один с виду вроде бы неглупый человек ляпнул в
публичном пространстве совершенно необоснованное суждение “о вредности
оператора goto
”2.
Начавшаяся после этого вакханалия растянулась более чем на полвека, а количество ущерба, нанесённого этим поветрием, настолько велико, что приходится дистанцироваться, чтобы его обозреть.
Миллионы адептов — отрицателей goto
до сих пор наводят ужас на
окружающих. Десятки новых языков программирования остались инвалидами,
поскольку ещё на стадии дизайна не включили этот оператор в свой набор.
В итоге в обществе сложился устойчивый стереотип:
—
goto
— зло!— Почему?
— Ведёт к запутанному коду!
— А ведь есть случаи, когда, напротив, — полезно, что с ними?
— Даже если и так, всё равно,
goto
— ужасный оператор, ему не место среди порядочных людей!
Именно Дейкстра был основателем первой крупной секты хейтеров
нормальной, в общем-то, технологии. В результате миллионы людей осудили
инструмент только потому, что какой-то “авторитет” что-то там сказал. И
им плевать на то, что такие вещи, как высокоскоростные однопроходные
парсеры или, например, код, выполняющий зависимую инициализацию и
деинициализацию нескольких ресурсов, пишутся с goto
так, что
по-другому лаконичнее и эффективнее не сделать!
Событие, принёсшее нам практически всенародную ненависть, направленную
на goto
, — пожалуй, самое яркое и длительное по времени, но, увы, не
единственное.
Поветрия, моды, снова поветрия… Следуя одно за другим со всё более увеличивающейся частотой, они приводят к тому, что многие хорошие и полезные вещи оказываются либо утрачены, либо заклеймены, либо (что самое поганое!) замещены их отрицанием.
Помимо уже довольно устойчиво вбитого в головы штампа “goto
— это
плохо”, мы окружены множеством других, не менее деструктивных.
Взять, например, современное “Статическая типизация — хорошо, динамическая — плохо”. И эта чушь началась прямо в тот момент, когда, казалось, были все шансы, чтобы языки программирования встали в один ряд с человеческими! Мда…
А ещё в наше пространство вторглись линтеры, не только верифицирующие код на предмет возможных ошибок (что в целом хорошо), но и указывающие нам, “сколько пустых строк ставить между блоками”, или “в каком порядке импортировать модули3!”
Кстати, поветрие о преимуществах статической типизации, как мне кажется, растёт оттого, что для неё проще писать линтеры. Других разумных объяснений нет.
Впрочем, каталогизация поветрий и мод — тема отдельной статьи (и я планирую её как-нибудь написать), а здесь я больше хотел поговорить об очередной современной напасти — о микросервисах.
Но прежде чем мы до них доберёмся, ещё немного лирически отступим и добавим в контекст рассмотрения некоторое количество вопросов иного плана.
Фрагментация мышления
Помимо поветрий, всё больше бросается в глаза усиливающаяся фрагментарность мышления среднестатистического программиста.
Причём, мне кажется, что причины этого явления и обсуждаемых выше поветрий одни и те же.
Фрагментарность мышления выражается в склонности программиста зацикливаться на частностях или мелочах, не глядя на картину в целом.
(Вообще проблема касается не только программистов, но, поскольку мы говорим о мире IT, ограничимся пока этим подмножеством)
— А этот тикет вы зачем (сами себе) написали?
— Это же технический долг!
— Почему вы считаете это долгом?
— Если доделать так, как здесь написано, то функция вместо 6 миллисекунд будет выполняться 600 микросекунд. Круто же?
— Нет.
— Почему?
— Потому что эта функция запускается один раз в сутки. Даже если время её исполнения будет равно 600 секундам, то это всё равно будет устраивать абсолютно всех пользователей.
Общаясь с десятками и сотнями программистов, я отчётливо вижу корреляцию: именно люди с фрагментарным мышлением наиболее склонны поддерживать поветрия (и наоборот).
Рассмотрим ещё пример. Движение к лучшей утилизации имеющихся ресурсов привело IT к широкому использованию асинхронных парадигм программирования, а они, в свою очередь, не могли не дать новых языков программирования.
И вот, крупная международная корпорация, для разработки нового
инструмента привлекает одного некогда умного, но ныне довольно
старенького, ставшего маразматиком, специалиста. И всё бы ничего, но
только он толкнул в массы новую “мегаидею” (по аналогии с “goto
— это
плохо”): “Исключения — это плохо!”4.
И теперь тысячи — нет, уже миллионы — программистов в каждой первой функции пишут повторяющийся код, засоряющий пространство на экране:
func foo(a, b string) (int, error) {
// весь мусор про `err` мог бы быть реализован компилятором
res, err := bar(a, b)
if err != nil {
return 0, err
}
return res + 1, nil
}
func bar(a, b string) (int, error) {
// весь мусор про `err` мог бы быть реализован компилятором
res, err := baz(a, b)
if err != nil {
return 0, err
}
return len(a) + len(b), nil
}
Если вернуться к фрагментарности мышления, то крайне характерно, что один и тот же разработчик будет, с одной стороны, с пеной у рта утверждать, что исключения — это плохо и в Go всё сделано правильно, а с другой — не будет видеть целого за частностями (прикладывая массу усилий к улучшению фрагмента, не думая об общем).
Как докопаться нам до истинной причины? ©
Внедрённая в коллективные мозги глупость “исключения — это плохо” привела к тому, что уже минимум два весьма популярных языка построены на этом базисе.
Скольким людям теперь не удастся “за деревьями увидеть леса”? Страшно помыслить!
Может показаться, что все эти поветрия придумывает какой-то злобный гений, однако, несмотря на то что у каждой гадости, происходящей в IT, есть фамилия, имя и отчество её автора, не будем ударяться в теории заговора и попробуем подобраться, наконец, к теме статьи.
Итак: несколько лет, раздумывая над истоками описанных выше проблем, я никак не мог найти объяснения, почему прекрасные, заставляющие понимать, что ты делаешь, парадигмы вроде TMTOWTDI5 постепенно замещаются их отрицанием6. Почему, реализуя крайне своевременную идею языка с асинхронной парадигмой на борту, добавили полбочки дёгтя — забыли о KISS-принципе7. Будто специально, решили ломать психику неокрепшим умам?
Ну ладно бы только Golang пострадал, но эта фигня теперь везде: возьмём тот же Rust, там — то же самое8! И это, как говорится, — ещё не вечер!
(Всё-таки придётся как-нибудь написать статью с подробным перечнем всех деструктивных поветрий, выплеснуть, так сказать, и заодно припомнить, “что они сотворили с фронтендом”…)
Однако я снова пытаюсь отвлечься. Вернёмся, наконец, к теме.
В общем, у меня долго не получалось найти рациональное объяснение происходящему, но однажды мне его буквально на пальцах растолковал… один из технических топ-менеджеров Яндекс.Такси, где я когда-то работал. История эта уже древняя, потому, думаю, вполне можно рассказать, никого не задев.
С точки зрения IT Яндекс.Такси — это такая компания, где и десять лет назад уже трудился значительный коллектив разработчиков. В то время, когда я там работал, она занималась довольно широким спектром технических задач: автоматизацией собственно такси, разработкой сервисов о еде и прочим…
А, в частности, — наймом водителей, ведь для своей работы бизнес такси требовал целую армию исполнителей, которую различными способами рекрутировали, постоянно преодолевая её естественную убыль.
На то, чтобы организовать найм водителей, компания в те годы ежемесячно тратила приблизительно миллиард рублей. В целом всё было хорошо: миллиард уходит на найм, а (условно) десять — зарабатывается. “Бабки крутятся, прибыль мутится” — все (в том числе собственники) довольны…
Однако в какой-то момент случилось не то чтобы ЧП, но что-то подобное, и в тот раз почему-то не вышло этот самый миллиард на найм выделить. То ли слияние компаний проводили, то ли реорганизацию. В общем, бюджет порезали, и вместо миллиарда выделили всего двести миллионов.
Надо сказать, что решая “сократить этот кост на один месяц”, руководство понимало серьёзность и последствия такого действия. Все отдавали себе отчёт, что будет просадка и в следующем месяце обязательно придётся увеличивать расходы.
Но вот беда — просадки не случилось! Месяц закончился, и вообще ни одна бизнес-метрика не пострадала: наняли ровно столько же, сколько в предыдущем.
Видя это, бизнес, разумеется, задался вопросом: “А стоит ли вообще каждый раз впихивать в этот найм по миллиарду? Может быть, и двухсот миллионов достаточно?”
Поскольку речь шла о сумасшедших суммах, то в срочном порядке собрали команду, которая должна была помочь понять, что происходит. Таким образом, туда попал и я — как технический исполнитель.
Взглянув на проблему и на техническое обеспечение этого самого найма (заглянув в код, пообщавшись с разработчиками), я сразу предложил чуть доработать рабочие места: операторов кол-центров, педагогов, инструкторов, а также лендинги, добавив в них этакий аналог метрик.
Метрики в чистом виде не подходили: требовалось разобраться с длинными цепочками, а для этого необходимо было удерживать связи между сущностями. В общем, чтобы выполнить нужные замеры и подсчёты, я решил взять любую базу данных (например, PostgreSQL) и записывать в неё происходящие события вместе с идентификаторами (будущих) водителей, операторов и т.п. Подождав месячишко, пока накопится статистика, я планировал поделать из неё выборки, отвечающие на вопросы бизнеса.
Просто же всё? И вот пришёл я с этим “просто” к тому самому топу.
— Здесь достаточно одного программиста, — начал я, — он за день (ну, хорошо, округлим до недели) сделает функцию, записывающую событие в БД. Большого количества полей в записях не требуется: тип, время, связь с нанимаемым водителем и связь с исполнителем. В общем, работа очень простая, могу даже сам запилить: тут строк пятьдесят кода. Затем, — продолжил я, — мы обойдём все формы и бакенд, добавляя http-запросы, генерирующие это событие, — и вуаля! В конце следующего месяца отчёт готов!
— Не пойдёт.
— Почему?
— Вы не сможете получить разрешение на размещение такого проекта на площадке Яндекса.
— А что тут не так?
— У нас регламент. Например, база данных должна работать в трёх датацентрах.
— Хорошо, запрос к эксплуатации будем делать на постгрис с синхронной репликацией. Что ещё?
— Вы не пройдёте техаудит.
— Что же тут аудировать? Пятьдесят строк кода! Пройдём!
— Нет, — снова повторил он, — то, что ты предлагаешь — ни разу не микросервис. А по регламенту должен быть именно он.
— Хгм… — озадачился я. — А ведь и инфраструктура, которую мы хотим обложить метриками, — не микросервисная.
— Ну и что? Получать ресурсы (БД, деплой) ты будешь для нового проекта, так? Значит, он обязан быть микросервисом, иначе ничего тебе не выдадут.
— Слушай! — попытался я воззвать к его сознательности, — посмотри на бизнес, там ведь все бегают как ужаленные и кипятком во все стороны писают! Речь идёт о судьбе, ни много ни мало, а миллиарда в месяц! Какая разница, микросервис или не микросервис? Давай максимально быстро дадим ответы на поставленные вопросы, а потом будем хоть до пенсии переписывать в спокойном режиме, приводя в соответствие к требованиям регламента?
— Нет, мы не станем так делать! — обломал меня он.
— А как?
— Мы реорганизуем (расширим) отдел. В него войдёт десять-двенадцать разработчиков, они напишут нужные микросервисы. Здесь я вижу что-то около десяти микросервисов.
Собирать статистику мы будем не в базе данных, а в сервисе биллинга, который уже используется в других проектах. Он, правда, для этой задачи не очень подходит… В общем, думаю, года через два сделаем всё необходимое.
— Но бизнес же ежемесячно, возможно, теряет до миллиарда!
— Нас не волнуют проблемы бизнеса. Соблюдение регламентов гораздо важнее!
— А в чём ценность этих регламентов, если за них приходится столько платить?
— Разве много? — удивился он.
— Один человеко-месяц (ограничение сверху) размениваем на двадцать четыре человеко-года (ограничение снизу) плюс, эээ…, двадцать миллиардов потерь за время разработки…
— Ну и что? — задал он вопрос, поставивший меня в тупик.
В общем, хоть задача действительно была на пятьдесят строк кода (вместе с тестами), я не смог его переубедить.
Конечно же, место для деплоя нам не выделили, постгрис тоже не дали. Аудит мы не то что не прошли — мы до него не дошли!
Поняв, что дело здесь тухлое, я спешно ротировался в другое подразделение Яндекса, не обременённое (ещё) подобными регламентами. Ну, а реформированный отдел уже без меня решал эту проблему (насколько я знаю) не два, а почти четыре года. Впрочем, как говорится, это — совсем другая история…
Решение, что нужно оттуда бежать пришло ко мне вместе с пониманием, зачем нужны все эти регламенты. Этот топ и объяснил мне всё, а примерив такую работу на себя, я понял, что “в этой клетке я жить не хочу, да, пожалуй, и не смогу”.
Прежде чем двинуться дальше, ещё немного отступлю от темы и сделаю небольшое пояснение о собственно предмете нашего с ним спора.
Технически (именно технически) микросервисы — совершенно бессмысленная вещь.
Микросервисы, например, — не способ масштабировать нагрузку9: stateless программы легко масштабируются простым добавлением копий, а масштабирование statefull всегда происходит там, где хранятся данные.
Можно даже сформулировать правило:
С технической точки зрения (производительность, количество кода и т.п.), микросервис всегда может быть замещён обычным кодом, и это действие приведёт к тому, что накладные расходы упадут, а эффективность вырастет.
Однако зачем их используют, для чего вводят такие регламенты?
— Видишь этих людей? — ответил он мне, показывая страничку одного из подчинённых ему отделов на staff, — здесь, например, их сейчас сто пятьдесят. Все они работают в одной парадигме — пишут микросервисы — причём значительную часть работы вообще делает кодогенератор.
Знаешь, в чём ценность подобного подхода?
— В чём? — переспросил я.
— Во-первых, я могу уволить половину или даже вообще всех, заместив их совершенно новыми людьми с улицы. От этого не случится никакого ущерба.
Во-вторых, никто из них, уйдя отсюда, не сможет сделать систему, аналогичную той, что мы имеем: большинство не то что не знает даже о половине бизнес-нюансов — не имеет представления, чем занимается сосед!
Осмысление
Итак, микросервисы нужны не потому, что дают некий технологический профит, а потому, что позволяют низвести разработчика до уровня мелкого винтика в производственной системе. Быстрая взаимозаменяемость этих винтиков имеет бо́льшую ценность, нежели расходы на разработку.
Это даже не разделение труда, которое предавал анафеме Жан-Жак Руссо, — это самое натуральное отчуждение от результатов труда по Карлу Марксу10!
Ни больше ни меньше!
Отчуждение рабочего в его продукте имеет не только то значение, что его труд становится предметом, приобретает внешнее существование, но ещё и то значение, что его труд существует вне его, независимо от него, как нечто чужое для него, и что этот труд становится противостоящей ему самостоятельной силой; что жизнь, сообщённая им предмету, выступает против него как враждебная и чуждая.
© Карл Маркс
Итак, рассмотрим среднестатистического разработчика Яндекс.Такси. Нанимаясь, он прошёл десяток-другой собеседований11 и попал, наконец, на вожделенную должность. А что дальше? А дальше над ним висит регламент: “только микросервис”. И даже больше — “на 80% кодогенерируемый микросервис”.
Что такое микросервис, значительная часть которого кодогенерируется? Это способ изолировать разработчика от целого (и друг от друга). Это жёсткий контракт в YAML-файлах: “На входе требуется вот это, а на выходе вот то, приступай!”. И даже внутри оставшихся двадцати процентов свобода творчества самым садистским образом ограничена: цензурируется шестью с половиной линтерами!
Поскольку человек — существо разумное, ему присуща потребность самовыражения. И раз она настолько серьёзно ограничена внешними рамками, то неудивительно, что он:
- Перманентно пребывает в демотивированном состоянии (отсюда столь низкая производительность: 24 человеко-года, против одного человеко-месяца).
- Пытается искать ей иное приложение, пытаясь, например, оптимизировать или улучшить то, что не нужно.
- Фрагментарно мыслит (ведь оперирует он именно фрагментами).
В Яндексе есть прекрасный внутренний ресурс (ЯЧан), где можно писать анонимно. Так вот, там эти самые “винтики большой машины” говорят о себе: “Я работаю перекладывателем JSON’ов!”
Шутка? Да, но в каждой шутке всего лишь доля шутки…
А дальше?
Сравнительно длительное время именно в IT мире наблюдалась уникальнейшая (по сравнению с другими отраслями) ситуация: наёмные рабочие имели доступ к средствам производства и в любой момент могли, используя их, прокатиться вверх на социальном лифте.
А что? Всё, что тебе нужно, — компьютер и немножко терпения. Идея же сгодится практически любая, просто сделай качественно!
Однако постепенно такие возможности закрываются и далее будут закрываться ещё агрессивнее. По мере роста отчуждения труд разработчиков будет всё сильнее дешеветь, пока из нынешних хипстеров не получатся настоящие пролетарии.
Уже сейчас бизнес нацелен на радикальное снижение уровня квалификации среднестатистического разработчика, на работника с максимально фрагментированным мышлением (чтобы не пытался, поднимаясь по социальным лифтам, составлять конкуренцию).
Ну а если мышление почему-то фрагментировано недостаточно, то и это ведь исправимо: помимо продвигаемой капиталом профессиональной фрагментации процветают и иные различные симулякры вроде всяких SJW12, BLM и т.п., мешающие человеку разобраться в ситуации, переключающие его из опасного конструктивного русла в безопасное деструктивное.
В итоге весь этот деструктив доводит до того, что некоторые уже добровольно13 устанавливают на свой IDE не только линтеры, контролирующие количество пустых строк, но и форматеры кода!
А затем, эти люди с поломанной психикой начинают доказывать, что вручную прописывать код обработки исключений в каждой функции — благо, что чем строже клетка, в которой их содержат, тем лучше!
Ещё бы! Они уже не помнят, что мир был (или может быть) иным!
Что делать?
Научно-технический прогресс понемногу приводит нас к тому, что именно мы — IT’шники — станем тем рабочим классом, которому придётся ломать систему эксплуатации человека человеком. И делать это придётся, преодолевая уныние и внутреннее лакейское нежелание что-либо менять.
Путь борьбы требует значительных психологических ресурсов, и самое трудное — преодоление собственного нежелания плыть против течения. Хоть это давно описано многими классиками14, но отклик находит лишь у немногих.
…Но иногда некоторые из них говорили что-то неслыханное в слободке. С ними не спорили, но слушали их странные речи недоверчиво. Эти речи у одних возбуждали слепое раздражение, у других смутную тревогу, третьих беспокоила легкая тень надежды на что-то неясное, и они начинали больше пить, чтобы изгнать ненужную, мешающую тревогу.
© Максим Горький.
Именно нам, IT’шникам, необходимо как можно быстрее превозмочь коллективный отказ от борьбы — иначе, как говорил великий американский писатель, железная пята математически непреложна15.
—- Тогда, и вы, и мы, и весь рабочий класс будем раздавлены железной пятой деспотизма, не ведающего удержу и жалости, —- деспотизма, какого не знала доселе ни одна, даже самая тёмная эпоха в жизни человечества. Вот имя для него —- Железная пята!
© Джек Лондон
Начал главу “Что делать?”, а о том, что делать, так пока ничего и не сказал. Исправляюсь.
Итак, бороться! А борьба наша начинается прежде всего с воплощения Ленинского завета: “Учиться, учиться и ещё раз учиться”16.
…среди рабочих выделяются настоящие герои, которые —- несмотря на безобразную обстановку своей жизни, несмотря на отупляющую каторжную работу на фабрике, —- находят в себе столько характера и силы воли, чтобы учиться, учиться и учиться, и вырабатывать из себя сознательных социал-демократов…
© В.И. Ленин
Как всегда, учиться придётся именно превозмогая и своё внутреннее нежелание и сопротивление среды.
Боритесь! Отказывайтесь от вакансий, где вам предлагают работать над микросервисами. Встречно предлагайте монолитные приложения!
Удалите из своего IDE форматирующие код расширения, уничтожьте линтеры, верифицирующие стиль, оставьте только те, что дают информацию о возможных ошибках. Заставьте творца, который живёт внутри, выйти на первый план!
Хороший кандидат, для реализации творческих потребностей — OpenSource17. Отчаянно необходимо, например, написать препроцессоры для Go и Rust, реализующие синтаксис исключений!
Изучайте весь стек технологий, а не только тот кусочек, за который вам платят. Чтобы прийти к успеху в деле свержения тирании капитала, необходимо удерживать при себе знания о всех доступных технологиях. Да, всего несколько лет назад понятие “фулстек разработчик” было крайне уважаемым и востребованным, а теперь хедхантер показывает всего одиннадцать вакансий по этому запросу18, против шестисот у “разработчиков микросервисов”.
Конечно, это соотношение демотивирует и навевает уныние, но именно оно и показывает направление, в котором нужно двигаться. Направление, в котором находится ахиллесова пята наших врагов.
Вместе с отчуждением уныние и нежелание бороться будут только нарастать, однако нужно помнить, что и шансы на победу со временем уменьшаются. Поэтому, чем раньше мы выступим единым фронтом, тем лучше!
Да, многие возможности уже упущены. Да, Железная Пята наступает с неумолимой неизбежностью. Однако наше генеральное сражение ещё впереди!
Дорогу осилит идущий. Капля точит камень. Если каждый из нас — хоть где-то хоть какой-то гадости в IT — скажет твёрдое “нет!”, мир станет лучше, чище и на шажок ближе к идеалу.
Оковы тяжкие падут, Темницы рухнут — и свобода Вас примет радостно у входа, И братья меч вам отдадут.
© А.С. Пушкин
Надеюсь, эта статья поможет читателю выбрать правильную сторону в этой вечной борьбе сил света и тьмы. К счастью, или, увы, но отсидеться в сторонке не получится.
Пролетарии всех стран, соединяйтесь!
Вместо постскриптума (к списку Литературы)
Многие философы (ещё задолго до Руссо) приходили к выводу, что разделение труда неизбежно приводит к тому, что Маркс впоследствии назвал отчуждением.
Но, увы, мало кто предлагал какие-либо конструктивные решения.
Может быть, кому-то будет интересным, но в начале 20 века, творил поистине великий философ и учёный - А.Богданов. Он, в частности, предложил ввести понятие “фулстек-учёного” и добавить науку, объединяющую все прочие.
Его труд — Тектология крайне рекомендуется к изучению. Конечно, это непростое чтиво, поскольку сильно отличается от современного научного стиля изложения.
Основная идея Тектологии состоит в том, чтобы выявлять общие закономерности в совершенно разных науках: общественных и естественных, химии и истории итп, сводя подходы к единообразным…
Чтобы стать хорошим фулстек разработчиком (по Богданову) придётся научиться переносить опыт, накопленный во фронтенде в бакенд. И всё вместе — в системное программирование. Как-то так.