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

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

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

19.08.2025

Пастка великих змін

“От якби все переписати на Go…” “Треба знайти кращу заміну для Jira” “Цю схему даних робили на колінці, треба спроєктувати хорошу, правильну.”

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

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

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

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

Я б радив відразу, як помітиш такий “революційний” хід думок, поставити собі питання - яку конкретно проблему ми намагаємся розвʼязати? Та чи є для неї “маленький” розвʼязок? Зазвичай виявиться - що так. Тільки він не такий блискучий та привабливий.


18.08.2025

Власні атрибути в HTML

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

По-перше, будь-який атрибут повинен починатися з приставки data- Це не просто домовленість, а частина стандарту HTML5. Цікаво, що хто користувався jQuery, той пам’ятає, що data-атрибути використовувалися принаймні за кілька років до виходу стандарту.

В jQuery для них була функція data(), яка спрощувала отримання власних даних, бо всі data-атрибути можна було прочитати однією командою. А на той час вся конфігурація до плагінів робилася саме через розмітку, інколи без жодного рядка власного JavaScript.

Та друге, в HTML немає true та false. Наявність атрибута вважається істиною, відсутність — хибою. Це теж за стандартом. Так що якщо потрібний атрибут, який хибний за замовчуванням — доведеться робити його “негативним”. У нас є гарний приклад зі стандарту - атрибут disabled. Бо enabled="false" було б не за стандартом.

З атрибутами-рядками та атрибутами-числами все традиційніше (ну, хіба що числа все одно мають форму рядків.)

В тому стандарті ще багато цікавого, хоча зазвичай, як я казав наперед, ніхто не заморочується.


17.08.2025

Thief

Згадав вчора про Deus Ex, але мені миліша друга гра того покоління та того ж легендарного розробника Looking Glass Studios.

Це, звісно, Thief. В мене з нею особиста історія. Колись на початку 2000-х потрапив в руки диск, де було ще щось нецікаве та… Thief. Хоч вона й мала погляд від першої особи, але це було щось зовсім особливе. Тут не те що стріляти доводилося нечасто — взагалі, герой дереться не дуже. Та кращий вибір — це завжди ховатися в тінях та тікати від сутичок.

Бо головний герой — грабіжник (із золотим серцем!), та більшу частину гри ти будеш сидіти десь в куті та спостерігати за персонажами. Атмосфера у Thief неперевершена. Від пʼяних охоронців до молитов паладинів, тут ніколи не нудно просто дивитися та слухати розмови. Та й сам герой час від часу відпускає тихі кумедні ремарки. Це все, разом зі здатністю дати здачі, але не дуже ефективно, створює справжній настрій.

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

Є думка, що Thief 2 всім краще за Thief. Візуально та механічно вони майже однакові, зате до Thief 2 команда знайшла свій жанр та гра вийшла більш цілісною. Треба памʼятати, що Thief був першим у своєму роді, та тому містить не тільки маєтки чи тюрми, а й такі рівні, як величезні катакомби та ще більші печери — які були б більше на місці у Tomb Raider. Яка вийшла на два роки пізніше! А для мене ці рівні одні з улюблених. Так що раджу пройти обидві частини. :)

До речі, за керуванням вони цілком сучасні, особливо з патчами. Графіка застаріла, але її естетика збереглася та насторожені охоронці крадуться темними коридорами так само мальовничо. Студії Looking Glass навіть з тими засобами вдалося зробити світ, який відчувається великим без того, щоб виливати на гравця ведра експозиції. Це вічно, як Half-Life (того ж 1998 року!)

Thief 3 та Th4ef (sic) вже не те. Третій зіпсований проклятим поколінням консолей, коли рівні нормального розміру не влазили в памʼять. Ну, принаймні є моди, що склеюють частини рівнів в один великий, тож в нього можна й пограти. А четвертий — це просто зомбі, наповнений сучасними формулами, сумне видовище, якщо грав у попередні.


16.08.2025

Мої перші 5 покупок в Steam.

Інтернетом ходить цікавий тренд — поділитися та прокоментувати перші свої ігри зі Steam. Осьо мої.

