Фёдор Борщёв

Заметки с тегом «Программирование»

Кроме управления разработкой, я ещё пишу код. Под тегом «программирование» я выкладываю заметки связанные с разработкой ПО — пишу про технологии, фреймворки, тесты, железки и всё такое.

Вам не нужно на фронтир

В маленьком вебе (надеюсь, вы его читаете) можно найти целый диапазон мнений про AI-хайп — от отрицания до полного поклонения (автор последнего — целый автор Redis). В Х (его вы, надеюсь, не читаете) топ-менеджеры AI-компаний жалуются, как ловят FOMO от скорости появления новых технологий, которые их же компании производят. В общем хайп-поезд всё ещё едет.

Боязнь остаться за бортом характерна для нашей отрасли. И оправдана — если условный сисадмин с нормальным для рынка уровнем знаний в 2016-2018 годах пропустил появление k8s и облачных технологий, зарплата у него не вырастет, пока он не докачает знания до новой планки. Думаю, каждый вспомнит такие революции в своём стеке: фронтендеры вспомнят появление реактивных компонентов, vue, svelte. Бекендеры вспомнят graphql и микросервисы. Деды вспомнят AJAX и MVC. Все вместе вспомнят блокчейн.

Остаться за бортом революции — страшно. Есть три способа справится с этим страхом. Кто-то бросает все силы, чтобы внедрить новое, сабмитит разработчикам баги, мирится с детскими болезнями. Это ранние пташки. Кто-то отрицает всё новое («выросло поколение, которое не может писать без веб-фреймворков») — как луддиты. А кто-то закрывает свои рабочие задачи тем, что есть, изучая новые технологии только тогда, когда от этого уже никуда не деться — как обычные потребители.

Стратегия обычных потребителей — самая выгодная: пока они доходят до новой технологии, она успевает достаточно созреть — обзавестись документацией, встроиться в экосистему, вылечить детские болячки. На этом этапе цена изучения технологии гораздо ниже — сравните, к примеру, первую версию документации react, которая предлагала комплилировать JSX прямо в браузере и современный next.js, на котором собрать сайт можно за 10 минут без помощников.

AI, хоть и отличается скоростью от предыдущих революций, проходит тот же самый путь: какие-то части уже созрели (Cursor, агенты), какие-то — пока на ранней стадии (агенты, которые пишут агентов). А какие-то части уже умерли, или потихоньку стагнируют. Если следить за всеми этими новостями — на работу не останется времени.

Как поступать с AI, придерживая стратегии обычного потребителя? За пару дней подобрать себе удобный зрелый инструмент (cursor/claude cli/opencode/figma), и, применив закон Парето к своему FOMO, просто решать свои рабочие задачи. А если ещё какие-то части AI-инструментария дозреют до того, чтобы заслужить вашего внимания — вы наверняка об этом узнаете, как сисадмины узнали о k8s.

Форма, функция и красота

В «Коммуникации Систем» мы много говорим о понятиях system form и system function. Форма — это как система выглядит: на какие модули разбита, с какими данными работает. Функция — то, что система делает: как реагирует на ввод, что отдаёт на вывод.

Форма и функция выходят далеко за рамки IT и проектирования. Это, скорее, про красоту. Вещи, в которых форма подчинена функции — красивы. Вещи, в которых функция размыта, а форма сложна — некрасивы и неприятны.

К примеру макбуки, Dell бизнес-серий, дорогие thinkpad — красивы: дают много возможностей владельцу и не отвлекают формой. Игровые ноутбуки и всякие дешёвые асусы — некрасиво, потому что их главная функция — блистать на полке в магазине. Есть и исключение — Framework: вроде бы и красивые штуки, но вот функция, которую они выполняют, — быть ремонтопригодный в домашних условиях, — вряд ли понадобится кому-то в здравом уме.

А сколько же на улице некрасивых машин! Дорогие немцы, в большинстве своём — некрасивы: функции размыты, а форма требует постоянного обслуживания. Исключение — разве что Майбахи, заточенные под перевозку одного пассажира, или BMW M-серии, сделаные для кольца: с такими функциями можно и хрупкую форму потерпеть. Маленькие SUV, которыми забит рынок — некрасивы: форма как у дешёвых ноутбуков, пригодна только стоять в автосалоне и говорить неискушённому потребителю «не думай, купи меня, я сгожусь на любой случай жизни».

Чувство прекрасного отдыхает на утилитарных пикапах вроде Toyota Tundra или том, что в штатах называют «траками»: они много возят, когда надо — быстро едут, а простое шасси и атмосферный мотор будут хоть 20 лет выполнять свою функцию. Очень красивы велосипеды на которых ездят курьеры: быстрые, лёгкие, ничего лишнего.

Глядя на форму, можно определить функцию, которую туда закладывает автор. Так, по названию хорошего класса в коде понятно, что он делает, а по первому экрану приложения видно, чего от него хотели авторы.

Форма эволюционирует вместе с функцией. К примеру Медиум когда-то был отличным средством для публикации лонгридов, а в процессе эволюции превратился в пейвольную помойку — очевидно, новая форма стала более выгодна владельцам. Или взять любой продукт Яндекса — почти везде его функция со временем перестаёт интересовать владельцев. Так навигатор превратился в тормозные «карты», а сервисы доставки еды и такси превратились в мигающий попапами и требующий кучи лишних кликов Yandex Go. Вообще, «экосистема» это что-то на шейрхолдерском, а не на пользовательском.

Когда проектируете что угодно — архитектуру системы, пользовательский опыт, пост в тг-канал — сначала подчиняйте форму функции, а потом уже думайте об украшениях.

К чему приводит наслоение абстракций

Недавно ковырял настройки сети в свежей 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 мы легаси не берём, если не видим способа быстро спрятать его в коробочку абстракций.

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

GPT-ассистенты мешают джунам учиться

Всё чаще встречаю джунов, которые плотно сидят на GPT-ассистентах, типа Copilot или Codeium. Кажется у каждой крупной корпорации, связанной с программированием появляется свой робот-помощник. Спрашиваешь такого робота «как добавить JS в Джанго-алминку?» и получаешь готовый код, который скорее всего даже заработает. Сразу чувствуешь, что будущее наступило.

Только вот будущее это — не для тех, кто бездумно пользуется такими ассистентами. Довольно мало ценности в том, чтобы переводить просьбы бизнеса в вопросы роботу — в какой-то момент такой посредник станет просто не нужен.

Профессионального роста от такого программирования тоже немного. Самое главное, что должен делать джун — это учиться: разбираться, как устроены библиотеки и как мыслят их авторы, учить языки, учиться учиться в конце концов. В общем, планомерно нарабатывать свои 10 000 часов за счёт работодателя.

Час, потраченный на изучение документации — это час, вложенный в ваш профессионализм. Час, потраченный на попытки починить GPT-код — это просто час, который вы продали работодателю, не получив ничего, кроме денег.

Доверяйте машине только те активности, которые не прокачивают лично вас — нагенерить тестов, крудов или семпловых данных. А для всего остального — читайте старую добрую документацию и скорее становитесь мидлами.

Старее