Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
19.06.2025
Мій літопис операційних систем
…Як всі нормальні українці, я починав з Windows. Першою ОС, над якою я відчував хоч якусь власність, була Windows 98, серійник від якої багато хто памʼятає напамʼять. Саме на Windows я навчився програмувати, та заробляти перші справжні гроші. Та Windows давав широкий лан для творчості — ігри, графіка, системні утиліти всякі, та, звісно, вебпрограмування, на якому я й побудував карʼєру. Славетний стек AMP (Apache, MySQL, PHP) чудово почував себе на Windows, та що цікаво, я навіть не думав про командний рядок. Все робилося через графічний інтерфейс, від операцій з файлами до роботи з базою чи конфігурацією вебсервера. PHP навіть розгортувати можна було через графічні файлові менеджери, та майже не піклуватися, що на сервері інша ОС.
Linux на десктопі для мене почався з Ubuntu 7.10, її треба було замовляти на компакт-диску, бо завантажити було нереально довго. Та, якщо так лічити, то десь чотири роки я з ним боровся; спочатку по-звичайному. Ніколи в мене не було все гаразд з драйверами, особливо на ноутбуках. Потім винайшов для себе віртуалізоване рішення та ще якийсь час використовував з-під Windows. Зараз не можу згадати, але здається, почав Linux просто через моду. Хоча, звісно, це принесло переваги: зокрема, можна було локально запустити nginx, або розробляти багатопроцесові програми в такому ж середовищі, як на сервері. Ну й все, що з Ruby повʼязано, краще працювало в *nix.
Та, нарешті, у 2011 я купив перший макбук (який, до речі, досі живий), та відтоді робоча ОС в мене macOS. Макбуки були надзвичайно популярні у рубістів. (Я ще пригадую в Railsware десь у 2010 була сторінка компанії, де прямо й було написано “ми любимо наші маки”.) Пропозиція macOS проста: це серйозний Unix для користувачів. З одного боку — все майже так, як на сервері — від файлової системи та моделі процесів до конкретних програм та програмних комплексів. А з іншого - macOS - це справжній ОГ графічних інтерфейсів, та культура якісних застосунків тут зародилася та досі залишається найсильнішою. Та до того — ніколи ніяких проблем з драйверами (поки не почнеш підʼєднувати щось рідкісне.) Та найкраща на десктопі модель безпеки.
За ці роки багато всього змінилося. Зокрема, зʼявився Docker, завдяки якому тепер легше мати на десктопі оточення, ще ближче до сервера. На Windows тепер є офіційний віртуалізований Linux. Багато продуктів переїхало в браузер (чи Electron), тим самим зрівняв поведінку всіх трьох систем. Але щоб я думав змінювати робочу ОС? Та ні в якому разі.
18.06.2025
Як я прийшов до Git
Якщо чесно, то сьогодні аж ніяк не було часу на хоч щось робоче (на Піп Іван довго ходити), тому натомість займуся археологією та згадаю, як переходили на Git.
Розкопав в історії, що я перейшов на Git 16 років тому — у 2009. Вмотивовано було це роботою. Найбільш дивне для мене те, що на GitHub я зареєструвався лише через місяць — значить, у нас був власний сервер Git? Оце так хотілося?
(Насправді, GitHub тільки років з сім тому дозволив безплатні приватні репозиторії. Я памʼятаю, бо один наш проєкт завдяки цьому переїхав з GitLab. Тому, ймовірно, у 2009 GitHub не входив у бюджет.)
До Git в мене був Subversion. Головне, чим він запамʼятався — гілка була копією всіх файлів, а через це їх робили тільки за великою потребою. Також SVN централізований, тобто коміти відбувалися на сервер, отже: повільно, з конфліктами з чужими змінами, та тільки за наявністю звʼязку. Це як замість git commit
завжди був git push
в main
. З усім тим, я навіть тримав SVN для власних проєктів, бо контроль версій це велика допомога.
(До Subversion я ще памʼятаю Visual SourceSafe, де щоб відредагувати файл, його треба було “бронювати”, тобто ніхто інший міняти його не міг. Можете собі уявити, як воно весело — часто доводилося підходити до колеги та просити звільнити файл.)
А ще на початку десь поруч з Git був Mercurial. Я нарешті згадав, чому ніколи серйозно його не роздивлявся. Просто Ruby on Rails був на Git! А я на той час вже почав писати на Rails. Потім став успішним GitHub, та тепер вже ніякої конкуренції між Git та Mercurial немає.
Чи хотілося б чогось іншого за Git? Ну в нього є слабкі сторони, як-от версіювання великих файлів, чи підмодулі, які часто виходять незграбними. Проте він абсолютно “good enough”, та це чудово.
17.06.2025
Проєкція GPX на світлину 2
🖼️ …В продовження вчорашньої теми, доробив до якогось результату, але далі, здається тільки з ручною роботою (про що нижче).
Сьогодні займався впорядкуванням того, що вчора накидав, бо досяг межі, коли далі йти нереально. Зокрема, завдяки нормальному потоку перетворень точок, зміг взяти частину точок, видиму в кадрі, та зберегти відповідний GPS-трек у GeoJSON, звідки його дуже легко побудує GitHub Gist (такий вам трюк в нотатки — це найлегший спосіб показати геодані на мапі.)
Це я робив для того, щоб переконатися, що цей хаос точок дійсно відповідає моєму кадру. Та, на велике задоволення, переконався. Значить, я правильно орієнтую камеру, та залишається питання проєкції.
Дізнався, що камери Three.js перетворюють координати в так звані NDC - нормальні координати екрана. Це не зовсім те, що я очікував — а саме, куб від -1 до 1, де з X та Y все більш-менш зрозуміло, а Z включає весь простір від найближчої до найдальшої площини області видимості. Все це треба знати, щоб вірно розташувати результати в кадрі та відітнути невидиме. (Оце починаєш спочатку робити випадкові зміни, щоб тільки запрацювало, а потім виявляється, що половину треба відкотити та зробити по-правильному.)
І другий момент, який довелося серйозно передивитися — це кут огляду. Виявляється, що айфон звітує горизонтальний кут, а Three.js хоче вертикальний кут огляду. Та щоб перетворити, там мало поділити на співвідношення сторін, а є дика формула із тангенсами-арктангенсами. Після того як виправив кут огляду, картинка нарешті почала сходитися з реальністю.
Далі результати ускладнюються двома моментами. Менш важливий — це похибка GPS. Якщо відстань до треку достатня, ти її й не помітиш. Але дійсно проблема — це поведінка акселерометра. Якщо телефон не знаходиться в спокої, то акселерометр показує не вниз, а в напрямку руху (грубо кажучи.) А хто ж зі штатива знімає…
Зате якщо дозволити ручне керування, то можна “від першої особи” виправити, просто рухом миші чи пальця. Бо нам треба лише трішечки скоректувати напрямок камери. Але то вже буду доробляти коли буде настрій наступного разу.
16.06.2025
Проєкція GPX на світлину
⛰️ Дивився сьогодні на світлину схилу гори, на якій було видно стежку. Та це навіяло ідею: а що, якщо, маючи GPX-трек маршруту, показувати його на світлині? Тут є моменти, які очевидно майже нереально зробити автоматично (як-от не показувати те, що сховане за ландшафтом), але в цілому має бути здійсненно.
(Пошукові системи мене не розуміють, тож уточню: йдеться не про світлину згори вниз, тобто мапу, а про звичайну пейзажну світлину. На мапу накласти трек проблем не складає, та інструментів для цього вистачає.)
Переглянув, яку інформацію зберігає айфон у світлині. Виходить, що дуже багато! (Навіть є uptime
телефону, але то нам не треба.) GPS-координати та висота — звісно, що є. Також є GPSImgDirection
, тобто азимут фільмування. І нарешті, AccelerationVector
- показники акселерометра, тобто кути нахилу телефону. Та навіть FOV
- кут огляду камери (він різний у різних обʼєктивів). Одним словом, у нас є всі дані для реконструкції матриці камери!
Далі що. Завантажуємо трек (до речі, GPX - це XML.) Переводимо його у пласку систему координат XYZ. Тут головний нюанс — що градус довготи змінює довжину залежно від широти, а інші нюанси є в моїй статті про координати. Та, до речі, поки припустив, що викривлення земної поверхні не важливе, хоча й це можна врахувати.
Тепер наче залишається суто класична задача 3D-графіки: перспективна проєкція. Для того має сенс взяти готову бібліотеку, як-от Three.js. Там як раз можна збудувати камеру з кутів повороту, кута огляду, співвідношення сторін тощо. І далі однією операцією project()
точки переходять в систему координат зображення.
А потім з тих координат малюємо поверх світлини ламану — наприклад, бібліотекою sharp або той же ж Three.js. То й все! Маршрут побудований.
От тільки поки я до кінця не налагодив всю цю математику, тому проміжний результат — ось, а далі буде.
15.06.2025
Метапрограмування та особливий стиль Clojure
В Clojure, абсолютно впевнено, код є даними. Насамперед для цього потрібно, щоб код не відрізнявся від даних на вигляд: саме для цього в ліспах такий дивакуватий синтаксис, де код не має особливих відзнак. Будь-яка конструкція з дужок може бути як “нормальним кодом”, так і вхідними даними для макроса, який інтерпретує цю конструкцію аж будь-яким чином.
Є макроси ситуативні: defroutes
чи html5
тощо. Вони нагадують схожі конструкції в Ruby чи JavaScript, бо принаймні не ставлять задачі вигадати нові мовні конструкції. Але то тільки верхівка макросів на Clojure… Бо справжній айсберг то макроси, що спрощують деяку сталу мовну конструкцію. Таких повно в самій стандартній бібліотеці. Так званих спеціальних форм, тобто дійсно “аксіоматичного” коду, який напряму розуміється компілятором, лише з десяток. А всі інші — як cond, аналог switch-case
, вже реалізовані як макроси.
Але звісно, стандартною бібліотекою все тільки починається. Бо все можна переробити під себе, або принаймні знайти вже перероблене.
Як приклад: бібліотека swiss-arrows. В Clojure вже є доволі проста протяжна форма (-> x f g)
, що еквівалентно (g (f x))
. (Це лише один спосіб спростити вкладені виклики.) Але ця бібліотека додає макроси для набагато складніших ситуацій, як-от діамантова вудка (sic) -<><
, що виконує одну форму та поширює результат до списку інших, можливо й в паралелі: (-<>< (+ 1 2) [<> 3] [4 <>])
.
Не знаючи макроса, під час просто неможливо зрозуміти, що він робить. (Бо ота вудка нічим не видає своєї дії.) Такі можливості створюють екосистему, де від проєкту до проєкту код може відрізнятися радикально. Це й гарно і погано водночас.
Гарно, бо можна ліпити код під себе, та майже нічого не стоятиме поперек шляху. Та повір, знаходити (чи створювати) та використовувати зручні макроси — на Clojure частина повсякденної інженерії, та без неї виходитиме багатослівно та теж незрозуміло.
Погано, бо немає ніякого стандарту. Ідіоми Clojure містять більш загальні твердження, як-от “пиши функціональний код” та “використовуй функції вищого порядку.” Коли шукаєш приклади чи читаєш код бібліотек, часто здається, що вони написані різними мовами (та певною мірою, так і є!)
Чимсь все це нагадує бібліотеку Lodash, бо там теж можна писати фільтри та інші параметри різними спрощеними шляхами: _.map(xs, ["foo" bar])
. Але я б радив спробувати Clojure, щоб на собі відчути цю силу вигадувати код таким, яким це зручно для твого проєкту.
14.06.2025
Як я робив проєкт аналізу автобусного руху
Років з 10 чи трохи більше тому в Дніпрі зʼявилася перша система відстеження руху автобусів - transit.in.ua (давно припинив існування, зараз там якийсь спам.) Вона показувала на карті координати автобусів… але більше не вміла нічого. Зокрема, не було там прогнозу прибуття автобуса.
Я якийсь час намагався цей прогноз запрограмувати. Виявилося, не так це легко! Втім, то був один з моїх експериментів на Clojure, та я хоч в цьому плані отримав користь.
Головна проблема ось в чому. Координати автобуса це є точка. Маршрут це є ламана. Точку потрібно перекласти в систему координат маршруту. Тобто отримати значення від 0 до 1, що показує пересування автобуса за маршрутом.
І тут далі… координати майже ніколи з ламаною не збігаються, бо такий реальний світ. Ба більше, за координатою не зрозуміло, в якому напрямку рухається автобус, бо через похибку її можна віднести як до прямого, так і до зворотного маршруту. (Зазвичай маршрути малюються як кільце, а не тільки лінія з кінця в кінець.)
Отже, доводилося також стежити за рухом точки ламаною та дивитися, чи буде він “у відʼємному напрямку”; тоді ми помилилися (“не вгадали”) з місцем — та треба брати місце на зворотному відрізку. Як можна уявити, коли в системі зʼявляється час, то вся архітектура ускладнюється.
А особливо допікав шум — автобуси, що стоять в тупику, ті, що поїхали в депо, або просто неправильно налаштували датчик. Я, напевно, тоді ще не зрозумів, що краще почати з часткового рішення, ніж намагатися покрити всі варіанти, та зрештою так і не розвʼязав цю задачу. А тепер, бачите, різні компанії вже розвʼязали.
Поставив питання — а де зараз взяти таку інформацію? Бо нині хто хочеш показує автобуси, включаючи Google Maps - але при тому самі трекери встановлює хтось один (влада?) Отже, повинне бути “джерело істини”. Та воно є! Відкрив для себе портал data.gov.ua, на якому, проміж іншим, є й API транспорту Дніпра, та й багатьох інших міст. Дуже цікаво!
13.06.2025
Чому ніхто не зробить нормальний застосунок для навігації?
Нещодавно приїхав за навігатором на турбазу в лісі… але був нюанс. Він обрав дорогу, хоч й максимально наближену до мого призначення, але з іншого боку річки. Через ці 20 метрів відстані довелося обʼїжджати 20 км лісу. Серйозно!
Я дуже люблю карти, але не можу любити поточний виводок навігаторів: Google, Waze, Apple… та всіляке дрібне, езотеричне та з різним рівнем доробки та підтримки. Наприклад, я люблю OpenStreetMaps всім серцем, але без врахування заторів в навігації великим містом нема сенсу.
Не люблю, що навігатори майже не беруть до відома особисті вподобання користувача. Є невеличкі покращення, але вони всі приховані за непрозорим інтерфейсом. Який все ж не йде далі ніж “з точки А в точку B”… можливо “через точку C”. Я все збираюся зробити свій навігатор для серйозних користувачів, але… ну ви знаєте, як воно буває з цими ідеями.
Для початку, просто хотілося б запланувати маршрут заздалегідь та знати, що він більше не зміниться. Ті застосунки, що я знаю, зберігають тільки точки маршруту, але сам маршрут може змінюватися. Інколи це гарно (коли затори), а в інших випадках ти ретельно перевірив маршрут (з міста у незнайоме місто), а навігатор несподівано веде зовсім іншою дорогою. (Та, звісно, хотілося б робити це в комфорті, з компʼютера, хоч це може й розкіш.)
Навздогін — хотілося б частину маршруту перемалювати вручну. Таке постійно доводиться робити, якщо десь на трасі відомі проблеми. Це така проста операція, але жодний навігатор такого не дозволяє.
Або взагалі, щоб деякі ділянки маршрутів можна було позначити, як улюблені. Як критичний випадок: заїзд у двори — завжди слабке місце в навігації. Але я чудово знаю, як саме я хочу заїжджати у свій двір. От можна було позначити це заздалегідь та уникати інших маршрутів. Зокрема в моєму дворі Waze відмовляється пропускати мене “під цеглину”, хоча це повний абсурд.
Чи вказати навпаки, ділянки, які я ніяк не хочу відвідувати. Може, бо там дорога погана, може там перекрито, чи просто не люблю. Така функція є в Garmin, але ж де зараз ті навігатори Garmin порівняно з застосунком на смартфон та CarPlay.
Можна сказати, що якщо ти знаєш дорогу, то навіщо тобі навігатор? Так, але не так. Часто ти знаєш тільки частину дороги. Або знаєш всю, але хочеш мати оцінку часу. Чи помітити та обʼїхати значні затори. Але, навігатори продовжують робити в найзагальнішому режимі (хоч і збирають з нас купу особистої інформації!)
12.06.2025
Capybara + Playwright: мрії здійснюються?
Не встиг я написати, що втомився від Capybara, як натрапив на незнайому мені досі бібліотеку capybara-playwright-driver. Так, це саме те, як що воно звучить: драйвер для Capybara через потужності Playwright - одного з передових інструментів інтеграційного тестування.
(До речі: знайшов я цю бібліотеку з іншого проєкту - capybara-lockstep - він стабілізує тести через неявне примусове очікування кожної операції. Але з нею досвіду не дуже маю.)
Отже, Capybara із Playwright, за досвідом, працює непогано — порівняно з Selenium, значно більше можливостей та менше місць, де доводиться робити криві обходи. Наприклад: є метод route для легкої підміни запитів з браузера. Дуже корисно для всяких сторонніх інтеграцій. Або Download - для перевірки завантажень. Це взагалі ексклюзив!
Також, оскільки цей драйвер керує звичайним сеансом Playwright, ми можемо трасувати тести, тобто зберігати повний хід виконання, включаючи всі запити до мережі, всю консоль, навіть стан DOM в кожний момент тесту! Це астрономічно більше інформації, ніж дає Capybara.
Втім, трасування виказує й недолік цього драйверу. Він використовує Playwright на простому, низькому рівні. Наприклад, в Playwright є власне очікування операцій — та дуже гарне. Але щоб зберегти поведінку Capybara, драйвер не користується ним, а тільки виконує команду перевірки багато разів.
Тут же ж є й альтернатива: пакет plsywright-ruby-client, на якому збудований драйвер. Він вже дає безпосередній доступ до дій та перевірок від Playwright. Тобто теоретично можна викинути капібару та писати тести прямо на Playwright, але з Ruby! Та зі збереженням повними можливостями підготовки стану та перевірки результатів на бекенді.
Поки я в захваті від цього нового підходу, та сподіваюся, він закриє частину недоліків Capybara. Одне тільки трасування чого варте.
11.06.2025
Відчуття від GTD
(Поки закінчую писати про GTD. Я наче пройшовся по основах, а також зрозумів, що краще писати, коли є натхнення з конкретної теми. Не кидаю надій зробити колись красивий посібник українською.)
Хотілося замість всього цього сухого поговорити про відчуття. Що я відчуваю без GTD та тоді, коли система працює.
Ось сцена, яка мені знайома як рідна. В ній герой хоче замінити лампочку, але натомість занурюється в яму послідовних задач: закріпити полку з лампами, змастити ящик з інструментом, купити мастило, і фінал — полагодити машину, на що в нього йде весь день. В серіалі це виглядає комічно — хіба не можна було закінчити першу справу, а потім братися за наступну? Але саме так я відчуваю себе без системи, в яку можна записати вхідні — я хапаюся за крайню справу, що здається важливою, бо без системи єдиний шанс зробити справу — це натрапити на неї та вхопитися негайно. Я називаю це “режим хомʼячка”.
Тобто звісно, якби всього в житті було пʼять задач, то нескладно розставити їх за порядком. А коли їх сто?
Напевно, все залежить від характеру (та від нейродивергенції.) Моя голова є нескінченним фонтаном ідей буквально для всього, тому в мене завжди більше незробленого, ніж часу. Частина цих ідей — чудові та розвʼязують справжні проблеми. Але інші — нереальні або тільки створюють додаткові проєкти та додаткове навантаження.
Без системи я заходжу на кухню та бачу мільйон задач — від законних “прибрати посуд” до наче важливих, але не зараз “повісити гачки для каструль” до зовсім казкових “зробити вертикальну грядку для зелені”. Виходжу з кухні та бачу ще мільйон задач… Річ не у тім, що всі їх треба зробити, та навіть не в тому, що треба виділити пріоритетні. Система GTD дозволяє мені зібрати всі задачі в єдину купу, та в спокійних обставинах приділити їм належну увагу.
З системою я оглядаю кухню та бачу — все як вчора, про все це я вже подумав. Можна спокійно прибрати посуд. О, і ще оце посилка нова лежить — запишу, щоб з нею розібратися. (Нарешті проєкт з гачками розблокований!)
Тобто, GTD існує (всупереч назві?) не заради того, щоб зробити всі справи, а щоб можна було спокійно взаємодіяти з життям та вже на ґрунті цього спокою будувати все інше. Та щоб я не захотів будувати - GTD допомагає рухатися до мети. Як кажуть, в GTD будь-що стає проєктом — значить, будь-що можна зробити - задачі, ідеї, мрії, турботи, тривоги. Ось заради цього спокою та впевненості я завжди повертаюся до GTD, скільки б не кидав.
10.06.2025
Звички GTD: огляд
Всю систему GTD можна розділити на дві частини:
“Активна” частина — це списки наступних дій та вхідні. Вона потребує щоденного перегляду. Дії ми просто робимо (сподіваюся), а вхідні обробляються за схемою. Це все, що потрібно робити постійно, щоб залишатися з робочою системою. (Ну й, звісно, користуватися календарем.)
Решту системи ми переглядаємо щотижня. Це називається, очікувано, тижневий огляд.
По-перше, під час тижневого огляду переглядаються всі проєкти; якщо є такі, що не мають наступної дії, чи застрягли без прогресу, то виправляються. Часто розумієш, що проєкт чи дія поставлені невірно та переформулюєш. Або — видаляєш / пересуваєш до “мабуть/колись”! Бо зайвих проєктів повинно не бути.
По-друге, ми додаємо нові проєкти. Вони можуть братися з календаря нагадувань, з “мабуть/колись”, або просто з навколишніх обставин. В офіційних посібниках для того є довжелезний перелік питань-тригерів, але можна зібрати й власний — з усіх сфер життя, де можуть виникнути проєкти.
Чому тижневий? Можна було б й рідше. Але краще стежити за обсягом системи та не брати більше справ, ніж можна переглянути за годину кожного тижня.
Що я не роблю щотижня, так це перегляд всіх “мабуть/колись” - їх просто надто багато. Натомість переглядаю тільки по одній категорії. Гадаю, це в моїй системі слабке місце, але з тим “мабуть/колись” - найменш термінова категорія, та зазвичай готова чекати.
Без регулярного огляду система розвалюється. Але, як бачите, саме завдяки систематизації нам вже не потрібно робити якийсь епічний огляд всього життя в абстракції, а достатньо переглянути кілька списків. Та, дуже приємно щотижня знати, що ти все переглянув та задачам більше немає де приховатися.