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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Интерактивное программирование

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

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

Игра про SQL

Сабж.

В игре есть сюжет, но не могу сказать, что он блещет художественностью, перестал читать его после третьего задания. По комментариям в поле ответа можно узнать все необходимое. Иногда есть небольшие неточности в задании (взбесил момент, когда в комментах были попутаны “Returned” и “Recovered”, благо в большом тексте все было нормально), но больше расстраивают манипуляции со строками в районе 15 главы. Для некоторых ошибок выдается объяснение, но у меня в основном были просто сырые исключения SQL и TypeError: can't convert undefined to object. Местами торчит диалект MySQL (или SQLite?).

Но в целом неплохой тренажер получается для начального уровня. Всего там 20 заданий на select, join, group by и т.п. и аж одно на delete.

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

Микросервисы — решение для тех, кто не осилил модули

Одни из основных причин использования микросервисов (помимо культа карго, разумеется) — изоляция и инкапсуляция. Зачастую разделение на микросервисы сопровождается изоляцией на уровне команд и репозиториев: «это наш огород, даже читать нельзя!» Модно, стильно, молодежно, компетенции растут, ответственность четко ограничена (все же знают, какой команде какой микросервис принадлежит, кек).

Альтернатива микросервисам — использование модулей. Если у вас есть какая-то обособленная функциональность, то не обязательно ее изолировать жесткими мерами. Можно просто этот код иметь в отдельном модуле/пакете/папке, и настроить тупейший линтер, чтобы карал за хождение между модулями. При этом можно переиспользовать какие-то общие вещи вроде конфигов, авторизации или всяких утилит. И сделать отдельный конфиг/модуль собственно для запуска кода: если модули изолированы, то легко сделать опции чтобы запускать/собирать только нужный модуль (например, для продакшена со всяким масштабированием, запихиванием в контейнеры если надо и т.п.), набор модулей (например, какие-нибудь фоновые работы) или все вместе (например, для локального запуска).

Расходы на поддержание сопоставимы с микросервисами — пайплайны все равно нужны, думать о межмодульном взаимодействии и инкапсулироваться все равно надо, надо управлять монорепозиторием и т.д. Но при этом можно снизить дублирование, править что-то по мелочи в «чужом» коде (потому что у «них» приоритета на нужную тебе хрень нет) и делать глобальные улучшения (обновление версий библиотек, например). При этом делить на модули приложение можно со старта и постепенно эволюционировать до большей изоляции между ними (использовать несколько баз вместо одной, вкорячивать очереди задач между модулями и т.п.). Да и на те же самые микросервисы разделиться, если будет оправдано.

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

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

Несколько аккаунтов с одной почтой

Если у вас есть почта your@email.com, то большинство почтовиков будут на нее же слать все письма от your+anyvalidcharacters@email.com, потому что будут считать все символы после + дополнительным тегом. Подробнее можно почитать, например, в RFC.

В свою очередь большинство сайтов будут считать your@email.com и your+awesome@email.com разными адресами. Таким образом, можно зарегистрировать два разных аккаунта, имея только одну почту.

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

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

Впечатления от GitHub Copilot

На всякий случай: пробовал не последний Copilot X, а обычную версию.

Когда удаляешь ненужный код, чтобы переписать его получше, он предлагает написать его же. Один раз предложил мне 3 копии моего же кода, т.е. “работает — не трогай” усвоено :/

Довольно часто предлагает вообще невалидный код — например, с несуществующим методом. Нет, я бы конечно сам попробовал так написать, но хоть какую-то валидацию хотелось бы иметь, благо можно спросить IntelliJ, в которой все это запущено. Но иногда Copilot предлагает откровенную дичь — например, предлагает паттерн-матчинг для Option для метода, который обычный String возвращает.

В некоторых простых случаях предлагает прямо то, что надо. Однако это обычно бойлерплейт. Да, для него он весьма хорош, но казалось бы, если надо писать бойлерплейт, то стоит что-то поменять в архитектуре или сменить язык? Хотя даже с ним Copilot может налажать — например, он передал не все аргументы в функцию с аргументами по умолчанию. Да и типовые задачи а-ля получить Stream из Iterator (что в java делается миллионом способов) иногда не может решить, на StackOverflow все еще надо было ходить.

В общем, вау-эффекта не произвело, но и отключать его пока не стал. Если пишете на чем-то унылом типа Java или Go, то иногда может помочь. Если на чем-то помощнее, то чаще будут подсказки не в тему, которые будут отвлекать.

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

Автоматический поиск индексов для базы

Я сталкивался со следующими подходами по добавлению индексов:

  1. Что-то стало тормозить — добавляем индекс “на глаз”. По умолчанию добавляем на что-то очевидное.
  2. Мониторим slow query, анализируем запросы, добавляем индекс по анализу статистики (это обычно выделенные DBA).
  3. Добавляем индексы на все поля по умолчанию, а там авось что пригодится.

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

На прошлой работе написал велосипед, который извлекал все SQL-запросы из юнит-тестов и прогонял их через EXPLAIN ANALYZE на копии продовой базы. Это работало весьма неплохо, но доавтоматизировать это до CI-стадии я так и не успел.

Что-то похоже есть и в опенсорсе — эта утилита делает примерно то же самое, только еще и сама создает “гипотетические” индексы и проверяет, что они дадут ускорение запросов. Использовать ее на проекте не смог, т.к. расширение для этих гипотетических индексов нельзя поставить на AWS-овский Postgres :/

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