-
Летнее время
Как известно, перевод часов на летнее время несет сплошную пользу. Прямо так хорошо от него, так хорошо, что аж сам себе завидую. И под это дело потерял день рабочего времени, и остальные тоже.
На работе я занимаюсь отчетностью. В Амазоне у меня зашедулено много отчетов, каждый из которых уходит своим потребителям. Большинство из них я сделал прошлой осенью и зимой, когда у заказчика было время +1. А весной произошло вот что.
Если не указать в Амазоне часовую зону cron-выражения, то по умолчанию берется UTC. Это хорошо, потому что точка отсчета фиксирована. Но одно и то же время UTC в зависимости от времени года дает разное локальное время. Например, зимой время 08:00 am UTC будет 9:00 am UTC+1, а летом – 10:00 am UTC+2.
Это значит, что после перевода часов потребители получат отчеты не в 9 часов, а в 10 по местному времени.
Начались жалобы: что-то подумал, что все сломалось, кто-то не успел предоставить отчет к созвону, где-то упал скрипт, который перекладывает отчеты в другое место. Починил так: нужно указать под cron-выражением местную зону, например
Europe/<City>
, и сдвинуть часы так, чтобы они совпадали с зимним временем, по которому работало раньше. На то, чтобы разобраться, задеплоить и проверить, ушел день. В первый раз я поднял часы на +2 вместо +1, и пришлось переделывать.Коснулось и других коллег: Майкл, почему твоя задача запустилась на час позже? И Майклу предстоит то же самое: считать на бумажке часы, деплоить и проверять.
У меня стойкая ассоциация: каждые полгода страна садится голой задницей на гвоздь. За полгода рана заживает, и кажется, что в этот раз обойдется без последствий. Но нет: снова боль, снова проблемы, крики. Никогда такого не было, и вот опять.
Спрашивается: сколько можно? Сколько еще нужно выбросить времени, денег, нервов, здоровья, чтобы чиновников отпустило? Десять лет? Сто лет? Уверен, в будущем над нами будут смеяться: представляете, дети, эти придурки на рубеже тысячелетий гоняли часы туда-сюда, чтобы сэкономить тысячу долларов на 20 миллионов человек. Примерно как раньше сжигали людей, чтобы задобрить бога – с таким же результатом.
Слышал, что за перевод времени люто топил Яков Перельман. Что неудивительно: более яростного человеконенавистника нужно еще поискать. Может, хватит брать с него пример?
-
Иконки в едином стиле
Беда, когда у компании несколько программ, и дизайнера просят сделать иконки “в едином стиле”. Почти всегда получается шляпа.
Каноничный пример – Гугл. Пока у него не было тыщщи сервисов, у каждого была своя симпатичная иконка. У почты – конверт, у звонков – телефонная трубка, у карт – карта. Но потом позвали дизайнера и сказали делать в одном стиле. В результате получились козявки с вариацией цветов: желтый, зеленый, красный, синий.
Поставтье хотя бы две такие иконки рядом, и вы запутаетесь.
Радует, что подобную иконку не сделали Ютубу: проект настолько самобытен, что ни у дизайнера, ни у менеджера не поднимается рука.
Иные иконки вообще лишены смысла, например у Google Authenticator. Старая иконка представляла собой замок сейфа в виде буквы G. Казалось бы, все логично: сейф, безопасность, буква. Новая иконка – это какая-то снежинка. Что хотел сказать автор? Помню как обновил Google Authenticator и десять минут искал иконку сейфа. И до сих пор не могу привыкнуть, что теперь это снежинка.
Более-менее было нормально у Адоба времен CS4. Они стилизировали иконки под периодическую таблицу Менделеева. Смысл в том, что каждый элемент (то есть программа) занимает свою уникальную роль, обладает особыми свойствами. Различать программы помогало следующее:
- на каждой из них было имя программы из двух букв, например Ps, Ai, Ae;
- иконки были разного цвета. Фотошоп – голубой, Иллюстратор – оранжевый, Индиз – малиновый и так далее.
Позже Адоб пошел по пути упрощения: иконки стали почти черно-белыми, а цвет остался только в контуре. Предполагается, что пользователь должен парсить все эти Ps, Ai, Ae, Id, Au, Pr и так далее.
Похоже, никто не может решить задачу иконок “в едином стиле”. А если и может, то не справляется с давлением менеджмента. Так зачем вообще браться за это?
-
ROW CHECK и безопасность
Работал я в одном стартапе на Кложе. Код прошел через десятки разработчиков и представлял лоскутное одеяло: разные подходы и библиотеки. Каждый разработчик городил что-то сбоку, а не исправлял текущее положение дел. Была своя ORM с километрами кода и склейкой SQL-строк. Много там всего было, и в том числе база данных.
Эта база прямо сейчас стоит в памяти. Она тоже прошла через серию разработчиков, каждый из которых знал, как делать правильно. Одни ребята забивали на нормализацию; другие решили, что добавлять колонки утомительно и сделали поле info с типом jsonb, в которое валили все подряд. Были материализованные вьюхи, обновлять которые было затратно, и которые без конца обновлялись из-за косяков в очереди сообщений. Ни одна запись физически не удалялась, а помечалась флагом
is_deleted = true
. Много багов было связано с тем, что данные выбирались без этой проверки.Но это не все. Основатель фирмы считал себя специалистом по безопасности и придумал вот что. В Постгресе есть штука под названием
ROW CHECK
: проверка доступа на уровне записи. Если некая функцияmy_check(row)
возвращаетnull
илиfalse
, то клиент словно не видит этой записи. Это медленно, но работало.Почему директор так сделал? Он хранил в одной таблице данные разных клиентов и опасался, что из-за ошибки в коде один клиент увидит данные другого. Поэтому каждая таблица хранила избыточные айдишки, и в рамках каждого запроса выставлялась переменная
current_owner
. ФункцияROW CHECK
проверяла, что ее значение совпадает с айдишками записи.Воздвигнув этот бастион, директор спокойно сидел под рутовой учеткой, для которой проверки были отключены. На моей памяти было два крупных инцидента, когда он путал окна и выполнял на проде то, что хотел выполнить на тесте. Терялись данные, пропадали целые таблицы.
К счастью, наши часовые зоны сильно отличались, поэтому на починку базы бросали другого человека. По понедельникам он рассказывал, как просиживал выходные за восстановлением бекапов, импортов CSV и отладкой. Были и другие, не столь фатальные случаи, связанные с активностью директора на проде.
Забавно, но наибольший урон базе нанес именно директор, а не хакеры или кривой код. Хакерам, видимо, стартап был не интересен, хотя в самописной ORM были дыры для инъекций. Код, хоть и был не супер, не страдал тем, что читал чужие данные. Свои удаленные – да, но не чужие.
Можно сказать одно: все запреты проверяются на прочность теми, кто их создает. У меня доступ на прод был только для чтения. В другом стартапе права на запись были, но под той учеткой я не ходил. В конце концов, был страх, что за подобный инцидент уводят. А у директора страха не было, вот и результат.
В более широком ключе: запрет хорошо работает только тогда, пока его соблюдают те, кто принимал. Не важно, о чем идет речь: о детях, собаках или машинах. Если говорящая голова топит за очередной запрет, но не готова применить его к своим детям, собакам или машинам, сказанное не имеет смысла.
-
Форки Фаерфокса
Заметка от нечего делать. Пробую форки Фаерфокса: поставил WaterFox и LibreWolf. Первый очень понравился: старый рубленый интерфейс, доступны опции, которых нет в официальной версии. Нет телеметрии и всякого дерьма вроде Покета и синхронизаци. Очень шустрый. Потыкал Ютуб – все ролики работают. LibreWolf вроде тоже неплох, присматриваюсь.
Пока что один минус: не работает webm, но стерпим и это.
Офицальный FireFox в последнее время не радует. Он сливает все больше данных, на сайте меняются формулировки: вместо “не передаем” пишут “улучшаем экспериенс”. Браузер обрастает Покетами-шмокетами, телеметрией и так далее. Нельзя отказаться от обновлений, нужно писать свои полиси.
К счастью, есть достойные форки, которые пилят люди, не нацеленные на прибыль. Их трудом пока что и буду пользоваться.
Пытался сидеть в чистом Хромиуме, но в нем не работает половина Ютуба. Причем даже не видео, а музыка из игр и фильмов. Спасибо, не надо.
От коммерческих хромоподелок вроде Брейва уже тошнит. Тут тебе и крипто-кошелек, и внутренние донаты, и свой поисковик, и то, и се, и облачная учетка, и сторонний VPN по подписке, и целые джунгли впридачу. В Вивальди вообще завезли почтовик и календарь с будильником.
Так что хоть мелкая, но отрада в наши дни: сидеть на форке некогда великого продукта.
-
Cloud-driven development
Расскажу об одной стремной вещи, которую называю “Cloud-driven development”. Это когда разработчик тестирует код не локально, а в облаке.
Выглядит так: нужно забрать откуда-то данные, переколбасить и сложить в другое место. Программист пишет код, деплоит в свое окружение и дергает апишку. Она падает. Он смотрит логи. Правит код, деплоит, дергает. Намылить, смыть, повторить. На двадцатой итерации работает как надо, и он закрывает задачу.
А потом у него отпуск, и мне говорят: поправь. Нужно взять данные из еще одной апишки и положить во второе место. Тестов либо нет, либо самые поверхностные.
Я как-то пытался играть по этим правилам. Быстро выяснилось, что окружение нужно готовить. Ой, у тебя старые сервисы, задеплой к себе эту фигню и эту тоже. У твоей облачной учетки нет пермишенов? Скажи девопсу Джорджу, чтобы добавил. Он в отпуске? Ну, жди. Потом не хватает каких-то креденшелов, токенов-шмокенов, их нужно откуда-то догонять.
Короче, выясняется: разработчик настроил себе уютненькое окружение и ушел в закат. Чтобы сделать то же самое мне, нужна неделя. А ведь мог же поднять Докер и помочь всем. В конце концов, не знаешь Докер, попроси кого-нибудь помочь, а пока что тестируй на локальной базе, локальном S3 – таких заглушек полно.
Кончается тем, что я пишу и Докер, и интеграционные тесты, которые ходят в локальные сервисы, чтобы приблизить локальную разработку к облачной. Причем зачастую в счет личного времени, потому что давай-давай.
Я уж не говорю о том, что Cloud-driven development страшно не эффективен. Каждый деплой занимает в лучшем случае 10-15 минут, и за это время ты все равно не возьмешься за другую задачу. Разработчик смотрит Ютуб или ходить курить. Вроде работает, а на самом деле решето: сплошная пустота.
Я бы вообще не давал разработчикам окружений. Это дорого и вдобавок развращает. Вот тебе Докер с базой, Редисом и Кафкой, пиши, тестируй. Пока локально не заведется, ни о каких облаках не мечтай.
В качестве побочки всплывают проблемы конфигурации. Выясняется, что ни один сервис нельзя направить на локалхост: везде захардкожено что-то вроде
"aws." + region + ".amazon.com"
. Лишний день уходит на то, чтобы сделать хосты конфигурируемыми.Читали же: “
квартирныйоблачный вопрос только испортил их” (с)… -
Украшение шахматных фигур
Давайте несколько постов не про айти? А то надоело. Вот хотя бы про шахматы, только не про игру, а фигуры.
У шахматных наборов одна проблема: трудно найти такой, где король и ферзь сделаны нормально. У этих фигур должны быть знаки отличия: у короля – шапка с крестом, а у ферзя – корона. Но и то, и другое делают плохо, если вообще делают. Если шахматы деревянные, то король и ферзь одинаковы, а на головах у них пипки. Чтобы понимать, кто есть кто, у короля пипка длиннее.
Когда играешь такими фигурами, дети часто их путают. Иногда и сам замечаешь, что в который раз двигаешь ферзя как короля и наоборот. Но не обязательно покупать новый набор: легко наколхозить кресты и короны своими руками.
Идем в ближайший отдел рукоделия: это где всякие нитки, ленточки, ткани. Среди этих штук есть мелкие побрякушки для нашивки и плетения: черепа, сердца и другие предметы, в том числе шапка монарха и корона. Стоит буквально ничего: три или пять рублей.
Берем напильник и подтачиваем пипки фигурам, капаем китайский суперклей и сажаем головной убор. Эффект просто бомбический: теперь у главных фигур металлические знаки отличия. Они выделяются, крест и корону никогда не перепутаешь. Цена решения – двадцать рублей.
На фотографии видно, что дети уже покоцали фигуры: один король потерял крест, но шапка осталась. Ферзю отбили зубцы на короне. Надо бы починить.
Удивляюсь, что никому из производителей шахмат не пришло это в голову. Казалось бы, купи оптом эти железки по рублю штука и налепи королям и ферзям – всего-то четыре железки на набор. Отдельно выделить эту фичу на маркетплейсе: смотрите, у нас фигуры со знаками отличия, а не как обычно: у кого пипка длиннее, тот и король.
Но нет, приходится пилить самому.
В шахматы, кстати, я играю очень слабо, полный нубас. Что не мешает судить о красоте и удобстве фигур.
-
Про абстракции
Как только зашла речь об абстракциях, знайте: дело швах. Абстракции – это булщит-бинго, в котором линейному разрабу никогда не выиграть. Это штучки для менеджеров и архитекторов, то есть тех, кто парит над кодом, а не стоит в нем по колено.
Бывает, разработчики увлекаются и играют в эти шашни: всерьез обсуждают абстракции. Они забывают, что любая функция – это уже абстракция. Например, функция поиска простого числа может перебирать числа линейно, с интервалом или брать из таблицы. Может кешировать. Аналогично с факториалом или числом Фиббоначи: потребитель не знает, что внутри, поэтому функция абстрактна. Сюда же списки и хеш-таблицы.
В ООП языках абстракция вообще идет из коробки. Скажем, написал интерфейс
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 – участок памяти, доступный всем процессам. Что-то вроде глобальной переменной, только в рамках процессов.
Вроде топорно, но оказывается удобным на практике, потому и дожило до наших дней.