-
Перекладывание
Иногда говорят: это тебе не джейсоны перекладывать, тут думать надо. А между прочим, перекладывать джейсоны – очень трудное занятие.
Прилетает вам джейсон из сети. Надо его прочитать, провалидировать, распарсить даты, подрезать лишнее. Потом выгрести из базы то, из кэша се, из S3 третье и все это собрать в нечто нужное бизнесу. Сделать эксельку, положить в S3 и отписать в очередь.
На каждом шаге может быть сто причин для эксепшена. Записать логи, не раскрывая бизнес-данных и секретов, собрать исключения и отправить в Сентри.
Иные джейсоны пятиэтажной вложенности. Нужно рыскать по их кишкам и строить обратные мапы (индексы). Потом передавать по пять индексов в другие функции.
Читать из базы миллион джейсонов так, чтобы не умереть от нехватки памяти в AWS.
В идеале покрыть все случаи тестами, желательно с Докером, чтобы были настоящие база, Редис, S3 и так далее.
Все еще легко, на ваш взгляд? Не знаю, мне кажется трудным. Поэтому над “перекладыванием” я не смеюсь.
-
Excel и CSV
Маленькая техническая заметка. Не пользуйтесь CSV в надежде, что он откроется в Экселе. Если ваши потребители – люди с Экселем (а таких большинство), нужно генерить
.xlsx
, а не.csv
.Дело в том, что Эксель писали в Микрософте. Может быть, сегодняшний MS уже обрел какую-то человечность. Но Эксель отсчитывает возраст с 1985 года – прямо как я – и старше многих читателей этой заметки. Поэтому ни о какой человечности говорить не приходится.
Эксель никогда не откроет CSV без ошибок. Он обязательно промажет с разделителем: если в файле запятая, он ищет точку с запятой и наоборот. Для обхода придумали грубый костыль: в первой строке может быть выражение sep=, и тогда Эксель возьмет запятую. Но этот заголовок ломает парсеры CSV, которые ни о каком Экселе не слышали.
Разделитель по умолчанию может зависеть от локали. У француза откроется, а у австрийца не откроется.
Эксель по-прежнему игнорирует UTF8. Немецкие умляуты становятся кракозябрами. Махинации с меткой BOM ни к чему не приводят.
В Экселе есть мастер импорта из CSV, но можно подумать, людям больше нечем заняться, как импортировать что-то куда-то ради таблички.
В общем, нужно напрячь булки и выкинуть CSV, и вместо этого генерить нормальный Эксель.
Если вдруг у вас Джава или Кложа, берите fastexcel и fastexcel-reader – они быстрее и компилируются Граалем. Все, что основано на Apache POI, тормозное и не компилируется Граалем. Я эту дорогу прошел и вот делюсь с вами.
-
Мои объявления
Авито, страница “Мои объявления” — разве это не забавно? На экране все что угодно, кроме моих объявлений. Огромная плашка, громадные пустоты. Слоеный дизайн, когда каждый слой, пусть даже занимает сантиметр в ширину, растекается на весь экран.
Очередной калека-дизайнер, которому “не хватило места”. Важная часть уехала на экран ниже — потому что первый экран занял всякий шлак.
Считаю, таких дизайнеров надо даже не учить, а лечить. Обучение бессильно, пусть действуют профильные специалисты.
-
Загрузка в Амазоне
У веб-панели S3 есть особенность: если скачать оттуда файл, Амазон поправит расширение в зависимости от Content-Type, который назначили файлу при создании. Например, если у файла нет расширения, а Content-Type равен
application/json
, то Амазон допишет в конец .json, чтобы файлик открылся.Казалось бы, хорошо? А вот что имеем на практике.
Если залить файл
hello.json.gzip
, внутри которого сжатый Gzip-ом JSON, и указать заголовкиContent-Type: application/json
,Content-Encoding: gzip
, то при загрузке произойдет следующее.Файл будет декодирован Амазоном, чтобы клиенту не пришлось делать это руками. Не бог весть какая помощь, потому что и текстовые редакторы, и файловые менеджеры открывают gzip-файлы. Но ладно.
После раскодировки Амазон смотрит: что там внутри? Application/json? Значит удалим
.gzip
и добавим.json
. В результате получается файлhello.json.json
. Я не шучу, проверьте сами.Второй случай: я залил в Амазон файл
report.xlsx
, но указал не тот Content-Type. Указал старыйapplication/vnd.ms-excel
для xls документов, а надо было такую колбасу:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
. При загрузке Амазон молча исправил расширение с.xlsx
на.xls
. А Эксель тоже хорош: по клику на файл он пишет, что формат битый, ничего не знаю – нет бы первые 100 байтов проверить, тупица.На ровном месте Амазон заруинил файл, хотя никто об этом не просил.
Понимаете, не нужно мне помогать! Не нужно что-то тайно переименовывать для моей же пользы. Если прям чешется в одном месте – спроси, и я нажму “больше не спрашивать”.
Кроме того, надо помнить: в Амазоне работают не боги, а такие же кодеры, как и везде. Перед нами обычный баг, который живет в проде не один год, и никому нет дела. Баг состоит в том, что махинации с расширением нужно производить только если у файла нет расширения. Вдобавок у расширения приоритет выше, чем у Content-Type, потому что последний – это метаинформация, которая может потеряться или исказиться. Вероятность потерять расширение гораздо ниже, нежели Content-Type.
Верю, что когда-нибудь в Амазоне это поймут.
-
Время в Interstellar
Вы же смотрели Интерстеллар? Помните высадку на планету с волной? А музыку в фоне, такую тревожную, помните? Тик-так, тик-так по нарастающей?
Этот тик-так — неспроста. Каждый тик равен 1.37 секунды, и за это время на Земле проходят сутки. Именно такое соотношение времени между Землей и той планетой из-за близости к черной дыре. Ганс Циммер гений.
Когда знаешь об этом, в сцену добавляется новый оттенок. Теперь уже не смотришь на метания за разбитым кораблем: слушаешь тик-так и представляешь, как впустую проходит чья-то жизнь — твоя, например.
Иногда по вечерам, вытряхнув себя из-за компа, я чувствую что-то похожее. Словно жизнь — это фильм, а в фоне кто-то цокает языком. Исправляешь чей-то быдлокод и косяки, потом идешь домой и думаешь — что я вообще делал?
Нечто похожее встретилось в дневниках Корнея Чуковского времен блокады Ленинграда: “дни сгорают как бумажные”. Потому он и великий писатель, что не уходят, не летят, а именно сгорают.
Впрочем, потом меня отпускает, и я снова иду править чужой код и косяки. И так постоянно.
-
Список через запятую
Одна из самых дурацких вещей в айти – это список через запятую, например:
(1, 2, 3) ["test", "foo", "hello"] [{:id 1}, {:id 2}, {:id 3}]
Каждый, кто работал с таким форматом, знает, какой геморрой учитывать запятые. Элементы нельзя просто записать в цикле. Нужно собрать их в массив, а потом join-ить запятой. Это сводит на нет стриминг элементов, когда их много. А чтобы работал стриминг, нужно завести флажок “запятая уже была”, выставить его в первый раз и постоянно проверять: была или не была?
То есть на каждом шаге из миллиона нужно делать эту проверку, которая сработала один раз. Из-за какой-то никчемной запятой.
Какие проблемы возникнут, если запятые убрать?
(1 2 3) ["test" "foo" "hello"] [{:id 1} {:id 2} {:id 3}]
Не вижу причины, по которой любой из списков не может быть распаршен. Все три читаются и подлежат парсингу на ура.
В одном скобочном языке запятые вообще считаются пробелами: они уничтожаются парсером, словно их нет. И это никак не влияет работу: все читается, и даже лучше: меньше визуального шума.
Список через запятую – рудимент, от которого пора избавиться. Случись вам изобретать свой формат данных – откажитесь от запятых как значимых символов.
-
Выпадашка в Хроме
На скриншоте — типичная ситуация наших дней. По клику на аватару появляется выпадашка, но содержимое не вмещается, и у выпадашки появляется прокрутка.
Окно браузера растянуто максимально, ничего не сжато. Зум нулевой. Никаких вредоносных действий с моей стороны. Просто дизайнеру “не хватило” места. Еще бы: если обернуть каждый элемент в паддинг, скруглить углы, добавить отступы где только можно, поместить всю фигуру в другой паддинг, сместить вниз — откуда ж возьмется место?
На полном серьезе спрашиваю: что происходит с фронтендерами? Может у них пост-ковидный синдром? Вакцина дала побочку? Иначе это не объяснить. Дай фронтендеру экран размером со стену — и он поместит все нужное в выпадашку, которая появится по клику на гамбургер. Внутри все “воздушное”, не хватает места, и появляется прокрутка.
Раньше можно было понять: разрешение 800 на 600, кривой IE6, умирающий Netscape, ранние оперы и фейерфоксы. У каждого багов — как блох на жучке. Но сегодня-то что? Везде ретины, 4К, только Хром и его поделки. Что мешает делать нормально: без выпадашек с прокрутками?
Какая-то загадка.
-
Датомик
Лет семь назад я увлекся Датомиком. Кто не знает, это база данных, написанная на Сlojure и Java. Среди ее плюсов – неизменяемость (данные только накапливаются), независимость от времени (можно вернуться в прошлое) и выразительный язык запросов Datalog, взятый из Пролога.
Я долго ходил вокруг да около, а потом повезло: семья уехала на неделю, и я провел это время, читая доки и экспериментируя. У меня тогда был пет-проект на Postgres, и я перевел его на Датомик. Позже я использовал его в других проектах, в том числе в Хайлоад-капах от Mail.ru. Я написал статью про миграцию с Постгреса на Датомик, и она даже попала на главную Хакер-Ньюз.
У Датомика есть важное свойство: он красивый. Бросил взгляд, и сразу мысль – да, круто. Это изящная абстракция, воздвигнутая на элементарных вещах. Мало проектов, где эти свойства – изящность и простота – выражены столь же ярко.
Я много играл с Датомиком и даже пытался реализовать его поверх реляционных баз. Кое-что мне удалось, но поделки я так и не довел до ума. Практика показала, что скучные Postgres/Maria удобней в работе.
Прежде всего, неизменяемость из коробки не нужна. Там, где нужно хранить историю, Postgres/Maria справляются за счет триггеров или запросов вида
INSERT ... FROM UPDATE/INSERT/DELETE
. Когда говорят об исторических данных, у меня сразу вопрос – как вы ими пользуетесь? Они вообще вам нужны?Далее: страшные буквы GDPR. Если пользователь хочет удалить свои данные, с Датомиком будут проблемы. В Датомике атрибуты не меняются, а добавляются новые с поздним временем. Поэтому, читая один и тот же атрибут в разное время, получим разные значения. Но GDPR требует, чтобы в базе физически не было личных данных. Если вы записали в базу атрибут
(42, :user/name "XXXXXX")
, то старый атрибут(42, :user/name "Ivan")
остался, и прочитать его – дело техники.В Датомике есть функция физической очистки атрибутов, но она дорогая и выполняется во время обслуживания, то есть требует остановки прода.
Можно отключить историю атрибутов, но тогда вопрос – зачем вообще история, которой так гордится Датомик?
Кто-то скажет: ладно, пусть имя пользователя будет без истории, а остальное с историей. Практика показывает, что GDPR требует чистки чуть ли не всех таблиц. Когда мы удаляли пользователей из приложения с короткими видео, то пришлось шерстить десятки таблиц: профили, лайки, коменты, друзья, подписчики, обращения, сообщения… это были недели ада. Если представить, что у каждой таблицы история, ситуация станет еще хуже.
У Датомика никакой поиск, нет сортировки и пагинации. Как с этим жить – решать вам. Кого ни спрашивал – каждый пилит свои костыли, каждый случай – свое маленькое приключение.
Есть еще кое-что: Датомик, при всей своей красоте, нарушает доменную область. Я как-то говорил о том, что главное свойство домена – его ортогональность другим доменам. Другими словами, у базы и кода на Сlojure разные зоны ответственности. Датомик стирает эту границу: он превращает базу в хранилище, к которой только он имеет доступ. Этому есть объяснение, поскольку физически данные хранятся как бинарные дампы с кусками индексов, и работать с ними умеет только Датомик.
На практике это выливается в то, что если я хочу поправить записи в Датомике, нужно писать код на Кложе, который выгребает данные, исправляет и записывает в базу.
Это резко контрастирует с Postgres/Maria, которые предлагают свои языки и инструменты для работы с данными. Это и есть домен, когда я могу исправить данные, не обращаясь к Кложе. Бывает, я сижу в psql днями и неделями, манипулируя данными на чистом SQL.
Датомик нарушает это правило. Да, у него есть веб-консоль, но по сравнению с psql она крайне уныла, а до программ уровня PGAdmin или DBeaver ей как до луны.
Датомик как мороженное: он красивый, но позже липнет и затекает туда, где ему не следует быть. Поэтому я прекратил с ним шашни и продолжаю работать с Постгресом. И кстати, Постгрес в последние годы просто летит в космос, нарадоваться не могу.
Выбирая Датомик, имейте в виду вышесказанное.
-
Кража дизайна
Иногда я слушаю дизайнера Женю Арутюнова, он говорит клевые вещи. Говорит мягко и с самоиронией. Не бывает так, что слушаешь тезис, а потом: кто не со мной, тот мудак.
У Жени как-то спросили, как не красть чужой дизайн. Он ответил: спокойно воруй, потому что даже если не будет последствий, ты увидишь, что чужой дизайн не решает задачу полностью. Чтобы решал, нужно поправить здесь, поправить тут, и в итоге краденый дизайн либо развалится, либо изменится так, что перестанет быть краденым.
То же самое можно сказать про код. Даже если вы украли чей-то код, заставить работать его на вас трудно. Адаптация кода под задачу займет столько времени, что проще написать свой. А если выигрыш и возможен, его трудно оценить.
Иные проекты тянут сотни зависимостей — их написали другие люди. И все-таки мы пишем и отлаживаем свой код в папке src. Есть даже похожие сервисы и бизнесы, и некоторые с открытым кодом. Но нет — не смотря на колоссальные объемы открытого кода, нас продолжают нанимать. Мы пишем код, ловим баги, сидим в отладчике.
Именно поэтому когда случилась колоссальная утечка Яндекса — 50 гигабайтов исходников — я даже ухом не повел. Их обсасывали на всех новостных ресурсах, но скажите: что вы хотели там найти? Обычный корпоративный код: прочитать JSON, проверить его, положить в базу, дернуть очередь, записать в лог, собрать эксепшены в сборщик ошибок.
По той же причине я скептичен к коду, написанному ИИ. Пусть он пишет тетрис и змейку, этого добра на Гитхабе пруд пруди. Как мне поможет ИИ, если нужно впендюрить очередной if цепочку бизнес-процессов, чтобы ничего не упало? Как он придумает новый твиттер? Как он придумает игру, где участники отрывают жопы от стула(!) и идут в парк ловить виртуальных зверей?
Идея первична, лишь затем следует код.
Вот почему, имея горы открытого кода, мы, словно герой Никулина, ищем “такой же, но с перламутровыми пуговицами”. Потому что требования. Потому что это наша работа.
-
Телефонный спам
Ситуация с телефонным спамом печальная. Звонки поступают часто, и самое главное — их качество растет феноменально. Живые люди уже давно не звонят, вместо них на проводе “интеллектуальные помощники” — боты с элементами ИИ.
Иногда я слушаю, что скажет тот или иной “помощник”, чтобы быть в курсе технологий. Повторюсь, качество просто запредельное. Хорошо подобраны фоновый шум, интонация, неточности разговорной речи. Бот определяет, когда его пытаются перебить и вежливо просит дослушать до конца, а потом обсудить вопросы. Дерево сценариев огромно, продумано много случаев.
Не сомневаюсь, что многие люди говорят с ботом как с живым человеком. Не зная заранее, что звонки автоматизированы, легко принять бота за чистую монету.
По-настоящему раздражает несколько вещей. Первая — именование спама. Подобно тому, как взрыв называют “хлопком”, а пожар — “задымлением”, спамерские услуги называют “информированием” населения, а ботов — “интеллектуальными помощниками”. Такая манипуляция вызывает тошноту.
Вторая вещь — полный беспредел со звонками при помощи ПО. Еще можно понять, когда нанимают студентов в колл-центр. Но когда скрипт фигачит столько звонков, сколько выдерживает сеть оператора до временного бана, это ни в какие ворота.
Третья вещь — должно быть предупреждение, что обзвон совершает робот. Помнится, такое хотели принять в США, чтобы, когда говоришь с ботом, было предупреждение: с вами говорит робот. А тем, кто предупреждение не ставит, выкатывать конский штраф. Не знаю, приняли или нет, но считаю, это должно быть.
С телефонным спамом борются и фирмы. Почти у всех операторов есть услуга “антиспам”, и она даже работает, я проверял. Тиньков разрывает звонок и шлет смс, что это спам. Но почему фирмы борются с фирмами при полном попустительстве закона?
Напоминает современный веб: трекинг — блокировщики, еще больше трекинга — еще больше блокировщиков, а при открытии вкладки закипает мой ноут.
Пожилые люди запуганы спамерами и мошенниками. Много раз наблюдал: у человека звонит телефон, неизвестный номер, он смотрит на цифры, пытаясь определить — спам или нет? Думает, местный или нет, боиться принять вызов… до чего довели!
В моем случае было три раза, когда я не мог дозвониться людям старше себя. Я не был в их телефонной книжке, и вдобавок у меня виртуальный оператор с чудными цифрами. Вместо привычных 933 человек видел загадочные 399 и поэтому не брал трубку. Приходилось писать в вацапы-вайберы, чтобы догнать.
От некоторых ребят я слышал, как они живут припеваючи, разрешив вызов только с номеров в телефонной книжке. У меня не получилось: стоило включить это правило, как не дозвонился курьер, сорвалось мероприятие, разминулся с сантехником и прочая бытовуха.
Объясните родственнику: если он сомневается в номере, пусть сбросит вызов и перезвонит через минуту. В лучшем случае он никуда не дозвонится, потому что у мошенников динамический пул номеров. Если это банк с кредитом, он услышит музыку и номер в очереди. Наконец, если это был обычный человек, он примет вызов.
И покажите, как блокировать номер из списка недавних вызовов, это несложно. Шанс, что через месяц позвонят с этого номера, хоть и мал, но есть.