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

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

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

10.08.2024

Dark Souls та кати

🦀 Грав сьогодні в Another Crab’s Treasure - до речі, рекомендую як рідкісно життєрадісний, а все-таки дуже складний соулслайк. Та намагався зрозуміти, в чому ж та складність складається.

🚥 Кожний супротивник у Dark Souls має чітко визначений набір ударів та комбінацій - moveset. Критично важливо (для самої гри), що всякий удар починається з підказки (tell), за яким його можна відрізнити. А всяка дія гравця починається із затримки (замаху, наприклад), та не може бути зупинена.

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

⏲️ Тому найпряміший шлях до подолання наступного випробування у Dark Souls (або Another Crab’s Treasure) - це звернути увагу на рухи та підказки противника та шукати, як з ними “танцювати”. А шлях “в лоб” - тобто бити скоріше та захищатися від ударів — значно складніший та не такий приємний (тому багато людей вважають soulslike занадто складними.)

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


09.08.2024

Дженерики та кодогенерація в Golang

Я люблю генерацію коду як аналог метапрограмування на Go. Навіть більше, ніж метапрограмування як у Ruby, оскільки згенерований код можна переглянути, а не тільки уявити.

Дженерики частково прибрали потребу в кодогенерації: а саме, більше не потрібно генерувати код “з підставлянням типів”. Це чудово та, звісно, в нашому коді є місце дженерикам. (Хоча я поки не брався за впровадження суто функціональних підходів, як, наприклад робить модуль github.com/samber/lo.)

Але все ж навіть з дженериками залишається багато шаблонного коду, який неможливо узагальнити. Уявимо, що у нас є структура Database, в якій 10 різних полів Table[Key, Record]. Всі ці поля доведеться оголосити, ініціалізувати, та виконати різне обслуговування. Щоб не копіювати десять разів однакові рядки для кожної таблиці, нам і допоможе кодогенерація.

Раніше я передавав параметри генератора в рядку //go:generate, але нещодавно знайшов інший підхід. Можна почати з конфігурації у JSON чи TOML, а у генераторі зчитувати ту конфігурацію та генерувати весь код. Наприклад, в конфігурації може бути список таблиць, за яким ми генеруємо і структуру Database, і функцію Database.SaveTables(), і все інше.

Можливості практично необмежені! Але все ж я б радив зводити генерований код до мінімуму, бо код в шаблоні точно важче сприймати та редагувати. Наприклад, замість генерації всієї Database можна згенерувати структуру tables та вбудувати її: type Database struct { tables }. Тоді цей тип можна розширювати без вдавання до шаблону.


08.08.2024

Оптимізація структур даних Go в памʼяті

В продовження вчорашньої ситуації: ділюся декількома знахідками.


07.08.2024

Використання памʼяті в Go

Намагаюся знизити розмір величезної структури даних на Golang. (Назвемо її “базою даних в памʼяті.”) Вона більше не влазить в памʼять, відповідно, є сенс знизити витрати, а не просто палити гроші на неоптимально використані ресурси.

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

До того, всі складені типи займають деяку кількість зайвого місця. Структури містять вирівнювальні байти. Масиви мають резервну місткість. З типом map все взагалі погано, бо його нутрощі нам недоступні, та ми практично не можемо дізнатись, яка в словника резервна місткість. Але вона є: дуже грубо кажучи, Go резервує місце під кількість елементів, кратну ступеням двійки.

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

Пишу маленький аналізатор витрат. Поки що мені вдалося “пояснити” десь 60% тих витрат, що повідомляє ReadMemStats. Чи є 40% надлишком на керування памʼяттю? Хочеться, щоб ні.


06.08.2024

Значки-посилання для статичних сторінок

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

Звідки ті значки беруться? Робити їх власноруч — навіть статичні — трохи занадто. Тому що є готові сервіси — вони здатні не тільки згенерувати значок, а й додати до нього динамічний зміст.

Великих сервісів два. Shields.io - популярний та старий. Badgen - зʼявився як заміна для Shields, але так і не витіснив попередника. Shields.io підтримують більше сервісів та мають кращу документацію. Навіть можна взяти дані з власного JSON API, або навіть сторінки HTML!

Ось, я тільки що зробив значок для цього каналу. Хоч Shields.io не підтримує Telegram, але я можу отримати кількість підписників з вебсторінки каналу, передати її в Dynamic XML, витягнути потрібний блок через XPath, та ще й додати логотип Telegram у вигляді власного SVG (в Shields.io є логотип Телеграму, але надто мілкий.) Чудовий результат без коду та без інфраструктури.

Такий значок мені буде корисний на сайті, бо там така сама проблема, як з GitHub: він статичний. Взагалі хто памʼятає, в епоху Web 1 - тобто до соціальних мереж — вже існувала схожа технологія — інформери. Це теж були картинки, які збиралися на сторонньому сервері. Два типових приклади — це лічильних відвідувачів (коли ж я останній раз такий бачив?) та віджети з погодою (на власному сайті погода? просто метеоцифрова магія!) Єдине, що помінялося тепер: значки генеруються у SVG, а значить, не потребують від сервера більше зусиль, ніж звичайна маленька вебсторінка.


05.08.2024

