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

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

Доступ к базе в приватной сети

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

docker run --rm -it postgres:14 /bin/bash

или

kubectl run -it --rm tmp-psql --image=postgres:14 --restart=Never -n prod --command /bin/bash

Интересных флагов тут два: --rm, который говорит о том, что надо удалить под/контейнер после использования, и --restart=Never для того, чтобы создался только просто под, а не deployment.

(Как все просто было во времена железных серверов — просто провалился через ssh на хост и все).

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

Тестовые флаги

Использование условий вида if (test) или if (user in testUsers) — это рак.

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

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

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

Иногда подобным образом переключают часть функциональности (хотя для этого есть feature-флаги). Иногда так еще “упрощают” жизнь для нагрузочных тестов (т.е. тестируют не настоящую работу) или “для отладки” (хотя для этого есть ленивые логи с уровнями логгирования или внешняя инструментация).

Мне тяжело придумать нормальные обстоятельства, когда использование подобных условий будет оправдано. А поддерживать их накладно, они осложняют рефакторинг и засоряют код.

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

Suspend функции в Scala

В продолжение темы об излишних переусложнениях — на форуме Scala обсуждают предложение о добавлении корутин в стиле Kotlin. Со всеми недостатками двухцветных функций. Рекомендую почитать критику от де Гуза (автора ZIO) и сдержанный ответ Одерски (автора языка). Вкратце, suspend не нужОн, если зеленые потоки есть из коробки, и они планируются в рамках проекта Loom. А в Scala Одерски видит перспективы в более мощной типизации и в capabilities.

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

Context receivers

В рабочем проекте попробовал добавленные недавно context receivers. Вкратце, это очередной сахар, который позволяет требовать, чтобы функция вызывалась в контексте, содержащем какой-то класс как this:

context(Logger, DBConnection, Request)
fun someFunc() {
  log(select(request.param))
}

Под капотом компилятор генерирует дополнительные параметры для вызова функции.

В текущей версии (1.6.21) все очень сыро — я споткнулся об пару багов компилятора и пару ошибок во время исполнения в довольно простых случаях. Для прода это точно не готово (я использовал в тестах). Могут получиться уродские лямбды:

suspend fun someFun(
  block: suspend context(Logger, DBConnection) Request.(Param) -> Unit
)

Компилятор не всегда понимает, из какого контекста метод (и я натыкался на случаи, когда ему не удавалось это объяснить). Как и с suspend, функции приобретают “цвет”. У this непонятный тип — вроде объединение, но явно это не получить. Наконец, форматирование съезжает:) Больше критики можно почитать тут, похвалу — тут, а больше вариантов применения — тут.

Без сахара подобные задачи можно решать созданием одного класса Context и вызова функций с дополнительным параметром(ами) или через receiver: fun Context.someFunc(). Была бы поддержка типов-объединений, то тогда это было бы гораздо более читаемо (особенно с typealias). Ну а так вообще это все ради того, чтобы неявно передавать аргумент в функцию. И подобную проблему уже давно решили с помощью имплиситов в Scala. В общем, мне кажется, что начинается излишнее переусложнение, которое еще и хреново реализовано.

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

Разделение рабочего и личного на ноуте

Весьма скоро после перехода на удаленку рабочие задачи и личные почти полностью стали выполнятся на одном компьютере.

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

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

Сейчас я разделяю два пространства попроще — просто два рабочих стола (виртуальных) для смены контекста, и выделенный браузер для чисто рабочих задач. И еще одно место, где требуется разделение — git. Там настроено два профиля под разные директории:

$ cat ~/.gitconfig
[includeIf "gitdir:/home/ov7a/github/**"]
  path = ~/.gitconfig.personal
[includeIf "gitdir:/home/ov7a/work/**"]
  path = ~/.gitconfig.work

$ cat ~/.gitconfig.personal 
[user]
name = ov7a
email = home@address.ru

$ cat ~/.gitconfig.work 
[user]
name = Vlad Chesnokov
email = some.work.email@company.com

Т.е. все репозитории в рабочей папке будут иметь рабочий акк, а в папке под всякую дичь — личный.

И… все, пока потребности разделять что-то еще не появилось.

P.S. В первое время удаленки я даже заморачивался и разделял работу и дом сменой футболки, и это реально помогало. Но летом в жару 30+ я на это быстро забил:)

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

Локальный запуск билда Gitlab

Как отладить непонятную проблему в CI, если нет доступа к внутренним логам? Запустить локально ее агент, благо сейчас все в контейнерах.

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

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

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

Рейтинг постов канала в Telegram

Накалякал скрипт, который качает посты из указанного чата в телеге и сортирует их по метрикам. Внезапно, самым сложным оказалось найти версию библиотеки Telethon, которая и реакции поддерживает, и еще не сломана в процессе обновления на v2. Другую я заленился смотреть, но благо узнал, что можно ставить pip-пакеты прямо с GitHub’а:

pip install 'git+https://github.com/LonamiWebs/Telethon.git@539e3cb8081acbd9a5cc7a61c0731ca62842597e'

К сожалению, сам анализ никаких больших открытий не дал — посмотрел топ-посты в паре каналов с мемчиками, да и все.

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

SQL на csv

Прикольный рецепт как выполнять SQL запросы на CSV-файле: данные загружаются в in-memory sqlite, а там уже можно делать с ними что угодно.

Чтобы не запоминать зубодробительную строку, можно добавить функцию в ~/.bash_aliases:

function sqlcsv() {
  filename=$1
  shift
  sqlite3 :memory: -cmd '.mode csv' -cmd ".import $filename data" "$@"
}

Причем можно использовать как интерактивный режим, если передать только имя файла:

$ sqlcsv rus_cities.csv 
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> select * from data where source='омск' limit 3;
"омск","кадников","о"
"омск","казань","о"
"омск","калач","о"

так и неинтерактивный, если передать один или несколько запросов:

$ sqlcsv rus_cities.csv "SELECT DISTINCT(source) from data where source like 'ц%';" \
  "SELECT COUNT(DISTINCT(source)) from data WHERE source like '%ц' or source like '%цы';"
"цивильск"
"цимлянск"
"циолковский"
15

Конечно, это все можно сделать и в Excel/аналоге, но я лично потрачу больше времени на гугление нужных формул, чем на написание SQL-запроса.

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

Камеры на созвонах

Уже в нескольких утюгах обсуждают статью, в которой проводятся результаты нескольких исследований:

  • 103 человека медицинской компании, по результатам 4 недель на основе опросов: люди устают больше с камерами, камера незначительно влияет на вовлеченность, женщины и новички от камер устают больше.
  • опрос 10 000 человек, которые регулярно используют камеру на созвонах: женщины устают от встреч больше, более взрослые люди — меньше.
  • 150 обучающихся: студенты на лекции, где были включены камеры, лучше сдавали тесты.

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

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

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

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

Версионирование библиотек

Интересный доклад про то, какая бывает совместимость между разными версиями библиотеками, как безопасно приносить новое и удалять старое. Вообще целевая аудитория — разработчики библиотек, но и пользователям тоже полезно, чтобы понять, почему нужно писать всякие @ExperimentalAPI или @OptIn и как Kotlin дошел до жизни такой.

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