-
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
…и другие.
Так и хочется сказать: молодцы, собрали всю коллекцию. Реакт, редукс, бутстрап, роутер и всякие плагины. Наконец-то можно показать пять сообщений.
Повторюсь, современных фронтендеров нужно не учить, а лечить. Это какой-то особый сорт нелюдей. Я искренне не понимаю, как можно выкладывать такое в прод. Не понимаю, как людей не тошнит от настолько плохой работы и собственной неэффективности. Но похоже, им это ок. Человек ко всему привыкает.
Современный Авито напоминает творчество Лавкрафта: открыл на миг, ужаснулся и скорей закрыл, чтобы не вспоминать. Но преследовать будет долго.