• The Fuck

    Может быть, вы не знали, но есть программа с выразительным названием The Fuck. Написана на Питоне, 90 тысяч звезд, работает следующим образом.

    Предположим, вы запустили что-то в терминале, но получили ошибку. Не указан такой-то флаг, это депрекейтед, то-се. Если ввести fuck, то программа считает предыдущую команду и повторит ее, но на этот раз правильно.

    Звучит непонятно, так что рассмотрим пример. Скажем, я сделал новую ветку и хочу запушить ее на сервер:

    git checkout -b ssl-no-validation
    git add .
    git commit -m "some changes"
    git push
    

    Вот что я получу:

    fatal: The current branch ssl-no-validation has no upstream branch.
    To push the current branch and set the remote as upstream, use
    
        git push --set-upstream origin ssl-no-validation
    

    Гит прекрасно понял, что я имел в виду, но предлагает ввести команду повторно. Если же ввести fuck, то утилита считает bash_history и выполнит то, что нравится Гиту.

    В последнем Гите это починили: теперь git push делает апстрим самостоятельно. Однако долгое время меня выручал fuck.

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

  • Постгрес и отчеты

    В очередной раз выручил Постгрес.

    По работе я много занимаюсь отчетностью: генерю CSV и эксельки со всякими цифрами. Дело это не хитрое, но много нюансов: нужно собрать данные из десяти источников, очистить, переколбасить, построить прямые и обратные индексы. В идеале распараллелить. Потом пробежаться по коллекциям и записать итоговый документ.

    Поскольку дело происходит в лямбде, я очень стеснен в ресурсах и времени. Процессор медленный, памяти и диска немного, а на выполнение дается не более 15 минут. Это только кажется много, а на самом деле первые 7 минут уходят только на то, чтобы скачать архивы.

    Из последнего: в папке S3 лежит огромный CSV на 10 миллионов записей. Нужно выбрать из него одно подмножество, затем второе, а потом склеить их по id = parent_id.

    Написал на Кложе черновик — работает, занимает 11 минут. Можно плюнуть и оставить, но 11 минут — это уже близко к 15 минутам, а значит, можно получить таймаут. Переписал с параллельной обработкой — стало 5 минут, волноваться не о чем.

    А потом смотрю и думаю: ты же, дурачок, написал ровно то, что делает база данных. Только раз в десять медленней и костыльней. Убери быдлокод, загони CSV в базу и выполни запрос — получишь то же самое.

    Так и сделал: получаю из Амазона стрим с CSV-содержимым. Не скачивая его на диск, направляю прямиком в Постгрес во временную таблицу (апишка COPY FROM STDIN). Тот загружает 10 миллионов записей за 40 секунд. Потом посылаю SQL с двумя подзапросами и джоином — результат готов за 15 секунд. Его даже не нужно писать в CSV самому. Вызываешь COPY TO STDOUT — и Постгрес сам записывает CSV на диск. Точнее, в стрим, который я направляю в файл.

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

    Отсюда мораль — если что-то можно поручить базе, поручайте базе. Постгрес уже 20 лет делает джоины и проекции таблиц. Вероятность того, что вы сделаете быстрее, стремится к нулю.

    Ради интереса глянул на SQLite — зачем брать серверный Постгрес, если можно локально справиться? Оказалось, SQLite не умеет импортировать CSV. Такая команда есть в интерактивном шелле, а в протоколе обмена — нет. А в Постгресе есть потоковый COPY, поэтому выбора не остается.

    Есть у нас сервис, который пилят другие люди. Там логика крутится вокруг CSV и пакетного импорта в другие сервисы. Посмотрел и ужаснулся: километры кложурного быдлокода можно заменить импортом в базу и парой-тройкой запросов. Дай бог доберусь, переделаю.

  • Код на русском

    Я как-то рассказывал про феномен: показываешь человеку код на Лиспе, и он начинает хихикать, хрюкать, постить смайлики, словом, теряет всякое лицо. Примерно как школьник, принесший в класс эротический журнал.

    Заметил, что такая же ерунда с кодом на 1С. Если где-то всплывет код на русском, начинаются крики, эмоции… ужасно.

    Я писал на 1С три с половиной года в Чите, в славном Энергосбыте. У нас были две жирные программы: одна на Дельфях, вторая на 1С. Я поддеживал обе, и до сих пор нежно люблю эти платформы.

    Так вот, торжественно заявляю: код на русском поддерживается точно так же, как и на английском. Разницы нет. Когда читаешь код, то воспринимаешь его как структурированный набор команд. Никто не читает по буквам “Если…То… Конец”. Глаз выделяет структуру, операторы, циклы, словом, все как в обычном языке.

    Да, у 1С свои проблемы. Во-первых, язык не отличается врожденной красотой, а во-вторых, у 1С радикально низкий порог входа. Хотя то же самое можно сказать о раннем PHP. Еще одна косвенная проблема – 1С стоит особняком от других технологий, и в результате типичный 1С-программист ничего не знает о протоколах, безопасности и алгоритмах.

    Эти проблемы я признаю и готов обсуждать. Но когда очередной клоун смеется над кодом с русскими буквами, боюсь, он получит только мое презрение.

  • Дети в телефонах

    Разговаривал с пожилым человеком, и он выдал следующую мысль. Цитирую максимально близко.

    Мы, старики, часто бухтим, что дети сидят в телефонах. А разве пожилые люди чем-то лучше? Еду в поезде — книги нет ни у кого, все от мала до велика в телефонах и планшетах. Даже старики, которых в свое время приучали читать. На работе у нас пять чатов в Вацапе: младшая группа, старшая, родители, педсовет, бухгалтерия. И все туда пишут, отвечают, спорят. Постят картинки а-ля “с добрым утром”. Набрасывают политические новости, уже на втором сообщении переходят на личности. Бывает, три человека стоят в метре друг от друга и пишут в один чат. Чем они отличаются от детей, которых мы ругаем? Если сами не можем себя контролировать и каждую минуту открываем телефон, то что требовать от детей? Они повторяют за нами.

    И я подумал: эту мысль стоит разместить здесь.

  • Получить деньги

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

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

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

    Штатные сотрудники полагают, что бухгалтер переводит им зарплату по доброте душевной. На самом деле бухгалтер делает это из страха перед государством. Дело вот в чем: с каждой зарплаты фирма платит налог. В России мало об этом думают, потому что получают зарплату уже после вычета налогов. Но если кому-то не выплатили зарплату, то и налог с нее тоже не заплатили. Если государство узнает, что Иванову удержали зарплату, оно накажет фирму — но не за то, что Иванову нечего есть, а за то, что не уплачен налог.

    Получается, что у штатного работника есть “крыша” в виде государства, которая, разумеется, оказывает свои услуги за ренту. А поскольку ИП платит налоги по-другому, то волноваться о том, получил он деньги или нет, не нужно. Точнее, нужно, но в другом ключе: от кого и за какие услуги.

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

    Понимаю, что заметка немного опоздала из-за, как сейчас пишут, “изменившегося контекста”. Этот “контекст” нынче такой, что удаленщики возвращаются в штат. Но лучше поздно, чем никогда. А чтобы заметка не выглядела сухой, расскажу кулстори о том, как выколачивал деньги.

    Все началось хорошо: американский стартап с командой в Европе. Технический руководитель очень компетентный, полное понимание. Проходит месяц, жду зарплату. А девушка бухгалтер говорит: не могу отправить платеж, система не позволяет, то-се. Период оплаты прошел, программа закрыла бюджет, теперь в следующий раз.

    Проходит месяц, девушка выходит замуж и улетает в свадебное путешествие. Программа автоматом рассылает деньги всем, кроме меня. Жду.

    Девушка прилетает через пять недель, раскачивается еще неделю. Договариваемся на звонок. Разница 12 часов, она шарит экран, я подсказываю, куда какие реквизиты вводить. Вроде бы норм, деньги должны уйти, но в назначенный день не уходят. Девушка звонит в свой банк, ей объясняют, как правильно заполнить форму.

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

    Возникли вопросы у налоговой: в контракте указано N тысяч фантиков, а приходит на четверть больше. Как так? Пришлось выставлять квитанции якобы за переработки и допуслуги.

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

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

    Увы, не все были столь удачливы. Одному коллеге были должны пять зарплат, но за него никто вступился. Он долго переписывался с финальным боссом, а когда упомянул про суд, получил примерно такой ответ: делай визу, прилетай в Калифорнию, нанимай юриста и мы с тобой с радостью посудимся.

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

  • Разметка в Телеграме

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

    Дело в том, как передается разметка в Телеграме. Многие полагают, что в нем маркдаун, но на самом деле это не так. Телеграм может принимать маркдаун от ботов, но разметка приводится ко внутреннему виду, примерно такому:

    {:message "Welcome back, Ivan Grishaev!",
     :entities
     [{:type :text_mention,
       :offset 14,
       :length 13,
       :user {:id 100500 :nickname "igrishaev"}}]}
    

    Смысл в том, что есть сообщение и набор размеченных зон. Каждая зона знает смещение в символах и длину (поля offset и length). У зоны есть тип и дополнительные параметры, которые влияют на рендер. В примере выше слова “Ivan Grishaev” будут выглядеть как ссылка на пользователя с нужными атрибутами.

    У этой системы следствие: если поправить текст, смещения зон должны быть скорректированы. Например, я поменял Welcome back на просто Welcome. Пропали пять символов, и смещения всех зон должны уменьшится на 5. На простых случаях это работает, но когда зон много (болды, италики и прочее), что-то идет не так. Возможно, виноват многострочный код: он как-то оптимизируется, а смещения зон не принимают его во внимание.

    Если бы в Телеграме была система тегов вроде markdown или xml/html, такой проблемы бы не было. Братьям Дуровым, конечно, виднее, но я тоже могу высказаться.

  • Еще о пропаганде

    Я уже писал, как видит Россию западный человек. Для него Россия — это воплощение повести 1984. На каждом углу висит телевизор, из каждого утюга призывают брать Берлин.

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

    Никого не смущают признания Цукерберга насчет ковидной истерии. Согласно им, любой анти-ковидный контент опускался в выдаче настолько, что его нельзя было найти.

    Фактически это значит следующее. Если у человека нет долгой истории предпочтений (игры, котики, гаджеты, etc), то чтение ленты — это и есть потребление пропаганды. Но для западного человека “это другое”.

    Попался текст, который процитирую частично:

    Европейцы понятия не имеют о России. Российская пропаганда даже внутри страны вызывает у значительной части населения буквально рвотные рефлексы, если не брать во внимание психически нездоровую часть общества, крайне нуждающуюся в ежедневной порции агрессии и ненависти. Но эта часть всегда невелика даже в среде, которую искусственно разогревают самыми отвратительными эмоциями. Психика - это такая штука, которая не способна постоянно находиться в возбужденном состоянии, а пропаганда отрабатывает только один номер последние пять лет, из которых последние три - на форсаже. Если вас каждый день на протяжении долгого времени кормить даже самыми вкусными пельменями - вы скоро их будете буквально ненавидеть. Что уж говорить про пельмени от российской пропаганды…

    О чем я и говорил. Европеец считает, что россиянин после работы весь вечер смотрит пропаганду. А на самом деле россиянин смотрит тупые шоу и сериалы. В мессаджере у него не военкоры, а рекламное говно вроде “как унизить собеседника одной фразой”, арбитраж крипты, микродозинг, сибирский кузнец, кующий настоящие ножи.

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

    Уже несколько лет хожу в тренажерный зал. Что обсуждают между подходами? Фильмы, кроссовки, выступления знаменитых качков, телефоны, машины, бухло. Все то, что интересует обычного мужчину (почему-то ни слова про секс и женщин). Политика относится к той же области, что и религия: все понимают, что тема чувствительная и стараются замять, если всплыло. Неадекватов просят помолчать.

    Поэтому повторю тезис: кто рассуждает об ужасах чужой пропаганды, пересказывают свою.

  • Объекты в Джаве

    Когда-то давно я знал Джаву плохо, и у меня была проблема. Я открывал Джавадок и понимал в целом, как пользоваться объектом, но не понимал, как создать его. Сегодня я знаю Джаву лучше, но проблема никуда не ушла.

    Дело вот в чем: в ранней Джаве любой класс создавался конструктором, например

    Kokoko kokoko = new Kokoko("Ko");
    

    Пришел Джошуа Блох и сказал, что это неправильно: конструктор должен быть скрыт (или protected), а потребителям давать статичные методы, скажем .parse, .fromString, .of и так далее:

    Kokoko kokoko = Kokoko.parse("Kokoko")
    Kokoko kokoko = Kokoko.of(Sounds.KOKOKO)
    

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

    Более веселые вещи: иные экземпляры нельзя создать в принципе. При запуске JVM порождается скрытый синглтон, и статический метод .getInstance возвращает ссылку на его. Считается, что ты прочитал все методы и понял, что нужно так:

    Kokoko kokoko = Kokoko.getInstance();
    kokoko.processKokoko("Kwish")
    

    Бывает, даже когда прочитал все методы, все равно неясно, как создать объект. Оказывается, это такой дизайн: класс можно создать только из билдера — другого класса:

    KokoBuilder builder = KokoBuilder.builder().with("Kwhish");
    Kokoko kokoko = builder.build();
    

    Еще бывают фабрики, но по-моему, это то же самое, что и билдер, только менее замшелое. Блох пишет про билдеры, а про фабрики — ничего.

    Бывают статичные классы—агрегаторы. На деле это пачка функций, которые строят объекты других классов, например:

    Kokoko kokoko = KokoManager.newSingleThreadKokoko("Kwesh");
    

    Обо всем этом нужно знать, брать во внимание.

    Нам рассказывали, что с ООП наступит пони и радуга. Будем строить программы из одинаковых блоков, все системно и предсказуемо. На деле Джавные классы — это не блоки, а паззлы. С виду одинаковые, но каждая дырка и пупырка своей формы и длины, и отыскать совпадение — большая удача.

    Разнообразие в классах можно списать на долгую историю Джавы. Но сегодня нет ни одной качественной переработки ООП, и происходит откат к привычным “структура-функция”. Мне запомнился только Егор с его Элегантными объектами. Книга интересная, но когда я увидел “элегантный” код, мне немножко поплохело.

    Я считаю две вещи. Первая: к объектам нужно переходить, только когда процедурный подход уже не справляется. Запас прочности у него огромный, хватит на десятилетия (см. Postgres). Вторая: над концепцией классов нужно хорошенько подумать. На мой взгляд, она не завершена.

  • Гарри Поттер и деньги

    Читаю дочке на ночь Гарри Поттера. Она уже читала, но со мной переспрашивает многие моменты. Я в свое время пропустил Поттера, и теперь догоняю.

    Среди прочего заметил вот что: в волшебной стране интересная мера денег. Процитирую Огрида:

    — Золотые — это галлеоны, — пояснил он. — Один галлеон — это семнадцать серебряных сиклей, а один сикль — двадцать девять кнатов, это просто, да?

    Интересно, что оба числа — 17 и 29 — простые. Это значит, ни сикль, ни кнат нельзя разделить поровну между участниками. Скажем, если в группе три-четыре человека, делить 5 сиклей 11 кнатов будет, мягко говоря, трудновато.

    У простых чисел следствие: их произведение делится только на исходные множители. На этом основана вся криптография. Это хорошо понимали древние греки: они выбрали число 60 в качестве меры, потому что у него много делителей. Позже его заменило число 100, у которого делителей еще больше.

    Система денег с простыми числами максимально неудобна для расчетов. А потому вопрос: Джоан Роулинг выбрала их с умыслом или случайно? Понимает ли она особенность простых чисел? Выдумала сама или кто-то подсказал?

  • Авито 2025

    Заметка из серии “Иван зашел на Авито”. Приходится делать это раз в год, что поделать.

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

    Страница Messages заработала с третьего раза, до этого что-то шло не так. Выделяю все сообщения, жму “отметить прочитанными” — они не отмечаются. В заголовке по-прежнему мигает колокольчик.

    Публикую объявление, оплачиваю в Сбере. Авито не реагирует на платеж, страница не обновляется. Перехожу в объявление, жму “Опубликовать”. Написано, что уже опубликовано, но пока на модерации. Зачем тогда показывать кнопку “Опубликовать”?

    Смотрю консоль — все залито кровью. Десятки обращений к Sentry и внутреннему трекеру. Ставлю фильтр на JS, вижу запросы к файлам:

    runtime.17ee57e8c945aab7.js
    babel.56c763c5da678bfa.js
    react.dfd1d111f8ede875.js
    core-js.afc06ee845ff2534.js
    sentry.92aa5077131b46e2.js
    react-dom.b2b03dba79dd7e0e.js
    react-router.70c77e8819d4a40e.js
    react-router-dom.952fcbce71c8c0eb.js
    main.085d7b253d7b4fc3.js
    classnames.8bdb4ca7d18147c3.js
    axios.531715197964b964.js
    react-helmet-async.08c35d15407bd540.js
    clickstream.9d25519cca31a2b9.js
    desktop-header.08bc7205e5d97c1c.js
    desktop-error-boundary.60b97a6749bfdf5d.js
    bootstrap.a567aae79d5d83f3.js
    popperjs.23534e9c89ee28ca.js
    redux.812bd211f67f512a.js
    desktop-navigation.e3664b256e3d71c5.js
    navigation.054020057401a579.js
    PhoneActualizationPopup.0710bcce593318a7.js
    AuthProfileConfirmForm.61b7e0d361eaeba6.js
    react-redux.8146e991e20c5797.js
    profile-messenger.3520407fc648a850.js
    fingerprint.ce96eef5e5724e1b.js
    remoteEntry.faea46d9e2064abc.js
    Auth.d430faf2d81cfc87.js
    remoteEntry.6825f5efeccb47cc.js
    WwwProfileMessenger.dda85a70f5fec4e4.js
    

    …и другие.

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

    Повторюсь, современных фронтендеров нужно не учить, а лечить. Это какой-то особый сорт нелюдей. Я искренне не понимаю, как можно выкладывать такое в прод. Не понимаю, как людей не тошнит от настолько плохой работы и собственной неэффективности. Но похоже, им это ок. Человек ко всему привыкает.

    Современный Авито напоминает творчество Лавкрафта: открыл на миг, ужаснулся и скорей закрыл, чтобы не вспоминать. Но преследовать будет долго.

Страница 7 из 95