-
Про абстракции
Как только зашла речь об абстракциях, знайте: дело швах. Абстракции – это булщит-бинго, в котором линейному разрабу никогда не выиграть. Это штучки для менеджеров и архитекторов, то есть тех, кто парит над кодом, а не стоит в нем по колено.
Бывает, разработчики увлекаются и играют в эти шашни: всерьез обсуждают абстракции. Они забывают, что любая функция – это уже абстракция. Например, функция поиска простого числа может перебирать числа линейно, с интервалом или брать из таблицы. Может кешировать. Аналогично с факториалом или числом Фиббоначи: потребитель не знает, что внутри, поэтому функция абстрактна. Сюда же списки и хеш-таблицы.
В ООП языках абстракция вообще идет из коробки. Скажем, написал интерфейс
UserRepo
с методомUser getUserById(Integer id)
и везде его передаешь. А потом пишешь классыJDBCUserRepo
иMongoUserRepo
, каждый из которых ходит куда нужно. Об этом пишут в каждом учебнике по Джаве. Что может быть проще?Нормальный код в абстракции не нуждается – он и есть абстракция над байткодом или машкодом. Вот и весь разговор.
Лучшее, что можно сделать в споре про абстракции – это промолчать. Скорее всего, любителя абстракций отпустит, и он забудет о них так же быстро, как и вспомнил. И вы спокойно сделаете все как надо. Спорить и лезть на рожон глупо, потому что повторюсь: абстракции – это булщит-бинго, в котором разработчику никогда не выиграть.
-
Зарплата до налогов
Хоть я и не сталкивался, но предупреждаю вот о чем.
Некоторые HR-ы практикуют гниловатый прием: называют зарплату, не договаривая, что это ДО налогов. В итоге сотруднику платят меньше, а когда он спрашивает “wtf?”, ему отвечают: это до налогов, дорогой! Как в лучших домах Европы.
Такое случается не только в айти: слышал в том числе от стоматологов. Врача переманивают лишней двадцаткой и потом вычитают ее налогами. А назад уже поздно: взяли другого врача, да и ушел не совсем достойно.
Ситуация, конечно, бредовая: русская фирма нанимает русского сотрудника, а налоги у них как в Европе? Скорее, обычная русская жадность.
Будете устраиваться во всякие ВК-Сберы-Яндексы – имейте в виду.
-
Реляционная база данных
Повторюсь, до чего же это классно: иметь в распоряжении нормальную реляционную базу данных. Не тридцать микросервисов с HTTP JSON API; не OpenSearch; не Монгу; не черт знает что еще.
Скажем, у меня условие: отправлять письмо, если у вложенных атрибутов такие-то значения, плюс у сущностей, на которые ссылается эта сущность, тоже определенные значения. Эти проверки выливаются в экраны быдлокода. Сначала собрали вложенные куски, отфильтровали, построили индекс. Взяли айдишки. По ним выгребли другие сущности, плюс надо следить, что их не 10 тысяч, иначе пляска с пагинацией. Потом пробегаешь по этим сущностям, строишь индекс. И по двум индексам находишь ответ: есть совпадения или нет.
Даже на Кложе это приличный быдлокод, который через пару месяцев хрен поймешь:
map
,map
,filter
,reduce
,map
,group-by
– удачной отладки. В какой-нибудь Джаве с доменами и слоями проще выйти в окно.А в SQL это запрос в 18 строчек. Функция
json_path_query
, которая собирает вложенные пути, одинleft join
и пара условий. Все декларативно, нет переменных и циклов.Еще один момент: если придет человек и спросит, почему эта штука посчиталась именно так, то с микросервисами я сосу лапу. Код отработал, и какие структуры были в памяти, догнать уже невозможно. Раньше я дампил состояние в S3, чтобы позже скачать его и воспроизвести расчеты. Но это долго! А теперь я выполнил запрос в PGAdmin, и человек такой: все верно, это у нас надо поправить.
Принцип простой: чтобы стало легче, нужно отстегнуть гири, которые сами же привязали. Если нет легкого, произвольного доступа к данным, ни о какой удобной работе нет речи.
-
Зависание окон в Экселе
Работал в Экселе и заметил одну вещь.
В офисном пакете интерфейс устроен по принципу “один файл – одно окно”. Это значит, если открыто пять файлов, то будет пять окон. А восприятие наше таково, что каждое окно считается независимым. Технически много окон могут обслуживаться одним процессом, да. Но когда я вижу окно во весь экран с менюшкой и табиками, оно ощущается отдельной программой.
Это приводит к странному поведению: во время долгого импорта виснут все окна Экселя. Я рассуждал так: пока импортируется тяжелый файл, я поработаю с другим файлом. Но Эксель в этом плане однопоточный: остальные окна тупо ждут, пока отпустит первое. Может, такое только на Маке, а на Винде проблем нет, спорить не буду.
Интересно вот что. Сегодня все браузеры работают по принципу “одна вкладка – один процесс”. Я смутно помню, что этого браузеры, в том числе Хром, часто вылетали с ошибками, потому что вкладки были на тредах. Сегодня это редкость, а лет 15 назад было в порядке вещей. Или браузер мог повиснуть на Ютубе или какой-то упоротой верстке, заморозив все табы. А теперь, когда вкладке плохо, мы этого даже не замечаем.
Было бы забавно проверить эту модель в современном вебе. Иногда на звонках люди шарят экран, и я вижу Хром с тремя десятками вкладок. Без преувеличения, не менее тридцати, потому что табики сжаты до размера иконки. Десятки табов Джиры, Конфлюэнса и прочей корпоративной жести. А каждая Джира – это, на минуточку, 50 мегабайтов скриптов и запросы на каждый клик. Мне кажется, если бы тридцать Джир крутились в одном процессе, интернета мы бы вообще не увидели.
И еще одна мысль, которую не знаю, куда приткнуть. Сервер PostgreSQL работает по принципу “одно соединение – один процесс”. Никаких тредов там нет и в помине, на каждое подключение делается форк главного процесса. Обмен данными происходит через shared memory – участок памяти, доступный всем процессам. Что-то вроде глобальной переменной, только в рамках процессов.
Вроде топорно, но оказывается удобным на практике, потому и дожило до наших дней.
-
Зачем пароль?
Вот что меня удивляет. Когда логинишься в любой сервис, ввода пароля уже недостаточно. Обязательно спросят код с телефона или почты. В какой-то степени я с этим согласен, потому что телефон – физическое устройство, им трудно завладеть, коды одноразовые, их сложнее перехватить.
Хорошо, но зачем тогда вообще пароль? Если мы не доверяем тому, кто ввел пароль, зачем он нужен? Вроде бы есть проверка, но она не точная как фильтр Блума.
Коды из смс и всякие токены из приложения – все это буквально кричит о кризисе системы паролей. И вместо того, чтобы закопать стюардессу и отменить пароли, продолжают их использовать.
Видимо, кто-то считает, что связка “пароль” + “код из смс” безопасней, чем оба по отдельности, но я в это не верю. Это примерно как вызвать хэш-фукцию десять раз вместо одного: доказано, что такой подход не приносит пользы.
Телефон уже давно умеет в биометрию и может авторизировать человека где угодно. Неужели лица и отпечатка пальца недостаточно, чтобы зайти в личный кабинет? С какой стати человек должен помнить пароли вроде “не менее 8 символов, не менее двух заглавных букв” и мусора вроде решеток и долларов? И так для двадцати разных сервисов?
Тем не менее, все бездумно лепят одну и ту же схему: пароль, которому никто не верит, и коды с телефона. Тут явно нужно что-то менять.
Самое смешное: сейчас вы повозмущаетесь в комментариях, а что потом? Пойдете пилить форму авторизации с паролем.
-
Перевод часов
Трудно поверить, но во многих странах до сих пор живодерский обычай переводить время на час и обратно. Даже находятся те, кто утверждает, что это полезно для экономики.
Напомню, что сто пятьдесят лет назад какой-то бюрократ посчитал, что если зажигать лампочку на час позже, это будет дешевле. О мелочах вроде сорванных встреч, опозданий и нарушений биоритмов никто не думал.
Поражаюсь, почему люди до сих пор живут с этим бредом? Было совсем другое время, другое общество, только что вступившее в индустриальную фазу. Сегодня другие приоритеты. Почему не пересмотреть вопрос, но на этот раз учесть все факторы, а не только “экономию” нескольких тысяч долларов на всю страну?
Согласен, что зимой нужно корректировать время, но делать это нужно по-другому.
Зимой человек устает больше и спит больше. Поднять и собрать детей в школу зимой – целый подвиг. А весной или ранней осенью, когда солнце уже показалось, вставать легче. Отсюда вывод: нужно двигать не циферблат целиком, а распорядок госучреждений. Например, начинать занятия в школах, садах и госконторах не в 8 утра, а в 9 или хотя бы в 8:30. То есть давать людям лишние 30 минут на сон.
Это честно, потому что затрагивает только тех, кому это нужно. На офисных работниках, у которых служба начинается в 10, это никак не отразится. У них не поедет календарь, не придется опаздывать. У стариков не нарушится прием лекарств. Что может быть лучше?
Пока писал, вспомнил свою жизнь в Чите. Я тогда работал в Энергосбыте, где служба начиналась в 8 утра, и за опозданиями следили строго. Пара опозданий – выговор, три и более – лишают премии. Только одна женщина из соседнего отдела могла приходить к 9 утра, но такую привилегию нужно было выслуживать годами.
Так вот, Чита, зима, поднимаешься в 6:30. За окном ночь. Завтрак, подъем ребенка, сбор в садик. Едем на санках по морозу -30. Машины нет, да и не каждая машина заведется, постояв ночь при такой температуре. После сада нужно сесть на маршрутку, а они все полные. Кое-как добраться до работы, чтобы пересечь турникет за две минуты до 8 утра. Зайти в кабинет и полчаса отогреваться и отпиваться чаем. Зато успел, премии не лишат.
Блин, зачем так жить? Зачем рвать задницу ради 8 часов утра? Зачем переводить часы глобально? Почему нельзя подвинуть распорядок тех контор, которые начинают рано? То, что в мире сейчас – это какой-то идиотизм от начала до конца.
-
Книги не устаревают
Удивляюсь, когда говорят: айтишные книги устаревают. Это не так.
Книги об алгоритмах, сетях или азах разработки не устаревают в силу своей базы. Нет такого, что каждый день придумывают новую сортировку или топологию дерева. Новый сетевой протокол выходит раз в несколько лет, а не дней. Поэтому здесь волноваться не о чем.
Если условный Rust меняется каждый день, и код из прошлогодней книги уже не работает, то это проблема технологии, а не книги. Пусть читатель либо подождет, пока язык стабилизируется, либо выберет что-то более надежное.
Читая книгу, человек не просто что-то узнает. Он насыщает индекс, обучает свою нейронную сеть. Даже если он сядет за новую версию технологии, сработает фактор знакомства: это я уже видел, тут на 70% как в книжке.
Читайте книги!
-
Телефонные боты
Замечаю еще один забавный паттерн. Звоню в разные фирмы, и как обычно, на входе голосовое меню. Чтобы узнать то, нажми 1, чтобы это, нажми 2 и так далее. Либо тыкаешь сразу 0, чтобы попасть на оператора, либо ждешь, пока меню отпустит и сработает фолбек.
Но когда скрипт переключает на оператора, включается ИИ-бот. “Я голосовой помощник Иннокентий, какой у вас вопрос?” Говоришь “дай оператора”, и начинаются расспросы: а по какому вопросу тебе нужен оператор? В точности пенсионер-вахтер.
К чему я это пишу. Ребята, которые внедряют голосовых ботов: не кажется ли вам странным оставлять голосовое меню из нулевых годов? У вас же вроде ИИ, который знает и умеет все на свете, и который скоро всех заменит. Но прежде чем попасть на бота, я должен кликать в голосовом меню? Как-то не сходится. Зачем боту такой костыль?
То, что голосовые помощники тупы как пробки, нет смысла говорить. Выделяют ключевые слова и читают то, что уже есть на сайте. Например, спросишь: на какой премиальный курс я могу рассчитывать, если сумма обмена больше N тысяч евро? И он диктует текущий курс или расписание отделений.
Беда.
-
Postgres как поисковый движок
Накину ссылку, которая очень мне помогла:
Речь о том, как делать гибридный поиск в Посгресе. Это когда документы ищутся по разным критериям, ранжируются, а потом объединяются в финальный набор. Как раз то, над чем я работаю в текущем проекте.
Статья полезна вот чем: до нее я не понимал, как объединять выборки с удалением дублей. Бывает, один и тот же документ оказывается в разных выборках, и нужно оставить ту, у которой больше ранг. Пытался сделать это при помощи
UNION
, но из-за ранга дубликаты не удалялись. Чистить их вторым проходом тяжело, усложняется план.Так вот: автор предлагает объединение выборок при помощи full outer join и coalesce среди айдишек прошлых результатов. Звучит непонятно, но если разобраться, то получается как в примере ниже.
Для сравнения, вот первый запрос, который выбирает документы по условиям и сортирует по выражению с рангом:
SELECT aggregate FROM some_aggregates WHERE NOT ((aggregate #>> ARRAY['state']) = ':deleted') AND (((aggregate #>> ARRAY['attrs', 'code']) = 'hello') OR (aggregate @@ '$.attrs."code-name" == "hello"') OR ((aggregate #>> ARRAY['attrs', 'code']) ILIKE '%hello%') OR ((aggregate #>> ARRAY['attrs', 'code-name']) ILIKE '%hello%')) ORDER BY CASE WHEN (aggregate #>> ARRAY['attrs', 'code']) = 'hello' THEN 0 WHEN aggregate @@ '$.attrs."code-name" == "hello"' THEN 1 WHEN (aggregate #>> ARRAY['attrs', 'code']) ILIKE '%hello%' THEN 2 WHEN (aggregate #>> ARRAY['attrs', 'code-name']) ILIKE '%hello%' THEN 3 ELSE 999 END ASC LIMIT 51 OFFSET 0
На таблице с 1.5 миллионами записей метрики такие: execution=450ms, cost=90000, что довольно много.
А вот то же самое, но с подходом, который предлагает автор:
with sub1 as ( select id, 0 as rank from some_aggregates where NOT ((aggregate #>> ARRAY['state']) = ':deleted') and ((aggregate #>> ARRAY['attrs', 'code']) = 'hello') limit 51 ), sub2 as ( select id, 1 as rank from some_aggregates where NOT ((aggregate #>> ARRAY['state']) = ':deleted') and (aggregate @@ '$.attrs."code-name" == "hello"') limit 51 ), sub3 as ( select id, 2 as rank from some_aggregates where NOT ((aggregate #>> ARRAY['state']) = ':deleted') and ((aggregate #>> ARRAY['attrs', 'code']) ILIKE '%hello%') limit 51 ), sub4 as ( select id, 3 as rank from some_aggregates where NOT ((aggregate #>> ARRAY['state']) = ':deleted') and ((aggregate #>> ARRAY['attrs', 'code-name']) ILIKE '%hello%') limit 51 ) select aggs.id, aggs.aggregate #>> ARRAY['attrs', 'code'], aggs.aggregate #>> ARRAY['attrs', 'code-name'], sub1.rank, sub2.rank, sub3.rank, sub4.rank, aggs.aggregate from sub1 full outer join sub2 on coalesce(sub1.id) = sub2.id full outer join sub3 on coalesce(sub1.id, sub2.id) = sub3.id full outer join sub4 on coalesce(sub1.id, sub2.id, sub3.id) = sub4.id join some_aggregates aggs on coalesce(sub1.id, sub2.id, sub3.id, sub4.id) = aggs.id order by sub1.rank, sub2.rank, sub3.rank, sub3.rank asc limit 51
Хоть он и выглядит длинно, содержит CTE и джоины, но метрики такие: execution=7ms, cost=15000. Гораздо быстрее первого варианта.
Мораль в том, что короткий запрос не всегда значит быстрый. С помощью правильного джоина можно отсечь огромную часть выборки, сведя ее нескольким записям.
Статья на Хабре – перевод вот этого блога: https://anyblockers.com/posts/postgres-as-a-search-engine
В свою очередь, автор взял идею из блога Supabase: https://supabase.com/docs/guides/ai/hybrid-search
Тем, кто ковыряеся с Посгресом, будет очень полезно изучить ссылки.
-
Настоящий гей
Встречаюсь с приятелем, и он рассказывает: водил жену в ресторан, и знаешь, какой официант нас обслуживал? Настоящий гей! Или знакомый врач говорит: представляешь, вчера на приеме был настоящий гомик! Разумеется, они используют более резкие термины, но я не привожу, чтобы никого не обидеть.
В такие моменты я оживляюсь и спрашиваю: как ты определил, что это гей? Он оставил записку с предложением встретиться? Он погладил тебя за руку? Шлепнул по заднице? Пристал в гардеробе?
Все оказывается банально: этот “гей” был вычурно одет, пользовался косметикой, говорил с другой интонацией. И все? “Божечки, а разговоров-то было…” (с)
В городской среде сексуальная ориентация и внешность никак не связаны. Можно спать с мужчинами и носить обычную одежду. Можно носить ошейник и кожаные штаны, но не иметь связей в принципе.
В случае с официантом причин может быть много. Когда у человека совсем плохо с женщинами, он может притворяться геем, особенно если работает в женском коллективе. Это старый прием, потому что к геям девушки относятся по-другому.
Человеку может нравиться ролевая модель гея. Он изображает того, кто не вписывается в рамки. Ему нравится эпатировать публику, ловить взгляды. Провоцировать других и писать гневные посты в VK: а сегодня одно быдло сказало мне… Отсюда прилизанные лаком волосы, мушка на щеке, брошь размером с кулак.
Не вижу разницы с неформалами, готами и другими ребятами. Везде, если копнуть, сидит желание выделиться или уход от своих проблем.
Отучайтесь делать выводы об ориентации по внешности. Иначе вы не лучше деревенского гопника, который выучил, в каком ухе должна быть серьга, в какую сторону приглаживать челку, и какой фасон джинсов “правильный”. Мир как бы сложнее этих правил.