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

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

Підписатись на RSS · 📢 Канал в Telegram @stendap_sogodni

27.11.2022

В мене складні відносини з плануванням. З одного боку, методологія Getting Things Done перегорнула мені життя, і я досі вважаю її ґрунтовною для впорядковування власного життя. З іншого боку, це було років 15 тому, і за весь цей час GTD в мене так і не прижилась.

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

Можливо, що буддизм має правильну відповідь. А саме: хапатись і намагатись керувати життям — то є дукха; натомість треба пливти за течією. Власне, останні роки я нічого не планую детально, а просто намагаюсь робити крок за кроком до мети. Таке собі “планування методом A*”. Це не завдяки буддизму, а через втрату довіри до систем організації.

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


26.11.2022

⭐🤩💫 Фух, нарешті розставив зірочки першим репозиторіям, якими користуюсь.

Як же ж поставити зірку автоматично, скриптом? Для цього довелось поринути у GitHub API та його документацію. Сам API оманливо простий, ось метод, що нам потрібен.

Але — як авторизувати його? Спочатку я хотів зробити це з Personal Access Token, які можна створити вручну через вебінтерфейс. (До речі, ця можливість дуже прихована. Ось пряме посилання, якщо не хочете пройти квест.) А ще нещодавно зʼявились так звані “fine-grained tokens”, якими можна обмежити доступ токена. Я думав, що то ідеальне рішення.

Тільки воно не працює. Виклик “зіркового” API з персональним токеном заборонений. Це удвічі дивно, бо для fine-grained tokens можна обрати й доступ на запис до зірок. 🤷

Тобто (принаймні на сьогодні) для цього API треба робити OAuth2. Це легко, але не зі скрипту. Зазвичай авторизація OAuth в скриптах вимагала від кожного користувача створення власної аплікації з власними ключами — бо нормальний OAuth вимагає серверної частини для зберігання секретів, а в скрипті я б робив “фейковий” сервер.

Тому я був дуже радий дізнатись, що GitHub має особливий режим авторизації для скриптів - Device flow. У цьому режимі, фактично, GitHub сам виступає серверною частиною, а скрипт містить тільки несекретний ID аплікації, а отримує готовий access token.

…Додатково сьогодні встановив на компʼютер з Windows ще і Ubuntu (бо потрібен “залізний” Linux для деяких операцій). Ця процедура стала набагато простіше, ніж останнього разу (багато років тому.) Єдине, що для встановлення на систему з UEFI треба було створити флешку програмою Rufus.


25.11.2022

💎☕🐹 Закінчив зі збором залежностей для всіх трьох моїх головних мов - Ruby, JavaScript, Golang. Виявилось, що для Ruby було складніше за все.

В JavaScript залежності перелічені в файлі package.json, який як звичайний JSON легко прочитати. Далі є API npm.js https://api.npms.io/v2/package/:packagename, звідки дізнаємось домашню адресу пакета. (До речі, і цей API, і API RubyGems відкриті, бо всі їми користуються кожного разу, як встановлюють пакети.)

В Go залежності містяться в файлі go.mod. (Принаймні, в сучасному Go, бо раніше було декілька альтернатив, а зараз все стабілізувалось.) Файл go.mod нестандартного формату, але не складніше, ніж Gemfile.lock. До того ж оскільки в Go назва пакета — це адреса його репозиторію, то ці адреси ми дізнаємось безпосередньо.

Залишилось трохи причепурити та можна випускати у світ.

Весь скрипт написаний на Ruby, бо взагалі такі аналітичні штуки мати приємний вигляд саме цією мовою. Але, скажете ви, а як же ж купа запитів до API? Хіба не краще було їх паралелізувати, як то пропонує підручник по Go? А на Ruby паралелізувати операції, що блокують можна не гірше, практично в один рядок. Це тільки якщо у вас складні обчислення, то Ruby погано підходить, бо він фактично однопроцесорний.


24.11.2022

😺⭐💎 Через відсутність світла робота не дуже йде. Почав як вправу маленький проєкт, який давно крутився в голові: GitHub Autostar