Я (як тільки що виявив) зареєструвався в Steam у 2010. З одного боку це прямо не так вже й давно, а з іншого — напевно, десь як раз в ті роки нормалізувалася покупка в інтернеті, бо памʼятаю час, коли це було зовсім дико. Зазначу, що на той час ціни були ще в доларі, а не в гривні (аж до осені 2017.)

  1. Абсолютно не памʼятаю, чому я вирішив першою купити колекцію Fallout (а це 1, 2 та Tactics), та ще й не по розпродажу. Розпродажів тоді було значно менше, фактично літній та зимній. Що ж, я досі так і не пройшов жодний з цих Фолаутів, та й напевно не пройду вже — хоча був би просто щасливий гідному ремастеру. Дуже їх поважаю, але керування та інтерфейс не подужаю.

  2. А от TES GOTY Pack (Morrowind + Oblivion) - це моє рідне, тут ніяк не здивований. Перший раз грав в обидві у перекладі, тож, певно, хотілося придбати мовою оригіналу. (До речі, може й з Fallout така саме історія.) Особливо Morrowind й досі час від часу запускаю — а величезні доповнення від Tamriel Rebuilt виходять частіше, ніж я встигаю їх проходити.

  3. Comix Zone - красивенна гра, в яку грали з другом ще на Sega Genesis десь у 90-х. Мабуть, мені гадалося, що версія зі Steam буде зручніша, ніж така що на емуляторі… але насправді виявилося, що ні. Звичайний невидатний порт. Чесно, досі не бачив офіційних портів кращих за емулятори в RetroArch.

  4. “Сталкер: Чисте Небо” - тобто друга частина Сталкера — знову зрозумілий вибір. (А “Поклик Припʼяті” зʼявився в бібліотеці через пів року.) Щось там його зараз на Стімі критикують, але якщо перший Сталкер подобався, то цей це просто додаткова порція того ж самого, що тут не любити.

  5. Та остання покупка зроблена на моєму першому розпродажі — на честь Різдва 2010. Якщо зайти по посиланню, то як Super Meat Boy, так і Deus Ex Collection (з перших двох ігор) були в топі з величезними знижками. Так що все зрозуміло. Super Meat Boy я так і не пройшов, в мене на то терпіння немає — зате син пройшов… пару років тому. :) А Deus Ex - то золота класика, легендарний саундтрек, унікальна атмосфера та нескінченне джерело мемів.

А у вас що як?


15.08.2025

Портативні монітори (та Mac Mini)

Трилогія про Mac Mini завершується щасливим кінцем. Після минулого поста я взяв та купив найдешевший з адекватних портативний монітор Acer PM161Q 15.6" 1080p. Прийшов, розклався підʼєднав — і все працює! Практично як за ноутбуком… з механічною клавіатурою та мишею. Та вилкою в розетці, звісно.

Що я скажу — сучасні портативні монітори дуже зручні! Для підключення достатньо одного кабелю USB-C. Він і живить монітор, і передає картинку. Є й вхід HDMI, який буде корисний нижче. Монітор має форму кришки від ноутбука, тільки товщої рази у два. Опирається на ніжку-скобу, яку можна виставити під будь-яким кутом. Монітор під нахилом — так, дивно, але ж дивитися на нього доводиться зверху, як на ноутбук, тому насправді все зручно.

Є в нього навіть кріплення VESA, тож можна легко кудись змонтувати. Тобто якщо хочеться, користь від такого монітора можна знайти. Наприклад, дивитися на кухні серіали. Завдяки USB-C монітор легко приймає сигнал й з телефону, лише потрібно в другий розʼєм USB-C включити зарядку.

А ще портативний монітор це дуже зручно, якщо в господарстві багато пристроїв без моніторів. Ну точніше я вас запевняю, тягати сервери до монітора — це точно не зручно. Навіть якщо це Raspberry Pi, то як почнеш шукати на новому місці блок живлення та кабель Ethernet, то краще б вже нікуди не носити.

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

Так що рекомендую — просте та зручне рішення, прямо unix way якийсь.


14.08.2025

GitHub Actions: Docker Compose замість сервісів

Помітив ненароком, що у збірці цілих 2 з половиною хвилини займає запуск сервісів. Це, якщо не стикався, всілякі бази даних та інші залежності, які є просто контейнерами Docker, чого ніхто й не приховує.

Втім, при уважному роздивлянні виявилось, що сервіси запускаються чомусь послідовно. Хоча я звик, що Docker Compose запускає їх паралельно. Про це навіть є запит, який, чомусь мені здається, навряд чи буде виконаний, але то інша тема.

Вихід, відповідно, очевидний — замінити сервіси на Docker Compose. Кумедно, що весь блок конфігурації services буквально копіюється у docker-compose.yml практично без змін. Потім на початку збірки (другим кроком після checkout) запускаємо docker compose up --detach та бачимо запуск вже за 45 секунд. Ось так, майже без зусиль, півтори хвилини заощаджено з кожної збірки.

