Стендап Сьогодні

Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті

Підписатись на RSS
📢 Канал в Telegram @stendap_sogodni
🦣 @stendap_sogodni@shevtsov.me в Федиверсі

15.06.2023

Сучасний стан розробки на ClojureScript

На Реддіті побачив запитання про засоби перевірки OPML файлів для RSS. Ба, думаю, так я ж такий писав. От тільки давно. Та є два нюанси. По-перше, він був розміщений на моєму виділеному сервері, який я давно припинив підтримувати (бо складно). По-друге, написаний він був на Clojure/ClojureScript, бо в ту епоху (у 2015) мені було цікаво кудись його застосувати.

Куди розмістити зараз — в мене вибір один - Firebase. Бо дешево та просто. Але Firebase на бекенді підтримує тільки JavaScript. Не проблема, в теорії, бо бекенд можна портанути з Clojure на ClojureScript. Знайшов гарну інструкцію, як запустити ClojureScript на Firebase Functions, та це дійсно швидко спрацювало.

До переписування бекенду я поки не дійшов, бо ще треба оновити фронтенд. Майже все, що я використовував 8 років тому, померло. Зʼявилися нові інструменти. Замість Figwheel для збірки проєктів тепер є Shadow CLJS. Дуже приємно працює, з простими налаштуваннями робить дві збірки — бекенд та фронтенд, сам завантажує залежності (зі світу Clojure; ті, що на Javascript, завантажує yarn, як звичайно), в браузері наживо оновлює. По цьому питань взагалі нема.

Фреймворк для фронтенду Om теж більше не підтримується. Вони самі рекомендують переїхати на Fulcro. Це дуже складна система зі власними абстракціями та з привʼязкою до свого фреймворку на бекенді. В мене найбільше питань по тому, що для вибірки даних зі стану використовується EQL. Для простого додатка це зайві ускладнення.

Зате re-frame все ще живий. Re-frame це як React+Redux+Reselect в красивій функціональній абстракції. Його я б і рекомендував брати, якщо захочеш спробувати Clojure. Це, напевно, найкрутіше що є з практичних міркувань.

Для форматування коду мені дуже подобався parinfer, але й він більше не підтримується. Для розробки в VSCode є доповнення Calva з власним форматувальником — до нього треба звикнути, але задачу балансування дужок, в цілому, він виконує.


14.06.2023

WaitGroup в Go

Для закінчення питання, поставленого вчора, не вистачає ще однієї частини. Ну, добре, зробили ми архітектуру на контекстах, контекст сплинув, горутіни отримали сигнал зупинки. Що далі? Необхідно дочекатись, доки всі горутіни завершать свою роботу. Особливо якщо зупиняємо всю програму — якщо не чекати, то немає сенсу навіть ввічливо попереджати горутіни про зупинку.

Можна знову придумати свою систему з каналами, і так далі. А можна взяти стандартний тип sync.WaitGroup, який створений саме для того, щоб чекати зупинки декількох горутін. Від банального лічильника його відрізняє наявність методу Wait(), який буде чекати, поки всі горутіни не викликають метод Done().

Тобто алгоритм таких: на початку підраховуємо кількість горутін, які запускаємо, та заряджаємо викликом wg.Add(). Далі, кожна горутіна по завершенню викликає wg.Done(). Нарешті, головна горутіна спочатку сигналізує про завершення контексту, а потім викликає wg.Wait().

Чи не надто витратно створювати WaitGroup для довготривалих процесів? Ні, цей тип містить лише 2 цілих числа, та не має “живого” коду. Взагалі це просто лічильник + семафор, нічого магічного. Це добре, бо нам потрібно передати WaitGroup в кожну горутіну, яку ми запускаємо.

Як чекати з обмеженням по часу? Це типова задача — наприклад, ми знаємо, що через 60 секунд після отримання сигналу наш процес буде вбитий оркестрантом. Відповідь така: обмеження треба обробляти ще всередині горутін. Що це значить на практиці — залежить від конкретного випадку. Але ми точно повинні не кидати горутіни у невизначеному стані, як воно буде, якщо тайм-аут спрацює назовні.

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