GTD: успіх?

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

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

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

А коли на канві є плани у всіх необхідних подробицях, то список задач вільний містити тільки справжню наступну дію. З цим успіх перемінний, але я докладаю зусиль. Наприклад, читаю дію “зробити фічу X” та ловлю себе на думці “треба буде перевірити як це зробили в Y”. Значить, або відразу перевірити (та ймовірно записати в канву), або записати це як наступну дію. Такий процес для GTD життєво необхідний, та я радий що він не захламлює список задач (бо в ньому записана тільки безпосередньо наступна дія.)

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


04.08.2024

Homebrew Cask на практиці

Цими днями підʼєднав до Homebrew Cask всі встановлені застосунки, які там є. Вийшло аж 55! Навіщо воно потрібно?

(Homebrew Cask - це додаток до Homebrew, який містить звичайні графічні застосунки. Працює саме так, як уявляєш.)

Як я це бачу, найбільша перевага навіть не в тому, що застосунки легко встановити — бо я щоразу налаштовую новий компʼютер переносом системи та такої потреби навіть не стає. А в тому, як їх легко оновлювати. Homebrew Cask містить скрипти для повністю автоматизованого встановлювання навіть там, де воно зазвичай потребує діалогу — наприклад, для Zoom. Навіть MacUpdater так не вміє. (Хоча його теж рекомендую.) Та й звісно всі застосунки можна оновити однією командою — теж гарно.

В HomeBrew Cask не можна додати застосунки з App Store. Але сьогодні дізнався про утиліту mas для роботи з App Store через командний рядок. Так можна зберегти список застосунків та встановлювати автоматично. Хоча мені навіть більше подобається можливість провести аудит.

А з чим гірше, так це Setapp. За все хвалю цей сервіс, проте автоматизації йому бракує. Поки кожний застосунок доведеться встановлювати вручну. Шкода — за вісім років існування могли б вже щось зробити. Навіть стандартної для macOS автоматизації через AppleScript або Shortcuts немає. (Зате AI помічник є. Пріоритети нашого часу!)


03.08.2024

Емоції та думки

Абсолютно незаплановано рівно рік потому повертаюсь до теми емоцій. Також незаплановано мені сталося послухати дві книги про “поліпшення настрою” з досить схожими назвами: Feeling Good та Letting Go та схожими оцінками на Amazon та Goodreads. Обидві обговорювали емоції та думки. А головний збіг те, що ці дві книги розкривають тему з діаметрально протилежних боків.

Feeling Good ставила тезу: “навʼязливі погані емоції — це наслідок хибних думок.” Всі наші емоції є продуктом автоматичних міркувань. Через аналітичну роботу з думками можна виправити вади міркувань (наприклад, схильність перебільшувати проблеми), а коли негативні думки зникнуть — то з ними й емоції.

А Letting Go, навпаки: “погані думки — це наслідок законсервованих поганих емоцій.” Непрожиті емоції накопичуються та створюють постійне напруження, а з ним — і думки. Людину з законсервованим злом все буде злить. Людина з образою всюди знайде несправедливість. Через усвідомлення та проживання можна позбавитись накопичених емоцій та тоді ті самі обставини будуть викликати більш позитивні міркування.

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


02.08.2024

SMTP vs Email API

Я вже колись писав про те, який SMTP повільний та як там дивно реалізоване шифрування. В цілому, якщо ви надсилаєте пошту через сервіс та він підтримує HTTP API (як Mailtrap), та клієнт теж здатний надсилати по HTTP, то так і треба робити.

Але сьогодні передивлявся питання про наш сервіс з StackOverflow та викрив ще одну, дуже важливу причину надсилати пошту через HTTP API. Порти, через які надсилають пошту, будуть скоріше заблоковані.

Стандартний порт SMTP 25 взагалі блокують майже всюди, бо саме цей порт використовується для отримання пошти, а значить — це єдиний спосіб розсилати спам. Для підключення з клієнтського застосунку на сервіс надсилання пошти використовуються інші порти - 587 та 465. Але і вони дуже часто будуть заблоковані про всяк випадок — хоча надіслати пошту безпосередньо отримувачу за цими портами неможливо.

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

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


01.08.2024

Просунуте використання Dash

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

В простому вигляді раджу призначити Dash до комбінації клавіш; в мене це Hyper+D. Так документація завжди під рукою. Але сьогодні захотів піти далі та інтегрувати Dash у VSCode. Інтеграція знає мовний контекст, тому відразу відкриває сторінку правильної мови. Хотілося, щоб вона також працювала за комбінацією Hyper+D… щоб цього досягти, залучив BetterTouchTool та створив там привʼязку “Hyper+D у VSCode = Ctrl+H” (комбінація пошуку з доповнення.) Так у VSCode активується доповнення, а в будь-якій іншій програмі - Dash напряму.

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

Але ще цікавіше що документацію можна генерувати власноруч. Причому раніше для того було потрібно писати павуків та будувати базу SQLite, то зараз все суттєво спростилося: Dash вміє завантажити цілий сайт, а потім вже підчистити нашим JS/CSS. Нагадало, як на початку 2000-х завантажував всілякі енциклопедії програмою Teleport Pro.