В чому суть. Всі ми любимо оцінювати проєкти на GitHub за кількістю зірок. Але ж хто ті зірки ставить? Я сам нечасто про це згадую. Тож виходить дивна асиметрична оцінка.

Щоб виправити цю ситуацію, я хочу зробити скрипт, який знаходить в моїх проєктах всі прямі залежності, що є на GitHub, та автоматично проставляє їм зірочки. Це можуть бути Ruby-геми, пакети NPM, модулі Go тощо. Навіть закладки чи нотатки. Так без зайвої ручної праці можна спрямити несправедливість оцінок.

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

Тому схилився до статичного аналізу. Перша ідея: розбирати Gemfile. Але ж гемфайл — це фактично скрипт на Ruby, та хоч в гемфайлах зазвичай дотримуються визначеного формату, очікувати можна на все. Втім, знайти регулярками рядки вигляду gem "foo" досить просто.

Але потім нарешті роздивився структуру Gemfile.lock і знайшов там розділ, де перелічені прямі залежності проєкту (а саме, DEPENDENCIES.) Цей формат файлів створений для машинної обробки та — хоч він і не стандартний — прочитати його набагато легше, ніж Gemfile. Як результат, в робочих проєктах першим способом знайшлось 146 гемів, а другим - 150.

Після цього залишається звернутись до відкритого API RubyGems - https://rubygems.org/api/v1/gems/#{gem}.json та дізнатись домашню адресу кожного гему. А потім, перевірити, чи спрямована вона на GitHub.

Так отримав 128 репозиторіїв, що, порівняно зі 114 зірочками, що я поставив вручну за довгі роки користування Гітхабом, вже досить багато.

Наступні кроки — реалізація для інших мов, та пошук простого рішення для масової роздачі зірок.


23.11.2022

💡🔌⚡ Саме цікаве за сьогодні це те, що нарешті цілий вечір немає світла. Тож розкажу, які гаджети допомагають з цим поратись.


22.11.2022

Сьогодні з сином годину шукали по крамницях конкретний різновид мівіни. В найближчому “АТБ” такого не виявилось. Оскільки це було ввечері, то крамниці — як виявилось — були закриті. Тож, повернувшись до “АТБ”, та постоявши в черзі пізніх покупців, отримали ту саму мівіну, що могли б забрати відразу і без черги.

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

Урок, запропонований сином — варто йти на компроміси, замість пошуку ідеального рішення. Що ж, це так. Особливо цінно, що цей висновок був не навʼязаний.

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

Чи було це безцільне бродіння в темряві, або чудова вечірня прогулянка? Вирішувати нам.


21.11.2022

💭🗃️🧠 В генераторі стрічок я використовую цікавий підхід до кешу. А саме, як кеш я використовую звичайний файл на S3.

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

Колись цей генератор був звичайним вебдодатком на Sinatra. Тоді для кешу в мене був Memcached. (Так, це було дуже давно.) Але потім мені набридло витрачати гроші на хостинг додатка на Ruby, і я переробив генератор на AWS Lambda, яка запускається раз на добу, а результат зберігає на статичний хостинг S3. Таке рішення виходить повністю безплатним.

Залишилось тільки питання — що робити з Memcached? Очевидна відповідь — сервер AWS ElastiCache - коштує гроші. Та до того ж нераціонально тримати цілий сервер для декількох хвилин на добу. Тоді я і придумав рішення з S3.

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

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

Можу уявити й складніші рішення на такому самому підході — наприклад, можна було зберігати повноцінну базу SQLite.


20.11.2022

📰🖼️🧼 Вчора я тільки здув пил зі свого генератора стрічки; сьогодні доробив справжню красоту.

В більшості спирався на чудовий гем metainspector. Він вміє знайти на будь-якій сторінці метаінформацію - заголовок, опис, ілюстрацію. Причому знайти різними способами - наприклад, опис може взяти і з стандартної розмітки, і з розмітки OpenGraph, і просто з першого параграфу сторінки. Завдяки цьому гему вдалося збагатити стрічку базовою інформацією про публікацію, щоб легше було зрозуміти, чи цікава вона.

