• Ажиотаж вокруг ИИ

    Репост с гугло-переводом. Автор — Kira (McLean) Howe

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

    Проблема не в самом ИИ, а в одержимости его инструментами. “ИИ” — это очень круто и, безусловно, полезно, но это всего лишь инструмент. Инструменты сами по себе не создают ценности, в отличие от тех, кто ими пользуется. Мы упустили из виду то, что действительно важно: результаты.

    Мы уже видели этот фильм. Помните большие данные? Все разворачивали кластеры Hadoop для объёмов данных, которые поместились бы в один экземпляр Postgres. Потом контейнеры и Kubernetes — невероятные технологии, но годами мы тратили больше времени на поддержку кластеров, чем на создание чего-то, что действительно было бы нужно пользователям.

    Потом микросервисы — в теории они великолепны, пока не начнёшь отлаживать распределённые системы, которые изначально не требовали распределения. Потом блокчейн, бессерверные технологии, GraphQL, сетки данных, отсутствие кода, метавселенная, “agile at scale” и т. д., и т. п. А теперь ещё и ИИ.

    Схема каждый раз одна и та же. Каждый обещал революцию и в некоторых конкретных ситуациях её произвёл. Но для большинства команд они стали отвлекающими факторами — дорогостоящим отвлечением от реальной работы по созданию ценности. Каждый из этих инструментов или идей действительно заслуживает внимания, но внедрение или интеграция без чёткой цели — напрасная трата времени.

    Инструменты сами по себе не создают ценности. Ценности создают результаты.

    Сосредоточьтесь на результатах, а не на тенденциях. Если инструмент помогает вам двигаться быстрее или добиваться лучших результатов — отлично. Используйте его. Но если нет, он вам не нужен, и уж точно не нужен вашим клиентам, как бы громко ни звучала шумиха.

  • Webp

    Webp — достаточно бесячий формат. Да, он на 30% плотнее JPEG, и это неплохо экономит трафик. Но беда в том, что с ним ничего нельзя сделать. Картинку Webp вы не вставите ни в один гугловый документ! — неважно слайды это или текст. В высшей степени странно: авторы формата сами же его не поддерживают.

    Есть такой костылик: когда ищете картинки для презентации, ставьте расширение Don't Accept Webp. Оно сводится к тому, что из заголовков Accept убирается элемент image/webp — мол, браузер его не принимает. Однако сервер все равно может вернуть webp, хотя вероятность этого и ниже.

    Еще вроде бы webp можно отключить в about:config, но я не нашел.

    Кроме того, анимированный webp не работает в Waterfox, и порой это неудобно.

  • О перехвате исключений

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

    Практика показывает, что “плана Б” почти никогда не бывает. Сценарий всегда один: взяли то, получили другое, прибавили третье — вот и результат. Отсюда следствие: поймав исключение, вы ничего толком не сделаете.

    Я уже приводил примеры. Нет файла на диске — с этим ничего поделать нельзя. Нет файла в S3 — тоже. Не задана переменная среды (пароль или токен) — без нее никуда не пойдешь.

    Почти каждая ошибка означает, что задача в целом провалена, и пытаться дальше бесполезно.

    По этой причине, кстати, в Джаве нынче используют unchecked-исключения, то есть те, которые не нужно объявлять в сигнатуре метода. Каждый, кто хоть немного писал на Джаве, знает — если использовать checked-исключения, каждый метод обрастает ими, как дно корабля — морским желудем. Эта зараза ползет по коду: метод, который вызывает зараженный метод, вынужден либо унаследовать бороду исключений, либо заткнуть их все и кинуть unchecked-исключение.

    С одной стороны теоретики заливают о контрактах и безопасности кода. А с другой стороны — практика, которая доказывает: это неудобно. Знаете шутку: в теории между теорией и практикой нет разницы, а на практике есть? Это как раз тот случай.

    Перехватывать исключения имеет смысл в редких случаях, например:

    • поллинг. Бывает, вы посылаете сервису задание: вычисли то-то и положи результат в S3. После этого начинаете поллить файл. На этом шаге логично перехватывать FileNotFound или похожие ошибки — до определенного лимита, конечно.

    • Запасной источник данных — иногда одни и те же данные можно добыть разными способами: из базы данных и временного хранилища. Если второе отказало, можно сходить в базу, перехватив исключение.

    • Троттлинг — если вы часто ходите в какой-то ресурс, он может сказать “умерь пыл”. На уровне кода это будет исключение RateLimitException или HTTPError с кодом 429. Их можно поймать, поспать секунду и повторить.

    • Ошибки ввода-вывода. Бывает, моргнула сеть, подвис роутер и скачать файл не удалось. Поможет перехват IOException и повтор операции. Только не забывайте, что все продвинутые клиенты учитывают сетевые сбои. Внутри у них своя логика повтора в случае IOException.

    Еще один случай — когда нужно показать красивое сообщение об ошибке. Даже если было исключение, некрасиво вываливать стек-трейс (а то и вовсе небезопасно) — нужно завершить программу культурно. Программисты на Питоне, мотайте на ус: ваши программы часто валятся со стек-трейсами, стоит только ввести не те данные.

    Иногда ошибки кидают намеренно — опять же, по нескольким причинам. Во-первых, встроенная функция может вернуть null, однако это не имеет смысла. Я уже приводил пример: не задана переменная среды: токен, пароль и так далее. Продолжать без нее нет смысла. Поэтому вместо System/getenv вызывают свою функцию get-env!, которая кинет исключение, если переменной нет.

    В противном случае вы будете долбиться в сеть с заголовком X-Authentication: aws-null-null, и ничего хорошего из этого не выйдет.

    Другая причина — внести ясность в чужие исключения. Порой их сообщения лишены деталей и потому бесполезны. Например, “file not found” — какой файл? “Port is busy” — какой порт? “HTTP 404” — какой урл? Когда вызов один, разобраться еще можно. Но представьте, что у вас цикл, пул тредов — желаю счастливой отладки.

    Поэтому такие исключения оборачивают своими, которые говорят: file C:\windows\mustdie.text not found, HTTP 404: GET http://test.com, port 5432 is busy и так далее.

    Поймать исключение и подавить его, не имея на то причины — один из худших паттернов в программировании. Недавно я добился того, чтобы один сервис отвечал ошибкой, если нет файла в S3. До меня было так: разработчик читал его из S3 и парсил JSON-библиотекой. Все это он оборачивал в try-catch с логикой: если пошло не так, записать в лог и вернуть nil. В Кложе nil ведет себя как пустая коллекция, поэтому на вычислениях это не сказывалось, просто они были пустыми.

    В день было по 50.000 (прописью — пятьдесят тысяч) подобных ошибок. Все они были в логах. Кто-то хоть раз их читал? Разумеется, нет.

    Проблема вскрылась лишь в тот момент, когда код слегка изменили. В результате получалась мапа с нуллом в ключе: {nil ...}, и наш JSON-сериализатор падал: мол, не знаю, что делать с null-ключом. А до этого проблем не было. Не падает — значит, все хорошо.

    Так вот, возвращаясь к первоначальному тезису. Перехватывая исключения, думайте про “план Б”. Действительно ли он у вас есть? Лично я сомневаюсь. “​​План Б” — это буквально три-четыре случая, а все остальное — трусость, неопытность, желание замести проблемы под ковер.

    Крайне вероятно, что имеет место второе, а не первое.

  • Игровые валюты

    Как-то раз на меня нашла деградация: поставил на телефон тупую стрелялку. Примерно как 15 лет назад: бесплатную, но с продвинутой системой выжимания денег.

    Кроме бесконечных выпадашек с просьбой что-то купить удивило другое, а именно — разнообразие валют. Смотрите, есть сами деньги. Есть золотые слитки для премиум-товаров. Есть какие-то кристаллы. Есть энергетические сгустки, а еще какие-то кубки, бонусы, баллы и так далее. Я даже не запомнил номенклатуру, не говоря уж о том, для чего нужна та или иная валюта.

    Вдобавок это неудобно: чтобы купить пистолет, нужны кристаллы. Чтобы открыть бонус-уровень, нужны сгустки. Хоть на бумажку записывай. Разумеется, чьи-то дети сидят в игре часами и на память знают, что нужно для чего. Но такую роскошь я позволить себе не могу.

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

    Похожую вещь наблюдаю в фирмах с особо креативными менеджерами. Например, в Озоне. У них есть баллы, мили, вау-баллы, звезды. Есть бонусы продавцов. Недавно добавили какие-то морковки, засунули зайцев в каждую щель. Это все хорошо за одним исключением — я не понимаю, что вообще происходит. В многообразии валют, баллов и миль исчезает ясность: какие у тебя привилегии.

    Нужно, чтобы менеджерам Озона кто-то сказал: ребят, морковки это хорошо, но старое нужно подчищать. Похоже, вы сами не особо понимаете, что у вас там: мили, баллы и так далее. Навели бы порядок.

  • Python в Windows 10

    Виндуз 10 — мягко говоря, странная вещь. Во всех операционках Питон идет из коробки, а на Винде его нет. Вместо него — заглушка. Если набрать в консоли python foo.py, появится надпись: друг, у тебя нет Питона. Чтобы поставить его, просто введи python.

    Хорошо, ввожу python. Открывается магазин приложений и тут же выстреливает алертами: и какая-то ошибка, и регион не тот, и токен протух. Еле закрыл к чертям, а то и дальше бы кидался ошибками.

    Скачал Питон с официального сайта, поставил. Ввожу python foo.py — опять та же самая заглушка. Минуточку, где Питон, который я поставил минуту назад? Начинаю искать. В дни моей молодости он ставился в корень: C:\Python27. Там его нет. Ищу в C:\Program Files (обоих папках) — тоже нет. Наконец догадался: проверил ярлык в меню Пуск. Знаете куда он ведет? Вот:

    C:\Users\ivan\AppData\Local\Programs\Python\Python3.8\...
    

    Удивляюсь, какими же уродами надо быть, чтобы так сделать? Мало того что засунули его глубже некуда, так еще не сменили заглушку для магазина!

    Ладно, может быть заглушку нельзя трогать по условиям лицензии. Тогда почему инсталятор не добавил путь к Питону в PATH?

    Ничего не работает как надо. Какое-то сборище клоунов, честное слово.

  • Непонятный код

    Одна из самых бесячих вещей — когда кто-то вбрасывает непонятный код и спрашивает, что он выведет. Откуда я знаю, что он выведет? Запусти и посмотри. Еще лучше исправить код, чтобы он был понятен сразу.

    Я еще могу понять, если это какой-нибудь сишный код, оптимизированный по самые помидоры, чтобы умещаться в кэше процессора. Это чужой монастырь, и там свои погремушки. Но когда это обычный бизнес-код типа “принять две мапы и взять наибольший ключ”, оправданий быть не может.

    Почему-то мало кто понимает: писать непонятный код легко, а понятный — трудно. На это уходят годы практики, нужно пройти много ситуаций, чтобы понять, какой код и при каких обстоятельсвах понятен. Вываливать непонятный код — то же самое, что мочиться в штаны. Нужно тихо решить проблему, а не тыкать ей в лицо.

    Вообще, угадывание — худшее, что есть в айти. Когда угадываешь, фактически ты на дне. Ты исчерпал все нормальные варианты, ну или их не было. Должна быть легкая возможность запустить код — привет, программисты без репла. Должны быть тесты, линтеры, логи, метрики, бенчмарки, сбор ошибок и так далее.

    Угадайка — это билет в проигрыш, иначе быть не может. Да, бывают истории, когда человек раз — и решил сложную проблему, не имея никаких улик. Но это ошибка выжившего: на каждую такую историю приходится тысяча других, когда человек просидел выходные, решая проблему брутфорсом — и на двадцать пятой итерации что-то помогло. Я бы не рассчитывал на такую удачу.

    Короче, видишь плохой код — исправь, не гадай.

  • Без исключений

    Меня искренне изумляют ребята, которые обходят исключения стороной. Типа, вернем null и запишем в лог. Или вернем мапу {"success": false}. Или кортеж (nil, "error"). Или еще какой-то финт ушами.

    Мне интересно: а кто будет читать логи? Тот чел, который молча пишет в лог, у него что, в договоре прописано каждое утро их читать? С какой частотой? И что делать, если логи нашлись? Как реагировать? И кто следит, чтобы он их читал?

    Или какой-то калека вернул мапу {"success": false}. Что с ней делать? Какая была ошибка? В каком направлении двигаться? Просто неопытный разработчик переложил на других то, что должен делать сам.

    Замалчивание ошибок — признак неопытности программиста. В единичном случае это еще не страшно. Но когда каждая строчка возвращает null или мапу вместо ошибки, работать невозможно. Приходиться писать строгие обертки вокруг таких функций, которые кидают исключение с понятным сообщением: что я собирался делать и что пошло не так.

    Один коллега предложил: давай я буду возвращать сообщение об ошибке, если файла нет? Я аж чуть кофе не выплюнул: минуточку, все это время ты молчал о том, что файла нет? Блин, уж будь добр, потрудись сообщить о проблеме.

    При либом отклонении от нормы нужно кидать исключение с максимально детальным текстом. Вот, вобщем-то, простой секрет хорошего кода.

  • Фотографии на Маке

    Моя семейная жизнь течет спокойно и счастливо, однако нет-нет да окажется на грани развода. Всему виной они – фотографии.

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

    Даю жене яблочный ноут. Не проходит и пяти минут, как слышу: почему файл не открывается по нажатию Enter? Почему, открыв фотографию, нельзя перейти к соседней стрелочками? Почему сочетания кнопок такие неудобные? Почему нет бегунка, чтобы превьюшки стали больше?

    Ни на один упрек я не знаю ответа. В этом плане я обычная тряпка, яблочный приспособленец. Я не знаю, почему по нажатию Enter система предлагает переименовать файл, а не открыть его. Возможно, Стив Джобс был под наркотой, когда придумал это. Иначе как объяснить, что вместо Enter нужно либо дважды кликнуть по файлу, либо нажать Command+Down?

    Как часто мы открываем файл, а как часто меняем его имя? Что в приоритете? Ничего, что на клавише написано Enter – по-английски “войти”, а не “переименовать”? Сколько ЛСД принял Стив в тот вечер?

    То же самое с переходом между фотографиями. Когда человек открыл одно фото, он захочет посмотреть соседнее и нажмет стрелку влево или вправо. Логично же? Эпл предлагает выделить фотографии в Finder, нажать правую кнопку мыши, открыть в Preview. После этого можно просматривать несколько фотографий, – но только те, что выбрал.

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

    Файлы в режиме значков не подстраиваются под ширину окна. Если в ряду их десять и вы ужали окно, матрица не перестроится. Появится горизонтальный скроллинг, и часть файлов вы не увидете.

    Выбор фотографий превратился в маленький адок, который нужно пережить. Однако и я стал умнее. Зная, что супруга управляется с Виндой, я теперь делаю так. Отбираю фотки, которые ее интересуют, и помещаю в какой-то альбом. Это легко сделать на телефоне: достаточно выделить файлы и пометить тегом.

    Далее открываю яблочный ноут, приложение Photos. В нем работает экспорт файлов на диск. Разумеется, можно достучаться до файлов и обычным способом, но это нелегко. Фотографии хранятся в чертовом HEIC – яблочном формате, который совмещает в себе JPEG и HDR. Это добро откроется только на яблочной машине. У файлов машинные имена-уиды, а вся мета о них лежит во внутренней базе данных.

    Я думал, Эпл позволит экспортировать только штучные файлы. Но все оказалось проще: можно экспортировать целый альбом, и на диске появятся нормальные джипеги и mp4.

    Осталось перетащить их на Винду. Это тоже проблематично, потому что шаринг файлов между Эплом и Виндой максимально костыльный. Есть вариант с флешкой в exFAT. Но еще лучше воткнуть флешку в роутер и поднять на нем FTP- или SMB-сервер. Все просто: на яблоке закинул, на Винде скачал.

    И знаете, жить стало намного легче!

    Вот так технологии спасают семейную жизнь.

  • Чат вслух

    Бывает, пишешь коллеге: дружище, я вызываю такой-то сервис, посылаю мапу:

    {:foo 42
     :data ["some-type"]
     :items [:kek :lol :crap]}
    

    Сервис возвращает не то. Вот логи, вот ссылки, вот трассировочный заголовок. Все для тебя, мой милый-хороший.

    В ответ человек срет сообщениями:

    привет :)

    надо items передать через точку с запятой :)

    вроде так было в последнем коммите

    или погоди его не выкатили :)

    спроси девопсов выкатили или нет

    и еще foo надо не 42 а 41 :)

    по ходу да

    или не :)

    а да

    мы так тестировали работало :)

    на пре-проде работало помню

    и без двоеточий передай

    так заработает :)

    Я смотрю на это и думаю: ладно, есть люди, которые думают вслух. Им легче писать и проговаривать про себя, чтобы что-то вспомнить. Бывает. С этим можно смириться.

    Однако в конце этого выхлопа я ожидаю вердикт: какой запрос все-таки передать. Но этого не происходит: собеседник решил, что уже помог. Приходится идти по списку сообщений и применять каждое утверждение (“по ходу да”), а возможно, откатывать (“или не”).

    Что тут сказать? Других мы не исправим, а вот себя исправить можно. Не вываливайте на собеседника поток сознания, а если это имело место, подведите итог. Достаточно смотаться к первому сообщению и коротко на него ответить.

  • Интерфейс музыкальных сервисов

    Не знаю, как так вышло, но сегодня ни один — буквально ни один — музыкальный сервис не может сделать хороший интерфейс. Ни Гугл, ни Яндекс, ни кто бы то ни было. Не помогают ни миллионы денег, которые сервисы гребут за подписку, ни дизайнеры за 400 тыщщ долларов в год.

    Яндекс-музыка уже давно стала мемом а-ля Medium: хорошее начинание превратилось в музей багов. Без преувеличения можно сказать, что каждый квадратный сантиметр ее дизайна несет бред. Гугл со своей Музыкой не лучше: там все прыгает, переключается, показывает выпадашки.

    Прикладываю картинки. Слушаю музыку из мультика, вроде бы все в порядке. Но что-то нажал — открылось то же самое, но в другом лейауте. Почему? Без понятия. Как вернуться обратно? Тоже без понятия.

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

    И разумеется, сервису не хватает места. Даже на 4к-мониторе дизайнер не может все уместить. Треки приходят с сервера пачками по 20 штук, нужно проматывать страницу, чтобы они подгрузились, иначе поиск на странице не работает.

    Ради интереса сравните с Винампом: на ЭЛТ-мониторе в разрешении 800x600 он занимал только часть экрана. Там было все: кнопки, перемотка, плейлист, эквалайзер. Можно было поставить рядом Total Commander, и места хватало на две программы.

    Умели же люди делать плеер для монитора 800x600! А сегодня это сродни навыку писать на ассемблере.

    Секрет-то на самом деле простой. Я бы выдал дизайнерам ЭЛТ-мониторы и сказал: все должно помещаться на экране. За каждую выпадашку этим монитором тебя будут бить по голове. И тогда бы все наладилось — я гарантирую это (с).

Страница 5 из 105