13.06.2023

Контексти в Golang

Як зупинити код у відповідь на зовнішній фактор? Один з механізмів відомий всім — то команда kill, якою можна зупинити цілий процес. Але, як зробити це всередині програми? Що робити, коли блок коду займає більше часу, ніж ми можемо чекати? Це реальні питання, які часто не мають гарної відповіді. Ось в Ruby, наприклад, є модуль Timeout, який наполегливо рекомендують не використовувати.

В Go питання зупинки процесів стає ще актуальнішим, оскільки створення одночасних процедур — типова повсякденна робота. Як зупинити всі ті горутіни, коли вони більше не потрібні? Можна накрутити (та я й крутив) додаткові канали для сигналізації. Зупиняємо сервіс — сигналізуємо горутінам.

…Паралельно з цим доводиться постійно передавати в різні бібліотечні функції якийсь “контекст”. Нащо він потрібен той контекст — не знаю. Добре що завжди можна створити новий на місці, наприклад функцією context.Background().

Та тільки нещодавно зрозумів, що контексти в Go і є той самий механізм зупинки коду у відповідь на зовнішній фактор. У контексту є метод ctx.Done(), який повертає канал, що буде закритий, якщо пора зупиняти код. Для перевірки використовується команда select. Це й треба використати замість самописних механізмів. Більше в документації.

Щоб створити власний корисний контекст, є відповідно функції context.WithCancel та context.WithTimeout. Особливо зручно те, що такі функції загортають контекст батьківського рівня, та успадковують закриття ще й від нього.

Для сигналів, про які я вже згадав, є signal.NotifyContext. Сервіс, який себе гарно поводить, має спиратись саме на цей контекст, щоб контрольовано зупинити всі свої компоненти.

Тепер ніяких більше context.Background().


12.06.2023

Сумний стан української локалізації

Коли я сьогодні дізнався, що Cyberpunk 2077 невдовзі отримає українські субтитри, зрадів. А потім, захотів зрозуміти, який взагалі на 2023 рік стан локалізації. Вирішив зробити маленьке дослідження самотужки.

Звідки взяв дані. Відразу обрав як джерело Steam, щоб якось обмежити вибірку. Теоретично, каталог Steam відкритий для всіх, та є сервіси на кшталт SteamDB, які його викачують. Але саму базу для аналізу довелося ще пошукати, бо стягнути її не дають, а потрібного мені функціоналу пошуку не вистачало. Нарешті знайшов на Гітхабі версію на грудень 2022 року. Далі написав скрипт на Ruby, який генерує CSV з результатами. Далі — робота редактора таблиць.

Результати, на перший погляд, прикрі. Тільки 1746 ігор загалом перекладені українською. У відсотках це лише 8%. Менше, ніж російською або польською. Але більше ніж, наприклад, тайською — при тому, що в Таїланді живе 70 мільйонів людей.

(Цю цифру складніше отримати, ніж можна уявити. З ігор треба викреслити всі, що не мають локалізації зовсім — зазвичай це ігри англійською або китайською. До того, як це зробив, спостерігався різкий спад локалізації у 2014 році. Це пояснюється запуском програми Greenlight, за якою випустити гру в Steam стало набагато простіше.)

Якщо ж дивитися на значення в динаміці, то картина краща. З року в рік кількість ігор українською зростає. З ігор, що вийшли у 2022 році, перекладено було 10%. Взагалі бачу дві групи мов: є “класика” локалізації — французька, німецька, італійська, іспанська — ці мови втрачають долю локалізації. А менш представлені мови — як корейська, норвезька або українська — поступово її збільшують. Все це можу пояснити тенденцією до мовної інклюзивності.

