Фёдор Борщёв

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

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

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

Как мы запустили мобильное приложение на веб-технологиях и нам чуть не помешал Apple

Мы с клиентом запустили стартап. Он помогает малым локальным бизнесам — кофейням, барбершопам и другим — зарабатывать по модели, которую применяют Amazon и Яндекс.

Сделали мы это с помощью технологии PWA — создали практически полноценное мобильное приложение: с офлайном, пуш-уведомлениями и иконкой на рабочем столе. В этой статье делимся, как у нас получилось успеть всё это за 6 месяцев при том, что требования постоянно менялись (стартап же!)

Что за проект

Большие цифровые бизнесы зарабатывают кучу денег на пакетах и подписках. Пакеты повышают средний чек, а подписки помогают получать регулярную прибыль и планировать бюджет. Amazon и Яндекс продают пакет-подписку сразу и на кино, и на доставку товаров. Apple давно сместил фокус с продажи отдельных песен на подписку на Apple Music. Пользователь тоже выигрывает — если вы постоянно пользуетесь сервисами Амазона, месячная подписка отбивается за неделю.

Если вы — владелец кофейни, и хотите продать постоянным клиентам подписку на капучино по утрам, есть нюанс: у Амазона и Яндекса есть миллионы долларов на программистов, а у вас, скорее всего, нет.

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

Вот они, подписки:

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


На самом деле, в нём довольно много нюансов — барбершопу и кафе нужны разные форматы меню; у одного владельца может быть несколько бизнесов, а у одного бизнеса — несколько локаций; каждому сотруднику нужна учетная запись с возможностью считывать QR-коды клиентов, но без возможности менять настройки бизнеса; владельцу бизнеса важно видеть статистику; нужна интеграция с Google Maps, платежным провайдером и SMS API; нужно правильно учитывать налоги при приёме платежей.

Работа над проектом

Любой программист знает, как больно работать с меняющимися требованиями. В этом проекте этого было очень много. Мы вместе с клиентом составили список User Stories и обновляли его после каждой встречи. Это давало уверенность, что при пересмотре планов мы не забудем ничего важного:

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

Для стартапа, который только пытается нащупать своё уникальное товарное предложение, найти своё место на рынке, такие резкие перемены — нормальное положение дел.

Перед тем, как написать первую строчку кода, ведущий бэкендер проекта Лёша продумал архитектуру: провёл с клиентом сессию Event Storming и построил модель данных по контекстам. Это помогло разделить стабильные и часто меняющиеся части системы — быть гибкими, но стойкими.

Часть схемы Event Storming, архитектурного воркшопа, результат которого — схематичное описание системы, с которым согласен каждый участник


Технологии

На бэкенде использовали Python и Django, на фронтенде Vue.js — проверенный стек, с которым у нас большой опыт и экспертиза. Для инфраструктуры использовали проверенные решения: GitHub Actions, Cloudflare и Heroku, для SMS-рассылок подключили Twilio. Для мониторинга взяли Hosted Graphite — стоит дешево, настраивается быстро. Задачи менеджили в привычном нам Бейскемпе.

Прием платежей сделали с помощью Stripe Connect — готового решения для маркетплейсов. Деньги приходят владельцам локальных бизнесов, а Dozo автоматически получает комиссию. Идеально!

В Dozo два языка: польский и английский. На старте работы макеты были только а английском. Чтобы упростить жизнь клиенту, файл с текстами переводили на польский с помощью ChatGPT, а клиент проверял результат и исправлял ошибки. Еще схема с ChatGPT сильно помогла фронтендерам с версткой: примерная длина строк на обоих языках была понятна сразу. Если бы переводов было сильно больше — подумали бы интеграцию со специализированными API для локализации вроде DeepL, но в случае Dozo это оверкил.

Ещё одна вещь, которую мы делали в первый раз — интеграция с Apple и Google Wallet. Карточки товаров из Dozo можно хранить и показывать из родных интерфейсов iOS и Android без запуска Dozo, прямо как авиабилеты. Кстати, наши карточки в электронных кошельках динамические — то есть информация в них регулярно обновляется. Если в вашем проекте нужны wallet-ы — не оставляйте задачу на последние спринты, потребуется время, чтобы разобраться с кастомизацией карточек и обновлением данных.

PWA

Dozo это PWA (Progressive Web App) — сайт, который выглядит и работает как приложение. У него куча плюсов:

  • в отличие от сайтов, оно умеет открываться и работать оффлайн, без интернета;
  • его можно вытащить на рабочий стол, прямо как приложение;
  • у обычных сайтов, на экране постоянно висят кнопки «вперед, назад» и адресная строка, у PWA браузерные контролы скрыты, только наш интерфейс, как у приложений;
  • одно и то же приложение работает сразу и на iOS, и на Android;
  • не нужно проходить жёсткое ревью для каждого обновления.