Різниці у використанні немає — сервіси так само будуть доступні за тими ж портами, які були налаштовані раніше. Хіба що єдиний недолік — журнал контейнерів з сервісами ми просто так не побачимо. Хоча якщо він прямо потрібний, можна ж забрати з Docker без проблем.

Окреме питання — це величезні образи залежностей, які доводиться тягнути, а саме - OpenSearch, який важить майже гігабайт. Та й запускається він повільніше за всіх. Такий він, Web Scale!

PS. Самому хочеться щось вже позбавитись тих Actions разом із GitHub, але ж для роботи він точно ще довго залишиться.


13.08.2025

Єдиний різновид інтеграційних тестів, що працює

Чим більше років пишу тести, тим більше переконуюсь:

Єдиний різновид інтеграційних тестів (для вебу), що дійсно виконує свою задачу — це тест, що сумлінно відтворює дії користувача.

Це значить: взаємодіє тільки з тими елементами, які бачить користувач. Перевіряє тільки їхній текстовий зміст. В крайньому разі — також заглядає в стан бекенду, але тільки після перевірки відповідного стану на сторінці.

Якщо не виходить писати такий тест, варто змінювати інтерфейс, а не тести. Бо це пряма вказівка на те, що й користувачу буде незрозуміло. Особливо незрячому користувачу. Завжди можна додати до елементу текстовий атрибут ARIA, який зовсім не зіпсує ваш дизайн.

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

Звісно, також потрібний тестовий інструмент, який підтримує такий підхід без зайвих дій. Наприклад, Playwright. В нього не тільки чудовий широкий API. Він ще завжди ставиться до сторінки так, як це б робив користувач: перед тим, як натиснути на кнопку, прокручує сторінку, перевіряє, що кнопка дійсно видима тощо.

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


12.08.2025

Бюджет на рішення (так, я про гроші)

Давайте про дуже важливе питання, яке я особисто довгу частину своєї карʼєри не розумів.

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

Дуже довгий час я дивився на це однобоко: Я — програміст, моя задача — розвʼязувати задачі кодом. А робити фінансові рішення я не уповноважений. Так, є оцей сервіс за 10 доларів на місяць, от якби був безплатний, могли б долучити. А так і самі щось напишемо.

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

Так, заперечиш ти, але ж я напишу своє одноразово, а підписка — це назавжди? Не буває ніяких “одноразово”, кожне рішення потребує підтримки. Коли ти платиш за підписку, хтось інший буде оновлювати там базу, закривати діри безпеки, та й просто стежити за тим, щоб сервіс не падав та витримував навантаження. Забувати про це — величезна хиба планування. Ба більше, в нас є умовно нескінченний ресурс підписок, але дуже скінченний ресурс часу на підтримку власних рішень. Що більше ваш власний продукт буде обростати такими саморобочками, то далі буде ускладнюватися розвиток.

Дотичне питання - менталітет програміста проти інженера. Та бажання “зробити все точно так, як нам треба” або “не брати зайвого”. Звісно, якщо чуже рішення вже існує та його нескладно інтегрувати, то робити своє — це й буде зайве.

Все це ще більше стосується власних проєктів, де ніхто тобі не платить. Бо там ще менше часу! Чи хочеш ти витрачати цей час на розробку корисних можливостей, або на налаштування нотаризації під macOS?


11.08.2025

Нотаризація програм під macOS (наче все працює)

Після минулих невдач з підписами під macOS нарешті, як мені здається, остаточно все виправив. Принаймні вона запускається не тільки на тому компʼютері, де я її будував.

(Зізнання: минулого разу за браком часу я намагався навайбкодити рішення — тобто питав у агента розвʼязок, та не роздивлявся в те, що відбувається. Не вийшло, та й часу пішло чимало. Урок.)

Для випуску програми я беру GoReleaser. Ця утиліта поєднує всі кроки — від збірки до створення версії на GitHub та відвантаження архівів. Але підписувати вона… вміє з недавніх пір, втім, тільки в версії за підпискою — на яку мій масштаб поки не заслуговує.

В GoReleaser є підтримка підписів, теоретично (секція signs), але ці підписи мають конкретну реалізацію (GPG тощо) та ніяк навчити того, що нам потрібно, не вийде. Тому дивимося далі.

