Минутка просвещения

Читать в телеге. Когда-то там были посты не только от меня.

"Стандарт" UTF-8

Помню в далекие времена бомбило от CP1251, вот зачем эти однобайтные кодировки, есть же нормальный UTF-8, который совместим с ASCII, используй его везде и не парься, ну! Сегодня в интернете трудно найти сайт не в UTF-8 кодировке, Firefox даже запрятал смену кодировки куда-то далеко в глубины меню. Да и получить проблемы с кодировкой на сайте — моветон, предание старины глубокой…

И вообще это все от лукавого винды, вон на линуксе и на маке почти везде UTF-8… Но он там, оказывается, разный. В UTF-8 есть несколько нормальных форм. Если коротко, то символ â можно представить как один сложный символ (это NFC), а можно как комбинацию обычной a и крышки (это NFD).

Сам стандарт рекомендует использовать везде NFC. Linux и почти весь web используют его. У Apple другой путь — они используют NFD.

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

СсылкаКомментировать

Убьет ли project Loom корутины Kotlin?

Неплохой доклад. Ответ, разумеется, “нет”.

В начале — стандартная теория про то, что потоки != корутины, немного истории и про то как работает Loom и корутины. Если сильно упростить, то Loom переносит манипуляции с объектами Thread с операционной системы на саму JVM: идея в том, чтобы с минимальными изменениями превратить приложение с кучей потоков в приложение с кучей корутин, например, заменяя Executors.newCachedThreadPool() на Executors.newVirtualThreadPerTaskExecutor(). Соответственно, у Loom нет разделение функций на обычные и suspend. В корутинах больше фокус на всякие плюшки от структурированной асинхронности.

Далее сравниваются цели двух проектов (они, разумеется разные) и компромиссы по производительности и другим аспектам. В будущем возможно использование Loom внутри реализации корутин — сейчас тяжелые IO-операции используют настоящие потоки, которые можно будет заменить на виртуальные.

СсылкаКомментировать

Тренажер промптов для обхода ограничений

https://gandalf.lakera.ai/

Классная шутка, чтобы почувствовать себя кул-хакером. Иногда вылетает из-за лимитов ChatGPT, но полезная зарядка для ума. Советую записывать свои успешные промпты, чтобы использовать их повторно.

СсылкаКомментировать

Типичные ошибки при построении микросервисной архитектуры

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

Вначале идет немного теории про разные виды “монолитов”, а потом разбираются собственно ошибки:

  1. Предполагать, что микросервисы всегда лучше монолита.
  2. Общие модели и/или общая база.
  3. Слишком большие микросервисы.
  4. Слишком маленькие микросервисы.
  5. Начинать построение нового продукта с микросервисной архитектуры.
  6. Связывание через инфраструктурный код (логгирование/авторизацию и т.п.).
  7. Использование синхронных вызовов между микросервисами.
  8. Обратно-несовместимые изменения в событиях.
  9. Отсутствие автоматизации релизов.
  10. Отсутствие инкапсуляции (когда микросервис слишком много знает о деталях реализации другого микросервиса).
  11. Несоответствие организационной структуры архитектуре продукта.
СсылкаКомментировать

Cyber Chef

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

СсылкаКомментировать

Области поиска в IntelliJ

В IntelliJ при поиске можно указать в качестве варианта, где искать, определенный тип кода — например, искать только в тестах. Эти области поиска можно редактировать, добавляя свои. Кроме того, можно настроить цвет отображения в списке всех файлов. В самом окне проекта можно отобразить только тесты/только основные файлы/свою область поиска. Все это можно шарить — это хранится в .idea вместе с остальными настройками проекта.

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

СсылкаКомментировать

Как работает Live Reload?

Live Reload — это возможность обновления локально запущенного приложения “на лету” при изменении исходного кода вместо того, чтобы его останавливать, перекомпилировать и запускать заново. Эта функция есть много где — например, у фронтендеров в npm, у бэкендеров в Spring, в Jekyll, внезапно в gradle (там это называется continuous build) и т.д. Для реализации этого механизма нужно отслеживать изменения в коде и потом их собственно применять.

Первый этап можно реализовать одним из трех способов:

  1. Запомнить состояние исходников (сделать снапшот) и периодически повторять эту процедуру, сравнивая новую версию со старой.
  2. Получать и обрабатывать уведомления от файловой системы.
  3. Перехватывать системные вызовы.

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

В Linux для уведомлений от ФС (второй способ) есть подсистема inotify. Использовать ее довольно просто: создается файловый дескриптор, к нему привязываются подписки на конкретные файлы и/или папки, потом в бесконечном цикле читаем структуры-сообщения об изменениях из дескриптора (ожидание будет за счет блокирующего read).

Кстати, в большинстве случаев за счет уведомлений от ФС работают команды вроде tail -f. Совсем всегда — не получится, т.к. удаленные системы обычно не посылают такой информации.

Механизм применения изменений сильно зависит от инструмента, но обычно сводится наличию демона/лоадера/супервизора, которые ждут сигнала о наличии изменений и при его получении обрабатывают изменения и заменяют текущую версию (перезаписыванием статики, перезагрузкой страницы, перезагрузкой классов из класслоадера и т.п.).

СсылкаКомментировать