Також зі сторінки коментарів зробив витяжку трьох топових коментарів - також щоб відразу зрозуміти, чи цікава була дискусія. Власне, тепер моя стрічка більш зручна, ніж сам Hacker News, оскільки дозволяє на одному екрані побачити як підсумок публікації, так і коментарів до неї!

До рядка з базовою інформацією (оцінка / кількість коментарів / адреса / автор) додав позначки-емодзі. Так легше сканувати цю інформацію. Насправді, був здивований, наскільки легше.

Нарешті, збільшив кількість постів на добу до 60 - тобто двох перших сторінок головної. Так виходить 420 постів на тиждень - розумна кількість.


19.11.2022

🎨🗞️☕ Нарешті покращив RSS-cтрічку для Hacker News. Це один з найкращих ресурсів для айтішних новин та цікавих проєктів. Але його інтерфейс не підходить для читання раз на тиждень. Ще є багато альтернативних клієнтів для HN, з яких можу порадити hckr news, але ж мені потрібна RSS, і не просто RSS, а зручна.

Поки що стрічка просто містить топові пости з головної сторінки за минулий день. Далі мій RSS-агрегатор буде збирати пости за кожен день в загальну стрічку. Чому пости за минулий день? Тому, що топові пости можна обирати тільки з тих, що вже проіснували достатньо, щоб бути побаченими.

Стрічка доступна за адресою: RSS. Вона розміщена на AWS S3 і не має правильного сертифіката — тому http. Також, стрічка оновлюється скриптом раз на добу, тому її хостинг коштує умовно нічого (Тільки, будь ласка, не зловживайте.)

Друге покращення — вирішив, що тексти (Markdown) не обовʼязково писати у моноширинному шрифті, та поміняв шрифт на Helvetica. Власне, я вже багато років час від часу експериментую з пропорційними шрифтами. Та й зараз мій головний шрифт для коду — пропорційний Input Sans. У родині Input є, звісно, і моноширинний шрифт. Я вживаю його для мов, де вирівнювання рядків має значення — наприклад, для Go. У VS Code взагалі можна поміняти шрифт окремо для будь-якого формату файлів. (Чого не можна зробити — це поміняти родину шрифту для окремого типу символів, наприклад, коментарів.)

Додатково зробив так, щоб у Markdown була обмежена довжина рядка. Теж зручно для редагування текстів.


18.11.2022

🐹🗄️😭 Поскаржуся на складнощі з тестуванням БД на Go.

Попередження: мені ще не доводилося використати жодну з повноцінних ORM для Go. Причина в тому, що в мене завжди десь поруч Rails, а у Rails чудовий інструментарій для міграцій і такого іншого. Тож на долю Go залишається тільки обмежена кількість запитів. Тож записуємо їх явно, у вигляді SQL, а запускаємо за допомогою database/sql. Але ж їх теж треба тестувати.

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

Спочатку треба відтворити структуру бази для тестів. Якщо є Rails, то це просто — беремо базу від Rails. Також для CI копіюємо database_structure.sql з Rails в репозиторій з Go, і завантажуємо перед тестами. Теж нескладно (тільки доводиться вручну підтримувати в актуальному стані.)

А далі — складна частина. Як наповнити тестову базу даними? В Go немає загально прийнятного аналогу factory_bot - принаймні, такого, що можна вжити без ORM.

Раніше я наповнював базу довжелезними SQL-скриптами - на кшталт TRUNCATE ...; INSERT .... Їх жахливо читати та змінювати. До того ж в скрипті незрозуміло, де важливі значення, а де — необхідне наповнення обовʼязкових стовпчиків. Втім, саме такий підхід я вживав багато років на декількох проєктах — бо принаймні він технічно простий.

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

Бібліотека testfixtures дозволяє описати таблиці у вигляді YAML. В цих файлах YAML можна навіть використати шаблони, та передавати значення з коду Go. Тобто замість непрозорих, магічних значень тепер в тестах можна посилатись на ті ж самі змінні, що будуть записані в базу. Чого не вистачає — автоматичного наповнювання обовʼязкових стовпчиків.

Так поки й живемо. А ще налаштування бази зручно робити з testify/suite.