А з українською озвучкою все зовсім погано. Хоч в базі значаться близько 500 ігор, насправді більшість з них практично не має озвучки як такої. Реально можна порекомендувати хіба що серію Metro 2033 та всі частини Сталкера. Та, як не дивно, першу частину Baldur… ее, Брами Балдура. Оце справжня, міцна RPG. Та вся озвучка перекладена. Я спочатку й не повірив, довелося встановити та перевірити. Звісно, голосу в Брамі мало, зате тексту як в добрій книзі. Одним словом, рекомендую.


11.06.2023

Які RSS я читаю?

Поступив запит на рекомендації по RSS. Раніше я писав про те, як я користуюсь RSS взагалі. Складно давати рекомендації по конкретних стрічках, бо фактично через RSS можна споживати майже все, що вам цікаво в інтернеті, але все ж таки висвітлю дещо з того, на що я підписаний.


10.06.2023

Рімейк System Shock

В мене з System Shock смішна історія. Перший раз я про цю гру почув десь у 2001 році, та витратив може місяць, щоб викачати її через модем зі швидкістю 56.6К. На жаль, мене чекало тільки розчарування, бо користуватися архаїчним (вже на початок сторіччя) інтерфейсом не зміг. Після години чи двох спроб гра була закинута.

За минулі 22 роки я встиг пограти у всі нащадки System Shock - від System Shock 2 та Deus Ex до Dishonored та Prey. Тому, коли у 2016 році відкрився Kickstarter для створення рімейку, то я підтримав його без роздумів. На розробку пішло 7 років, але нарешті рімейк вийшов.

Та вийшов пречудовим! По суті це абсолютно нова гра, яка близько відтворює рівні та сюжет оригіналу. Вочевидь багато чого змінено; насамперед темп гри змінився абсолютно, та, я так розумію, довелося переосмислити озброєння та противників. Тепер це повноцінна бродилко-стрілялка з інвентарем, за формулою дуже нагадує Prey.

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

Чи рекомендую я System Shock Remake? На всі 100! Чи хороша це гра сама по собі? Так, чудова.

Тепер з ігор, в які я б дуже хотів пограти, але не можу через архаїчність, залишається Fallout 1 та 2. Може, і їх дочекаюсь. А ще все ж таки хочеться тепер спробувати оригінал System Shock, або принаймні Enhanced Edition.


09.06.2023

PostgreSQL vs Elasticsearch

Поступив запит: чим Elasticsearch краще за PostgreSQL. Спробую сформулювати. Наперед скажу, що питання скоріше не чим, а де або для чого.

Постгрес — це база даних загального призначення. Вона вміє все. Та з кожною новою версією ще більше. Якщо порівнювати суто по можливостях, то з PostgreSQL можна робити що завгодно. В цьому його головна перевага. Якщо з чогось починати проєкт, то Постгрес найкращий вибір, завжди (якщо в бюджеті є місце для сервера бази даних, звісно.)

Єдине, що PostgreSQL робить гірше — це масштабується. Рішення для горизонтального масштабування існують, проте коли вертикальне (збільшення машини) не розв’язує задачу, то, на моєму досвіді, всі обирають поміняти базу. Наскільки вистачить однієї машини — залежить від того, що потрібно зберігати. Для облікових записів користувачів — напевно, вистачить назавжди. А для, скажімо, щосекундних аналітичних метрик — може й для старту буде мало. Бо як БД загального призначення, у PostgreSQL доволі обмежені здібності оптимізувати під задачу.

Як я вже писав, для вирішення сучасних потреб в масштабуванні зʼявилися бази даних NoSQL. В їхньому числі й Elasticsearch (так, як я вже писав, Elasticsearch - справжня база даних.) В серці кожної NoSQL бази сидить компроміс: так, вона масштабується, але характер використання буде обмежений. Тому, при виборі NoSQL бази, треба дуже уважно дивитись, що вона вміє, та чи не буде вам потрібно щось інше.

Elasticsearch вміє класний складний пошук та агрегації. При цьому його легко масштабувати як на запис, так і на читання. Як приклад того, що він робить погано: поєднання документів на кшталт JOIN. Тобто в базі мають сидіти документи, які нас цікавлять самі по собі.

