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

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

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

29.04.2025

Кращий час для виправлення технічного боргу може бути зараз

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

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

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

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

Виходить, чим успішніше проєкт, тим менше треба відкладати на технічний борг. На сьогодні логіка така.


27.04.2025

Застосунок для покращення оцінок часу

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

Ідея в тому, що якщо давати оцінку, а потім заміряти справжній час виконання, то можна побачити розбіжності та згодом зробити оцінки точніше. Я не раз чув про такий підхід, але не знайшов застосунків. (Здивуйте мене!) Хоча, звісно, застосунок дуже простий — таке собі поєднання таймера та секундоміру.

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

Бо так, я передбачив, що задачі ж повторюються, та чим більше вимірів, тим більше впевненості. Тому кожен “експеримент” відбувається не в ізоляції, а в контексті якоїсь “активності”.

Та ще є сповіщення, які я вже навчився робити по-всякому. Одне сповіщення — на “заявлений” час виконання, друге — на середній час (тобто “емпіричний”). І ще можна повторювати в час, кратний заявленому - щоб зовсім сумно стало.

Окрім прямої користі — самодосліджень — застосунок також мотивує робити справи без відволікань! От зараз пишу пост та вже відчуваю підвищену концентрацію.


27.04.2025

Як я робив TG-бота для самоменеджменту

Прочитав нещодавно в пана Рожкова про бота для обліку пального. Та відразу згадалося, як я колись такого нагородив… аже поділитися захотілося, бо проєкт нікуди не пішов. Йдеться про бота для обліку власних задач за моделлю GTD.

Власне, ось навіть код виклав.Я писав його влітку 2017-го, але сьогодні легко завів. Бо це Go, а не React Native. У Go підтримка легасі — це одна з головних цінностей дизайну. Ще треба зазначити, що в Telegram дуже зручна модель розробки ботів, тож ти його можеш запустити в себе локально та створити власного бота. Поки програма запущена, бот буде доступний будь-звідки через інтерфейс Telegram.

Як бот влаштований. Фактично бесіда з ботом — це “вікно” в дані, яке фокусує нашу увагу на чомусь одному (наприклад, поточній дії.) Задача бота — просувати це вікно, а також пропонувати ефективні та вчасні операції в поточному контексті. Це досить особливий бот, можу порівняти його з людиною-тренером, або з інтерактивною літературою, тільки ще й з твоїми даними всередині.

Головна складність в тому, що він повинен памʼятати стан бесіди, причому навіть після довгої паузи. А бесіда має складну блок-схему (“обробка вхідних” в GTD вже складна!)

Я роздивлявся різні моделі та вирішив розбити спілкування на пари “питання-відповідь”. Кожне питання має: код-ідентифікатор, “шаблон інтерфейсу” - текст та кнопки, та обробник відповіді.

(До речі, оці кнопки - це лише “заготовлені відповіді”, тобто немає різниці, натиснути на кнопку чи ввести її текст вручну. А також тому можна обробляти кнопки та вільний ввід одночасно, в одному “питанні”.)

Обробник інтерпретує відповідь, робить належні зміни в базі, та надсилає повідомлення про результат. Результатом обробника завжди є нове питання, яке набуває чинності та отримує шанс побудувати вже власний “інтерфейс”. Наприклад, ось питання action_suggestion з ілюстрації.

Таким чином вдалося ізолювати логіку кожного кроку. Щоправда, я на той час не здогадався класти додатковий стан, як-от поточну дію, в поле JSONB, а записував прямо в спільні поля в моделі користувача. Це погано, бо в кожного питання може бути своє розуміння “поточної дії”.

Мені цей проєкт, з одного боку, подобався та досі подобається за його інтерфейс. Є щось особливе в тому, щоб працювати з даними в режимі діалогу (що на цей день стало тільки актуальніше.) А з іншого, діалог обмежує. Зокрема як тільки треба передивитися всі дані в базі, та ще й робити над ними зміни. Були в мене фантазії гібридного застосунку — тобто такого, де діалогова модель доповнює традиційну - але руки не дійшли.


26.04.2025

OmniWOPE: публікація ілюстрацій в Mastodon

