Я всю профессиональную жизнь связан с разработкой. Видел много нормально запроганных, но мёртвых проектов, в которых создатель просрал продуктовую работу. Видел много успешно работающих проектов, где разработка была полным дерьмом даже без юниттестов — но создатель делал продуктовую работу на отлично, и проект, пусть и со страдающими программистами, но ехал вперёд.
И ни разу я не видел проекта, который не запустился из-за медленной разработки.
Конечно, в долине смерти много бизнесов, где код говно, а программисты нарушают обещания. Но причина их смерти — не в программистах, а всё в той же просранной продуктовой работе: нулевой product-market-fit, несходящаяся экономика, неумение нанимать людей и тестировать гипотезы.
Плохой код — следствие общих проблем, а не причина
Когда пойдёте на следующий курс по вайб-кодингу, чтобы заменить своих программистов, вспомните пожалуйста меня — ваш проект умрёт не из-за программистов, не из-за бухгалтеров и не из-за поставщиков воды в офис. Он умрёт из-за вас.
Недавно ковырял настройки сети в свежей Ubuntu и грустил — с точки зрения Developer Experience Линукс окончательно скатился до уровня современного фронтенда. Вот пара вещей, с которыми я столкнулся только за один день:
netplan, хоть и конфируется на YAML, не принимает файлы .yml — только .yaml. Кладёшь .yml — получаешь неработающую сеть.
Директория /etc/if-up.d/, в которую раньше можно было складывать скрипты, запускающиеся про поднятии интерфейса, всё ещё существует, но не работает — скрипты не запускаются.
netplan try — классная штука, которая пробует новые сетевые настройки, и при обрыве соединения откатывает их назад — не откатывает настройки назад. В Ubuntu 22.04 откатывала, в 24.04 — перестала.
systemctl при неудачной попытке запустить сервис не выдаёт ошибку, а говорит «читайте журнал через journalctl». journalctl на одно сообщение об ошибке показывает 10 строчек бойлерпдейта, одинакового для всех сервисов. Почему бы в момент ошибки не показать мне нужную строчку из systemctl? Не знаю.
И это я ещё не говорю о менее зрелых с точки зрения DevEx инструментах, вроде Wireguard, у которого есть две утилиты, которые парсят один и тот же конфиг, с одинаковым названием и структурой, но в разных форматах: wg понимает только простой конфиг, а wg-quick — расширенный, и если скормить wg конфиг от wg-quick, то wg молча упадёт, сказав что у него ошибка в конфиге, и ни слова не упомянув о двух форматах.
Сисадмин настраивает Wireguard
К такому состоянию дел мы пришли путём, характерным не только для опенсорса, но и для программистского мышления в целом — вместо того, чтобы чинить неработающие вещи, мы любим прятать их за фасадами абстракций. Давайте посмотрим, к чему это приводит, на примере развития способов настройки сети в Ubuntu/Debian.
Когда-то давно сеть настраивали командой ifconfig, которая, кстати, до сих пор живёт во всех дистрибутивах линукса. Как настоящий unix-way инструмент, ifconfig умеет делать хорошо только одну вещь — настраивать сетевой интерфейс. Чтобы настройки интерфейсов не терялись после перезагрузки, его запускали из /etc/rc.local. Если кому-то надо было гарантировать порядок и названия интерфейсов — колдовали с modprobe. Жили так довольно долго: где-то, например во FreeBSD, настройки ifconfig писали в /etc/rc.conf, где-то, например в мини-дистрах для специальных задач, вообще никакого стандарта не было.
Потом пришёл кто-то, кому это не нравилось, и изобрёл /etc/network/interfaces. Это такой файл, куда записываются настройки ifconfig на очень похожем, но всё же своём языке. Сисадмины выучили ещё один DSL (благо в те времена таких языков было немного, и все они были маленькими), а автор с радостью решил несуществующую у реальных юзеров проблему — теперь все настройки сети хранились в одном месте. Правда не совсем удачно — другим программистам было тяжело парсить его DSL, потому что настройки могли лежать в /etc/network/interfaces.d, скрипты после поднятия интерфейсов запускались непойми откуда, а как сохранять порядок интерфейсов — было вообще непонятно. Юзеры обо всём этом не знали — у них болело, что radioethernet, который недавно переименовали в WiFi, не работал без ужасного wpa_supplicant, который мало того, что был непонятным, так ещё и с /etc/network/interfaces никак не взаимодействовал. Но кто же их спрашивает, юзеров-то.
Здесь бы нам всем остановиться, добавить в /etc/network/interfaces WiFi, и протащить его в другие дистры (или затащить в Debian стандарт из других дистров). За 10 лет и пару мажорных апдейтов такую штуку можно было бы довести до рабочего состояния — чтобы и WiFi через GUI конфигурировать, и на серверах было понятно, что куда писать. Но старые абстракции чинить никому не хочется — лучше нагородить новых поверх. Так появился NetworkManager. У него тоже нашлись несуществующие, но при этом нерешаемые проблемы — и появился systemd-networkd. На удивление, и у него нашлись нерешаемые проблемы, к тому же NetworkManager почему-то отказался умирать, поэтому пришлось изобретать ещё одну абстракцию поверх их обоих — netplan.
systemd решил все проблемы (нет)
Вероятно, я пропустил пару абстракций, потому что не плотно слежу за развитием Линукса, но суть ясна — программисты, вместо того, чтобы засучить рукава и чинить то, что наговнокодили, предпочитают объявлять это всепрощающим словом «легаси» (и от кого же вы это унаследовали?) и делают поверх абстракцию. Абстракция течёт, превращается в легаси, и поверх неё пишут ещё одну абстракцию. И во всём этом процессе никто не думает про опыт пользователей — главное, это написать всё заново и «чисто».
Ничего не можем, потому что легаси
Мне сложно осуждать таких программистов — я и сам ненавижу работать с плохим кодом. И в fands мы легаси не берём, если не видим способа быстро спрятать его в коробочку абстракций.
Но кажется, если бы у владельцев бизнеса был инструмент, который мешает программистам городить новые абстракции поверх старых, а заставляет их чинить то, что есть, стоимость владения такими решениями была бы существенно меньше. И пусть код в них был бы намного скучнее — зато он закрывал бы бизнес-задачи, а люди, которые им управляют, были бы счастливее за счёт отсутствия на работе авралов, вызванных очередным джуном, который не понял очередную абстракцию.
Недавно задумался, что всю жизнь обхожусь без нетворкинга в его привычном понимании — не тусуюсь на конференциях (выступил и домой), не хожу на вечеринки, почти никогда не встречаюсь с кем-то без конечной цели и чёткой повестки. Все новые проекты и интересные предложения я получал либо от незнакомых мне людей, либо предлагал сам сам — людям, с которыми не был знаком лично.
Освободившееся время я предпочитаю тратить на что-то более результативное — лучше напишу пост в блог, сделаю что-то полезное в бизнесе, займусь пет-проектом или хобби. Связи, которые люди установят со мной, изучив портфолио в блоге, будут крепче и полезнее, чем связи, которые установятся просто потому, что мы оказались в одно время в одном месте.
Да, без нетворкинга не работает биздев — если вы продаёте b2b товары или услуги, и не придумали как взломать систему, то вкладывать кучу времени в знакомства с почти нулевым результатом — это ваша святая обязанность.
Ещё нетворкинг — это в том числе и рекреационная активность: общаясь с людьми, можно отдыхать. Но в большинстве случаев между пополнением списка контактов в телеге и сидением в одиночестве, я выберу одиночество.
В перерывах между крупными проектами наши программисты обычно делают мелкие задачки для компании и клиентов: рефакторят старый код или настраивают мелкие интеграции, что сэкономить время на рутине. Обычно в таких проектах мы даём полную свободу — можно выбрать любую технологию и любой подход. Недавно на двух таких проектах одновременно заметил тенденцию к оверижинирингу: типа затащить RabbitMQ в проект, который в ответ на один вебхук дёргает другой вебхук или прикрутить строгую типизацию в кодовую базу на 300 строк.
С одной стороны ребят можно понять — хочется больше практиковаться в новых технологиях: когда пришёл на проект, где всё уже работает, самый хороший способ изучить его технологии— воспроизвести с нуля на соседнем проекте. Да и индустрия давит — парочка хайповых технологий в резюме привлечёт больше сорсеров, чем умение решать задачи за 300 строк вместо 30 000, которое, к тому же, никак не проверишь без собеседования.
Если планируете развиваться в кого-то кроме деда, годами не вылезающего из своего единственного проекта, такой оверижиниринг для вас — стратегическая ошибка. Технологии — это хард-скиллы. Сегодня RabbitMQ, завтра BunnyPQ или RussMessageOchered: всё это учится за 1–2 недели при желании. А вот умение писать мало кода — это целый сложный софт-скилл: тут и в бизнес-задаче надо разобраться, и изобретать уметь, и заказчику продать свои изобретения. За пару недель не освоишь.
Софт-скиллы качать всегда выгоднее, чем хардскиллы — технологии меняются, а ваша голова и опыт остаются. Так что если на работе достался небольшой проект без ограничений — постарайтесь на нём написать меньше кода, а не больше.
Если составить топ проблем разработки, с которыми ко мне когда-либо приходили проектные менежеры, то в самом верху будет «срываются сроки». Банальное — договорились сдать в четверг, настал уже вечер пятницы, а от программиста всё ещё ни слуху, ни духу. Часто в этом виноват накопленный техдолг, плохая коммуникация или безответственные программисты. Но причина может быть и в самом менеджере, вернее в его неумении слушать.
Когда программисты называют сроки в виде вилки, типа «2–4 дня», многие менеджеры слышат только первую часть вилки — «2 дня». Если сказать «во второй половине мая», менеджер услышит «15 мая» вместо «между 15 и 30 мая». Если сказать «не меньше трёх дней», менеджер услышит «три дня».
Что с этим делать? Если вы программист — называйте абсолютные, а не относительные сроки. Не «2–4 дня», а «будет в следующий понедельник». Не «во второй половине мая», а «1 июня». Не «не меньше трёх дней», а «через три дня назову срок».
Если вы менеджер — закладывайте запасы и слушайте то, что люди говорят на самом деле, а не то, что вы хотите от них услышать.