Такий режим використання гарно себе показав для всілякої журнальної інформації, тому зараз більше можна побачити Elasticsearch як базу даних для журналів, ніж як пошуковий рушій (бо, якщо все, що вам потрібно — це повнотекстовий пошук — то його чудово вміє робити Postgres.)

На останнє, не раджу читати абстрактні порівняння вигляду “знайди 10 відмінностей”.  “PostgreSQL - реляційна база даних. Elasticsearch - документна” і так далі.  З таким підходом в сучасних базах (та й взагалі технологіях) швидко загубишся. Щоб обрати базу, треба розуміти, що вона робить краще інших, та може ще важливіше — чого ніяк не робить. А якщо є сумніви — беріть PostgreSQL. :)


08.06.2023

Кілька думок про Docker Compose

Сьогодні був день Docker Compose. Як я вже писав, в нас багато на нього навішано. Взагалі, як на мене, якщо вам доводиться працювати над системою складніше, ніж класичний LAMP-стек, то варто опанувати Docker Compose та відтворити на ньому архітектуру.


07.06.2023

Kafka

Тиждень тому я писав про важливість перенесення навантаження з критичного шляху. А також про те, що це вирішується чергами. Черга надає можливість передати роботу з одного сервісу до іншого. Але є проблема — черга це труба о двох кінцях. Нам обовʼязково доведеться створювати споживача “в пару”. Черга створює жорстку звʼязку сервісів.

Apache Kafka розв’язує цю проблему. Це дещо середнє між чергою та базою даних. Як в черзі, дані організовані в послідовність повідомлень. Як в базі даних, ці повідомлення надійно зберігаються миттєво після приймання, та не видаляються після їх прочитання та обробки. Категорія сервісів, до яких належить Kafka, називається брокер повідомлень. Один сервіс (або сервіси) повідомлення пише, інший (або інші) читають - все з надійним посередником посередині.

Як на мене, то в першу чергу Kafka корисна тим, що дозволяє високонавантаженому сервісу максимально швидко писати дані, без того, щоб відразу розробляти архітектуру їх обробки. Це й спрощує розробку, й підвищує надійність, і взагалі в наш час Big Data розкриває нові можливості збирати те, що незрозуміло як використати.

Але є й інші переваги. Kafka може роздавати одній й ті самі повідомлення декільком споживачам — наприклад, сьогодні вони потрібні тільки в базі, а завтра, може, зʼявиться сервіс аналітики.

Також є прості, але можливості обробляти дані всередині Кафки, наприклад, рахувати їх, або обчислювати кінцевий стан сутності по журналу змін - Kafka Streams. Та Kafka Connect - інструмент для завантаження даних з Кафки до звичайної бази даних або ще кудись.

Єдине, що мені не подобається — все воно написане на Java, з усіма особливостями конфігурації та розміщення сервісів на Java.


06.06.2023

Перша засада гарної доповіді — думай про аудиторію

Сьогодні слухав на роботі презентацію про те, як робити презентації. Причому фокус був на робочих дзвінках, які є повсякденністю для нас всіх. Задумався, які поради я можу додати зі свого боку.

На мою думку, головне, про що треба думати при плануванні доповіді (формальному плануванні, чи в голові за пʼять хвилин — це вже як піде) - це аудиторія. Бо предмет робочої доповіді нам зазвичай добре відомий. Але що з нього розказати? Я нерідко бачу, як люди закопуються в деталі, які нікому окрім них не зрозумілі, або навпаки, зазначають, що за два тижні рівно нічого цікавого не відбувалось. Тому, щоб підготувати себе, пропоную пару питань:

З таким фокусом в голові вже можна підходити до предмета доповіді та планувати, на яких аспектах можна зупинитись. А ще зорієнтованість на аудиторії сприяє рапорту більше, ніж правильний кут камери або уникнення слів-паразитів.

Раніше: про логічні ланцюги.