Хотів сьогодні насправді писати зовсім інший пост, але для нього потрібна була ілюстрація. А їх мій скрипт для публікації — себто OmniWOPE - не вмів викладати в Mastodon. Нарешті цей недолік виправлено, та зображення повернуться в мій канал.

Технічний прототип в мене вже рік був готовий. Ну тобто я міг завантажити дану світлину в Mastodon. Що, до речі, відбувається у два кроки: спочатку медіафайл окремо, потім — статус із посиланням на ID файлу.

Але я довго думав, як же ж організувати статуси. Додавати зображення прямо у головну статтю мені не подобається, бо це спонукає клієнтів показати її як “статус-зображення”. Нарешті вирішив публікувати як відповідь до головного статусу — це все ж загально прийнятний спосіб.

Ще виявилося, що треба ж оголосити тип медіа. (До речі: сьогодні дізнався, що саме “тип медіа” сучасна назва, а не “тип MIME”.) Досі для Telegram мені було потрібно тільки знати, чи є ілюстрація зображенням чи відео. Та нарешті, чомусь вбудований у Go метод multipart.Writer#CreateFormFile не дозволяє призначити тип медіа! Та найкраще рішення для того — скопіювати та виправити код методу.

На сьогодні все. Нову версію вже можна забрати з GitHub.


25.04.2025

Графічні клієнти для Git

Я вже багато років майже всі коміти в Git роблю з графічного інтерфейсу. Інакше мені роботу важко уявити, бо я люблю коли мої коміти акуратні та впорядковані.

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

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

Цікаво, що все інше я роблю через термінал. Хоча, наприклад, для перегляду гілок теж є багато програм; втім, ми користуємося простою моделлю гілок, тому терміналу вистачає. Ну, хіба що ще git blame з редактора зручно робити.

Щодо конкретних програм: колись дуже давно все почалося з git gui - стандартного інтерфейсу. Здається, це було в мій час Linux на Windows, та я відкривав той GUI через Xming. Але наче цей GUI досі живий Потім я переїхав на мак, а тут git gui немає. Знайшов gitx - наче якщо не клон, то дуже схожу програму. Вона досі підтримується, та я досі її можу рекомендувати для macOS. Хоча останні роки мої коміти робляться всі через VSCode, тож у твоєму IDE теж може бути гарний редактор комітів — залишається ним користуватися.


24.04.2025

Швидкі задачі

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

Так, є архетипова ситуація, де розробник каже на задачу - “ой, справ на пʼять хвилин” - а вона обертається цілим днем. Це не скасовує того, що, є й такі задачі, які дійсно можна зробити, покрити тестами, та оформити за лічені хвилини. Особливо коли це стосується прибирання (тобто видалення) коду, або дрібних змін в інтерфейсі.

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

Але як тільки така робота стає поза поточним контекстом, планувати її стає важко. Керування проєктами гарно працює з епіками на тижні та місяці роботи, а не на хвилини. Мені стає боляче слухати про “заплануймо це на після оцього”, коли йдеться про годину чи дві роботи.

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


23.04.2025

ZIP проти .tar.gz

🗜️ На мою думку, необхідно знати рівно два архівних формати (“формати” насправді умовно, про що нижче.) Різниця між ними дуже суттєва.

Справа тут в чому. Алгоритми стискання всі працюють на потоках даних. Про файли та каталоги вони нічого не знають. Тому коли ми хочемо стиснути каталог, доведеться спочатку перетворити його на потік даних.

.tar.gz - це насправді комбінація двох архівів (за принципом Unix “кожна програма робить щось одне”.) tar зберігає каталог файлів у вигляді потоку. Щоб прочитати один з файлів, доведеться бігти по архіву, поки його не знайдеш. gz стискає один файл — це не обовʼязково файл .tar, може бути будь-який, наприклад, .json.gz - якщо вам потрібно стиснути лише один файл, tar не потрібний.

ZIP зберігає файли каталогом, де кожний файл стиснутий окремо. Тобто на верхньому рівні ZIP файлу сидить каталог, в ньому можна знайти будь-який файл та розпакувати. На ZIP побудовано багато форматів файлів — це JAR, DOCX, ODT тощо. На відміну від .tar.gz, ZIP-архів можна швидко передивлятися, розпаковувати окремі файли, та навіть редагувати архів — бо в .tar.gz можна тільки створити його наново.

