Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
23.11.2022
Гаджети, що допомагають за відсутністю світла
💡🔌⚡ Саме цікаве за сьогодні це те, що нарешті цілий вечір немає світла. Тож розкажу, які гаджети допомагають з цим поратись.
-
Налобна лампа (Petzl Tikkina 2) на трьох батарейках AAA. Найнижча яскравість тримає 16 годин. Зазвичай в моїх лампах стоять акумулятори (Panasonic Eneloop). Але якщо немає, то батарейки нескладно здобути та зберігати. Налобна лампа — то найзручніший ліхтарик для активностей, бо підсвічує там, де дивишся, і не займає рук.
-
Ліхтарик Brennenstuhl PL 200 A - довго шукав такий “неформатний” ліхтарик, і нарешті випадково побачив у колеги. Завдяки формфактору його пристебнути до одягу чи до рюкзака — це я й шукав — але також за магніт можна повісити на різноманітні поверхні. Світить дуже яскраво.
-
Павербанк на 20000 мАч (від Baseus). До того всі мої павербанки були близько 5000 мАч, бо такі легше носити. Але ж маленький павербанк є “одноразовим”, потім треба заряджати. Двадцять тисяч — це зовсім інший рівень свободи. Їм можна користатись багато годин, не обмежуючи себе. Але ж заряджається він також кілька годин, навіть на найміцнішій зарядці у 18W.
-
Лампа від USB (в мене від Xiaomi, але їх безліч). Вона працює від того самого павербанка і світитиме за моїми підрахунками десь 30 годин. Це на найвищій яскравості, коли вона майже замінює нормальне освітлення.
-
USB-роутер з 4G та Wi-Fi, що я покупав для машини, але тепер його можна вставити в той самий павербанк та мати мобільний інтернет для всієї родини з набагато меншими витратами енергії, ніж якщо роздавати з телефона.
-
Макбук M2 Air. :) Останнє, про що доводиться перейматись — це чи вистачить батареї для роботи.
-
А щоб ноутбук працював довше, раджу софт - AppTamer, щоб обмежити активність додатків при роботі від батареї та TripMode, щоб так само обмежити використання мобільного інтернету. Обидва доступні з Setapp.
22.11.2022
Наше ставлення до ситуації обирати нам
Сьогодні з сином годину шукали по крамницях конкретний різновид мівіни. В найближчому “АТБ” такого не виявилось. Оскільки це було ввечері, то крамниці — як виявилось — були закриті. Тож, повернувшись до “АТБ”, та постоявши в черзі пізніх покупців, отримали ту саму мівіну, що могли б забрати відразу і без черги.
(До речі, чи знаєте ви, що саме “Мівіна” - власний український бренд миттєвої локшини? Принаймні, був, поки його не купив Nestle. Тому, всю миттєву локшину я наполегливо називаю мівіною, а ніяк не ролтоном чи дошираком.)
Урок, запропонований сином — варто йти на компроміси, замість пошуку ідеального рішення. Що ж, це так. Особливо цінно, що цей висновок був не навʼязаний.
Але, як на мене, то можна подивитись на ситуацію інакше. Прогулянка — сама по собі задоволення. Ще й разом. Ще й зараз, коли вулиці такі темні, що місто стає сюрреалістичним, лімінальним вже о восьмій годині вечора.
Чи було це безцільне бродіння в темряві, або чудова вечірня прогулянка? Вирішувати нам.
21.11.2022
Просте та дешеве кешування для скриптів зі збереганням на AWS S3
💭🗃️🧠 В генераторі стрічок я використовую цікавий підхід до кешу. А саме, як кеш я використовую звичайний файл на S3.
Кеш потрібен здебільшого для того, щоб не завантажувати одну й ту саму сторінку два рази. Бо коли для кожного поста в стрічці треба робити окремий запит, повторювати ці запити дуже не хочеться.
Колись цей генератор був звичайним вебдодатком на Sinatra. Тоді для кешу в мене був Memcached. (Так, це було дуже давно.) Але потім мені набридло витрачати гроші на хостинг додатка на Ruby, і я переробив генератор на AWS Lambda, яка запускається раз на добу, а результат зберігає на статичний хостинг S3. Таке рішення виходить повністю безплатним.
Залишилось тільки питання — що робити з Memcached? Очевидна відповідь — сервер AWS ElastiCache - коштує гроші. Та до того ж нераціонально тримати цілий сервер для декількох хвилин на добу. Тоді я і придумав рішення з S3.
Найпростіша база даних — то завжди є простий файл. В цьому випадку, файл у форматі JSON, що містить ключі кешу та значення. Окрім самих значень, я також зберігаю термін придатності — так кеш не буде зростати нескінченно.
Перед запуском скрипту я завантажую кеш та видаляю значення, для яких вибіг термін, а по закінченню — зберігаю назад на S3. Тут можна подивитись код.
Можу уявити й складніші рішення на такому самому підході — наприклад, можна було зберігати повноцінну базу SQLite.
20.11.2022
Покращення повнотекстової стрічки Hacker News
📰🖼️🧼 Вчора я тільки здув пил зі свого генератора стрічки; сьогодні доробив справжню красоту.
В більшості спирався на чудовий гем metainspector. Він вміє знайти на будь-якій сторінці метаінформацію - заголовок, опис, ілюстрацію. Причому знайти різними способами - наприклад, опис може взяти і з стандартної розмітки, і з розмітки OpenGraph, і просто з першого параграфу сторінки. Завдяки цьому гему вдалося збагатити стрічку базовою інформацією про публікацію, щоб легше було зрозуміти, чи цікава вона.
Також зі сторінки коментарів зробив витяжку трьох топових коментарів - також щоб відразу зрозуміти, чи цікава була дискусія. Власне, тепер моя стрічка більш зручна, ніж сам Hacker News, оскільки дозволяє на одному екрані побачити як підсумок публікації, так і коментарів до неї!
До рядка з базовою інформацією (оцінка / кількість коментарів / адреса / автор) додав позначки-емодзі. Так легше сканувати цю інформацію. Насправді, був здивований, наскільки легше.
Нарешті, збільшив кількість постів на добу до 60 - тобто двох перших сторінок головної. Так виходить 420 постів на тиждень - розумна кількість.
19.11.2022
Покращення для моєї RSS-стрічки для Hacker News
🎨🗞️☕ Нарешті покращив 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
Cкладнощі з тестуванням БД на Go
🐹🗄️😭 Поскаржуся на складнощі з тестуванням БД на 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.
17.11.2022
Система пошуку в інтернеті Kagi - мій новий пошукач
🔍🦮🎩 Сьогодні несподівано поміняв свій підхід до пошуку в інтернеті.
Я вже багато років вживав як базовий пошук DuckDuckGo. Для мене головна його перевага — це так звані bang-команди, що дозволяють відразу делегувати пошук на інший сайт — наприклад, !g foo шукатиме в Google, а !yt bar - на YouTube. Сам по собі пошук у DuckDuckGo кепський, бо власного індексу він не має, а шукає через Bing. (Тому мого блогу в DDG не знайти.) Але, можливість легко перестрибнути в більш доцільний пошукач мене полонила.
Але. Колега порадив пошукач “нового покоління” Kagi. За який треба платити $10 на місяць. Що ж такого він пропонує за ці гроші? Вочевидь, гроші за підписку — гарантія (або обіцянка) того, що пошукач не торгуватиме твоїми даними. (А ще спробувати до 50 запитів можна без оплати.)
Крім того, сподобалась можливість налаштувати пошук під себе — вийняти сайти, що не подобаються, або навпаки, підняти деякі догори. Та й сам по собі пошук добре працює. Хоча Kagi також веб не індексують, а делегують запити різним системам, в тому числі й Google. (Так що тут мій блог знайдеться.) На перший погляд здається, що низькоякісні статті Kagi ховає, але тут ще подивимось.
Як щодо bang-команд, то Kagi їх підтримує. Але я вирішив піти ще далі, та знайти локальну заміну. Бо як DDG, так і Kagi перенаправляють bang-команду зі свого сервера, а локальна утиліта піде напряму. Так я знайшов доповнення для Safari xSearch - це буквально те що треба. Працюватиме xSearch і на айфоні.
Тут є проблема — в Safari не можна додати власний пошукач. Тому як Kagi, так і xSearch вдаються до хаків, перехоплюючи запити до стандартно обраного в Safari пошукача. Це працює непогано, але не дуже акуратно.
Отже, я вирішив піти до кінця та залучити додаток, що в мене вже є - Alfred. Єдине що, треба перевчитись писати пошукові запити туди, а не в браузер.
16.11.2022
Obsidian, погана синхронізація через iCloud Drive, та хороша через Obsidian Sync
🪨☁️🔄 Obsidian розчарував з синхронізацією через iCloud Drive, але з цього можна винести гарний урок.
Головна проблема в тому, що на iPhone файли з iCloud завантажуються помітно повільніше, ніж локальні файли. Через це уповільнюється пошук по файлах — а це найважливіша в мобільній версії функція. Якщо ж немає надійного підключення, то все стає ще гірше, бо наявність локальної копії файлів з iCloud Drive не можна гарантувати.
Одним словом, для синхронізації iCloud Drive погано підходить. Як хмарне сховище для файлів — добре, але якщо потрібна швидкодія — ні.
Тому довелось заплатити гроші та перейти на Obsidian Sync - їхній власний сервіс. Має end-to-end шифрування, тобто на сервері нотатки прочитати неможливо. Нотатки, що синхронізуються з Obsidian Sync, розташовуються у звичайній локальній директорії, та ніякої неоднозначності з їх наявністю немає. Як на телефоні, так і на компʼютері пошук працює швидше.
До речі, поставив собі питання, як це Bear, яким я користався раніше, не має такої проблеми, хоч і синхронізується через iCloud. Виявляється, що тут синхронізація побудована на хмарній базі даних CloudKit, а не на iCloud Drive. Тобто якщо будувати свій додаток з синхронізацією, то теж краще дивитись в бік CloudKit. Проте, в Bear нотатки не мали вигляд звичайних файлів — довелося обирати або одне, або інше.
15.11.2022
Як підтримувати швидкодію додатків на React
⚛️🚅📝 Зачепив сьогодні тему того, як підтримувати швидкодію додатків, написаних на React.
На мою думку, тут є простий максим: швидкодія забезпечується тим, що якнайменша кількість компонент перемальовується якнайрідше. І також треба розуміти: сам React нічого не робить, щоб обмежити перемальовування вкладених компонент.
Отже, висновок: чим частіше оновлюється той чи інший стан, тим глибше у дереві компонент він має зберігатись. Для більшості станів та дій це цілком не важливо - пишіть так, як зручно. Виправляти треба тоді, коли уповільнення стає помітним. За моїм досвідом, найбільш це критично для вводу з клавіатури: саме тут варто прикладати мемоїзацію як значень, так і компонент.
Мемоїзація взагалі не безплатна, як по швидкості, так і по розумінню, тому я уникаю мемоїзації без приводу. Наприклад: мемоїзацію ламають обʼєкти та масиви, утворені літералами — будь-який літерал створюватиме новий обʼєкт при кожному виконанні, а мемоїзація працює тільки, якщо аргументи не змінюються. Якщо мемоїзації немає, то й проблеми це не ставить. Що добре, тому що літерали у коді скрізь.
Redux вносить другий вимір у рівняння швидкодії. Кожний з селекторів — тобто функцій, які використовуються в хуці useSelector - буде виконаний при кожній зміні стану. Щоб уникнути проблем, варто не привʼязувати селектори до компонент, що можуть повторюватись багато разів.
14.11.2022
Перетворення коду за допомогою синтаксичного дерева AST
🔠✂️🌳 Хочу детальніше розповісти про механізми, що дозволяють, наприклад, написати перетворювач Markdown на HTML для Телеграму, не розбираючись при цьому з синтаксисом Markdown.
Центральним поняттям тут є синтаксичне дерево, AST. Це структура даних, що відтворює зміст вхідного коду. Практично всі сучасні інструменти роботи з кодом починають з того, щоб побудувати це синтаксичне дерево.
Що конкретно являє собою AST - залежить від реалізації. Це деяка деревовидна структура обʼєктів. Зазвичай треба ще зрозуміти, як з ним працювати. Але це свідомо простіше, ніж парсити код.
Саме так працює Goldmark - парсер Markdown для Go. Окрім того, щоб писати власний рендерер, можна було також написати трансформацію дерева, а потім передати звичайному рендереру. Так, наприклад, можна додати особливу розмітку, чи навпаки, обмежити її.
Де це ще може бути корисним? Наприклад, якщо захочеш написати свої правила для ESLint - там теж є своє AST. Та й якщо будеш писати свій парсер, будь то з чистого аркуша, або краще, на основі спеціальних бібліотек — то на виході теж отримаєш дерево.
А найбільш відоме всім нам синтаксичне дерево — це, напевно, дерево HTML, тобто DOM.
Окрему категорію ставлять Ліспи — в них вхідний код та його синтаксичне дерево мають буквально один й той самий вигляд. Тому на ліспах просто писати потужні макроси: вмієш працювати зі списками — готовий перетворювати код.