Варто тут зʼясувати, чого ж від нас хоче Apple. Тут автентифікація складається з трьох частин. Спочатку підпис сертифікатом розробника (sign) - так само як і GPG - це криптографічний підпис, який каже, що програму скомпілював не аби хто, а я. Далі нотаризація (notarize) - а це вже особливий для Apple крок, коли ти надсилаєш програму на їхній сервіс, вони її перевіряють та реєструють в базі даних. Так, в Apple є центральна БД всіх перевірених двійкових файлів! Нарешті, коли користувач запускає застосунок перший раз, ОС перевіряє його в цій базі — що потребує підключення. Цього можна уникнути, якщо завантажити та прикріпити квиток нотаризації (staple) до пакета.

Перші два кроки на 2025 рік є практично обовʼязковими, бо без них програма в користувача не запуститься без спеціальних дій. Та так, пакети з Homebrew та інші серйозні застосунки так і роблять. (Або інший вихід — збирати двійковий файл локально.) Прикріплення теж варто робити, але то потребує пакування в епловський формат - .dmg, .pkg чи принаймні .app. Я б і не проти, але безплатний GoReleaser їх не робить.

А GoReleaser радить утиліту gon. Вона вміє і підписувати, і пакувати, і нотаризувати, і прикріпляти. Але ж мені потрібно все це робити в контексті GoReleaser, щоб поєднати зі збірками на інші платформи та відвантажити. Отже, поки задовольнився тільки підписом та нотаризацією самого двійкового файлу, після чого його забирає GoReleaser.

Весь процес збірки диригується GoReleaserом. На збірки для macOS в нього поставлений постхук. Хук викликається після компіляції, генерує конфігурацію Gon, робить всю магію, в тому числі пакує в ZIP, надсилає на нотаризацію, а потім розпаковує та вертає підписаний файл назад на місце.

З усього цього, певно, найскладнішим було те, що хуки GoReleaser запускаються без оболонки! А значить, в них не працює перенаправлення виходу, умовне виконання та інші оболонкові функції. Коли збагнув, що треба все завертати в sh -c, справи пішли.

(PS: сиджу і думаю - чи варті були всі ці зусилля, щоб заощадити 11 доларів на місяць на GoReleaser Pro?)


10.08.2025

Какао

Гадаю, що какао ще менше розкритий в наших кавʼярнях, ніж чай. Чай принаймні можна знайти й сортовий, і заварений гарно, а то ще й проливний. А какао майже завжди обмежується чимсь молочним та дуже солодким. Я вам скажу, в ацтеків того молока зовсім не було, як і апаратури для знежирення какао-маси (що потрібно щоб отримати какао-порошок.)

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

Проте якщо копнути глибше, то какао-порошок — то вже субпродукт. Можна робити какао як його робили ацтеки — з какао-маси. Какао-маса — це 100% подрібнені какао-боби. При кімнатній температурі виглядає як плитка шоколаду — втім, навіть 100% шоколад зазвичай робиться з порошку та масла, бо це простіше. А тут маємо сирий продукт. Гарна какао-маса має значно цікавіший смак, зокрема тому, що робиться з какао одного сорту — аналогічно з кавою. Така зазвичай називається “церемоніальний какао”.

Якщо шукати недалеко, то є польський Chocante, а якщо глобально та гарно — то Cacao Laboratory. В Україні какао-маси я поки не знайшов, але як хочете просто неперевершену плитку, то раджу полтавський Stranger, моя улюблена — це Танзанія.

Какао-маса збивається з гарячою водою блендером, в співвідношенні десь 10:1. Отримуємо напій, який нагадує еспресо за насиченістю та характером, але на відміну від нього жирний. (Ясно, що масло не плаває на поверхні, а створює емульсію.) Тож, мабуть, скоріше bulletproof еспресо, якщо чули про таке. Для мене це єдиний гарячий напій, який може змагатися з кавою.

Є ще інший підхід — заварювати обсмажені шматочки бобів та шкаралупи. Тобто робити як з кавою — наприклад, у френч-пресі. (Тільки не молоти. Молоти какао — взагалі погана ідея!) Виходить щось середнє між кавою та чаєм, але тут вже буде шар масла нагорі. Смак від кислого до гіркого чи навіть паленого, залежно від сорту та обсмажки. Я таку каву-какаву знаходив у Chocolate Alchemy, там взагалі асортимент гарний. Але цей напій вже на любителя.

Мене ця тема зацікавила, щоб перейти з кави. На кілька місяців вистачило. Тільки різниця як раз в тому, що такий какао нема де пити. Втім, передрікаю, що через років десять такі напої з какао будуть не менш поширені, ніж матча — її теж років 15 тому треба було замовляти десь з Китаю.