Если пользовались мобильным сайтом Сбербанка или Тинькофф Банка в 2024-ом году, скорее всего вы сталкивались с этой технологией. Примеры из международного рынка — PWA приложения AliExpress, Twitter, Starbucks и Pinterest.

Невооруженным глазом PWA не отличить от мобильного приложения из Google Play или App Store:

Есть и минус — на iOS нельзя выкладывать PWA в App Store, а значит пользователям гораздо тяжелоее добавить икноку на рабочий стол.

На Android (слева) можно сделать кастомную кнопку установки PWA из браузера, мы сделали баннер наверху экрана. На iOS (справа) такой возможности нет, единственный вариант— зайти в настройки сайта и нажать Add to Home Screen:

Риски PWA мы взвешивали вместе с основателем и CTO Dozo, и решили, что в нашем случае плюсы перевешивают минусы.

Как мы попали в замес борьбы двух Голиафов

Итак, два месяца до запуска. Работа расписана по дням, время — ударно допиливать фичи и запускаться. В начале февраля Apple объявляет, что выключает PWA для европейских пользователей в следующем обновлении iOS.

На примере Spotify: слева как выглядит PWA на iOS 17.3.1, справа — на iOS 17.4 Beta 3. Слева, считай, приложение, справа — вкладка в браузере.

Дело в том, что незадолго до этого Евросоюз принимает закон о защите конкуренции, по которому владельцы платформ (читай Apple) не имеют права ограничивать установку сторонних программ на свои устройства. Apple нехотя подчиняется, но в ответ портит пользовательский опыт для жителей ЕС — мол, вините в этом своих политиков. Есть много мнений и аргументов о том, кто прав в этом споре.

Для нас же это выглядит как сход лавины в горном походе. Сетовать на несправедливость мира глупо, нужно искать путь в обход. Есть несколько вариантов, самый очевидный — засунуть сайт в нативную обертку, типа Capacitor-а, тогда для Apple мы будем выглядеть как самое обычное приложение. Проблема в том, что времени у нас осталось в обрез, а продакшен-опыта с Capacitor у нас не было. Решили запускаться на iOS просто как сайт.

К счастью, через несколько недель после анонса отключения PWA, Apple поменяла свое решение (кажется, сыграли роль в том числе и крики разработчиков в соцсетях) и мы запустились как планировали, со всей функциональностью, но нервы это потрепало и нам и клиенту.

Финал

От подписания договора до запуска MVP прошло шесть месяцев. Первые два месяца мы вели подготовительную работу, следующие четыре — активную разработку. Основную работу с нашей стороны сделали два бэкенд-разработчика, два фронтенд-разработчика и руководитель проекта.

Если вы живете в Варшаве — скоро сможете купить подписку на стрижки в барбершоп или комбо из капучино и булочки со скидкой в кофейне через Dozo. А наша команда продолжит поддерживать и развивать продукт после запуска.

Если хотите запустить проект с нами — пишите в телеграм или оставьте заявку на нашем сайте.

Команда

Андрей Бацунов, фронтенд-разработчик,
Алексей Богословский, ведущий бэкенд-разработчик,
Артур Даценко-Боос, фронтенд-разработчик,
Полина Никитина, бэкенд-разработчица,
Иван Седов, фронтенд-разработчик,
Инна Сидорова, руководитель проекта.

Количество подписчиков == оборот бизнеса

Задумался тут, что количество подписчиков в телеге, да и в любом другом блоге — это как оборот у бизнеса. Почему-то предприниматели, когда рассказывают о своём бизнесе, обязательно меряются оборотами, но никто не говорит о маржинальности и прибыли.

Допустим у кого-то бизнес с оборотом 500 миллионов рублей в год, из которых 200 уходит на закупку товаров, 200 на зарплаты, а 95 — на обслуживание кредитов. Получается внушительная цифра, но вот прибыли не много. Или возьмём бизнес в 10 раз меньше — 50 миллионов в год, о при этом затрат у него только 10 миллионов. Второй бизнес хоть и выглядит скромнее, но гораздо более прибыльный. Я-то уж точно выберу второй.

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

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

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

Сравните две крайности — у Тонского маленький канал с супер-интересными срачами в комментах, а у Лебедева — гигантская площадка медийного уровня, но вот услуги студии он там давно не продаёт.

Старее