Алгоритмів стискання існує багато - gzip, bzip2, xz, Zstandard. Обирати варто тоді, коли у вас дійсно є потреба заощадити якнайбільше; в іншому разі я б брав всюдисущий gzip. До речі, ZIP теж підтримує багато алгоритмів, хоча “нормальний” такий саме, як і в gzip - DEFLATE.

А ще окрім стискання є шифрування. Тут ZIP програє, бо в нього досі немає шифрування аж всього змісту архіву. А з .tar.gz все просто — зверху накидається шифрування, та виходить .tar.gz.enc чи .tar.gz.pgp.

Виходить, вся різниця в тому, що .tar.gz суттєво простіше, зате у .zip можна швидко передивлятися зміст архіву та редагувати його. Але головне, на мою думку, дотримуватися цих двох поширених форматів та не лізти в екзотику.


22.04.2025

Oblivion

Сьогодні абсолютно несподівано вийшла оновлена версія Oblivion: Remastered. Звісно, я поки нічого, окрім вступу, в ній не бачив, але поки виглядає як дуже цікавий ремастер, де наче оновлений графічний рушій з Unreal Engine сидить на старому ядрі. Не виключаю, що вони перевіряють такий підхід для використання в нових іграх, а не тільки для ремастера. В ремастері є стара знайома тека Data, наповнена старими знайомими файлами Oblivion, тож я гадаю, можливо й моди будуть працювати.

Але хотілося натомість згадати, як вийшов оригінал Oblivion. Ще до того ми з друзями були фанатами Morrowind та чекали виходу наступника. Обіцяли, що це буде “гра для компʼютерів майбутнього” та буде надзвичайно крутіша за Morrowind. В ту епоху (2004) інтернет був дуже обмежено, тому більшість інформації розходилася плітками. Чесно, набагато цікавіше уявляти, яка вона буде та гра з описів, ніж бачити трейлер. Хоча зрештою всі ті фантазії виявлялися хибними.

Хоча що було чистою правдою — на моєму компʼютері (здається, із Radeon 9250) Oblivion ледве йшов. Запускався — що вже успіх — але гальмував так, що доводилося знижувати якість та дальність зору до мінімуму — що не допомагало. Згодом знайшов програму, здається, Oldbivion, яка підставляла спрощені шейдери. Уявляєте, спрощені шейдери, щоб гра йшла! Перший та останній раз довелося таке робити.

В мене мішані відчуття від Oblivion. В ньому багато цікавих квестів та мальовничих локацій. Та я бозна скільки програв в нього юнаком. Але з тим в Oblivion жахлива прогресія та бойовка, яка з часом стає тільки нудніше. Тому не сумую за ним. Для мене, Morrowind досі є верхівкою формули Elder Scrolls. Та судячи з активної сцени модів для неї, не тільки для мене.


21.04.2025

Резервне копіювання для Ping

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

На жаль, забув випустити раніше. Але ось що допомогло. Моя власна копія почала зависати на запуску. В XCode дуже легко зрозуміти. що зависає — достатньо поставити застосунок на паузу. Тому коли дістався до XCode, то відразу побачив, що висне — не сама резервна копія — а її завантаження до iCloud, метод setUbiquitous.

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

Так що довелося закінчити фічу — робити копіювання раз на день, додати вимикач та допомогу. Завдяки використанню @globalActor виніс роботу з головного потоку. Тут у Swift цікаво: async/await роблять код рівночасним, але залишають виконання в головному потоці (тобто гальмують інтерфейс застосунку.) Щоб зробити код ще й паралельним, потрібно винести його в актора.

Також зазначу. що бета-версії застосунків в Apple TestFlight згоряють за 90 днів. Тобто кожні 90 днів потрібно викладати нову версію, щоб бета-користувачі не втратили доступ. Та в мене сьогодні минуло 79! Радий, що через цю ситуацію встиг згадати та скоригувати курс.


20.04.2025

Кава та сон

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

І тут теж було несподівано, бо я не став спати краще. Скоріше навіть гірше, бо все літо прокидався дуже рано та не міг заснути. Чи то ластівки заважали, чи кішка, чи сонце у вікно — в будь-якому разі був постійно не виспаний.

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

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

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

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