• Иконки в едином стиле

    Беда, когда у компании несколько программ, и дизайнера просят сделать иконки “в едином стиле”. Почти всегда получается шляпа.

    Каноничный пример – Гугл. Пока у него не было тыщщи сервисов, у каждого была своя симпатичная иконка. У почты – конверт, у звонков – телефонная трубка, у карт – карта. Но потом позвали дизайнера и сказали делать в одном стиле. В результате получились козявки с вариацией цветов: желтый, зеленый, красный, синий.

    Поставтье хотя бы две такие иконки рядом, и вы запутаетесь.

    Радует, что подобную иконку не сделали Ютубу: проект настолько самобытен, что ни у дизайнера, ни у менеджера не поднимается рука.

    Иные иконки вообще лишены смысла, например у 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 – участок памяти, доступный всем процессам. Что-то вроде глобальной переменной, только в рамках процессов.

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

  • Зачем пароль?

    Вот что меня удивляет. Когда логинишься в любой сервис, ввода пароля уже недостаточно. Обязательно спросят код с телефона или почты. В какой-то степени я с этим согласен, потому что телефон – физическое устройство, им трудно завладеть, коды одноразовые, их сложнее перехватить.

    Хорошо, но зачем тогда вообще пароль? Если мы не доверяем тому, кто ввел пароль, зачем он нужен? Вроде бы есть проверка, но она не точная как фильтр Блума.

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

    Видимо, кто-то считает, что связка “пароль” + “код из смс” безопасней, чем оба по отдельности, но я в это не верю. Это примерно как вызвать хэш-фукцию десять раз вместо одного: доказано, что такой подход не приносит пользы.

    Телефон уже давно умеет в биометрию и может авторизировать человека где угодно. Неужели лица и отпечатка пальца недостаточно, чтобы зайти в личный кабинет? С какой стати человек должен помнить пароли вроде “не менее 8 символов, не менее двух заглавных букв” и мусора вроде решеток и долларов? И так для двадцати разных сервисов?

    Тем не менее, все бездумно лепят одну и ту же схему: пароль, которому никто не верит, и коды с телефона. Тут явно нужно что-то менять.

    Самое смешное: сейчас вы повозмущаетесь в комментариях, а что потом? Пойдете пилить форму авторизации с паролем.

Страница 2 из 93