Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
02.05.2025
Що я любив у Pivotal Tracker
…Якщо в мене й був улюблений трекер робочих задач, то це Pivotal Tracker. Той, що два дні тому закрився, та ще й так суворо, що навіть стилі блогу злетіли — а можливо, невдовзі зникне й сам блог. Згадаю, чим Pivotal Tracker був такий хороший.
(Я навіть давно писав клієнт командного рядка, а потім інтеграцію з OmniFocus). А колеги з роботи писали доповнення для Chrome. Одним словом, років 15-10 тому це було прямо явище.)
Головним чином, Pivotal Tracker був орієнтований на розробників. Якщо ти розробник, то це наче само собою зрозуміло, але насправді трекерами задач користуються ще, наприклад менеджери, яким потрібно планувати великі проєкти та узгоджувати роботу різних команд. PT це абсолютно тактичний, а не стратегічний трекер. Та тактика розробки в ньому була неперевершена.
Список задач показував все, що тобі потрібно знати про сьогодні та недалеке майбутнє — стан задач, скільки залишилося, хто над чим працює, що вже закрили тощо. Всі дії робилися прямо тут, одним натиском кнопки. Задачі стояли в порядку виконання. Хочеш змінити пріоритет — перетягуй задачу вгору чи донизу. Фактично весь інтерфейс це й був один екран трекера. Ніяких блукань Джірою в пошуках таски.
Але ця сфокусованість була й недоліком Pivotal Tracker. Він вимагав дуже чіткого процесу розробки (можна було б сказати - Agile - але це слово може значити аби що.) Ну, наприклад: PT автоматично бʼє роботу на спринти, дивлячись на оцінки та швидкість виконання. Для цього потрібна однорідна команда, де хто завгодно може підібрати задачу.
Pivotal Tracker був продуктом із вбудованою методологією. Що в цілому не так далеко від того, як я сам думаю про продукти, та вважаю, що це чудовий підхід, коли ця методологія є (У Pivotal Labs - величезної та успішної фірми з розробки — була.)
До речі, з живих досі продуктів мені ще подобався Shortcut, тоді відомий як Clubhouse. В нього із Pivotal Tracker є дещо спільне. А ще хтось зробив сайт Goodbye Tracker, де зведені понад 10 альтернатив — деякі дуже зрілі!
01.05.2025
Штучний інтелект — хто виграє від нього найбільше?
Перше, виграють виробники потужностей. Всі великі виробники компʼютерів вже вийшли з “AI” пристроями. Дуже вчасно зʼявилася причина оновити компʼютер, бо якщо не дивитися на “AI”, то останніми часами компʼютери стали достатньо потужні, щоб не думати про наступний. (Бо в моєму дитинстві компʼютер оновлювали, щоб на ньому можна було подивитися фільм.)
“AI” це золота жила тому, що його можна продавати будь-кому — від малої дитини до панів в костюмах. Зокрема, подивимося на відеокарти. Ресурси для відеоігор досягли стелі якості, за якою їх нерентабельно виготовляти. Та й ринок все одно обмежений. А тепер можна скільки завгодно потужностей продати заради “АІ”.
Хоча понад усе виграють власники хмар. Бо, цілком очевидно, що ніж купувати дороге залізо, можна заплатити хмарі. Тому, коли зараз кажуть, що пристрої “з AI” не мають попиту, я гадаю, що споживачу хмари достатньо. Наперекір сумнівному ставленню хмарних компаній до етики — про яке можна судити вже з того, що вони вже тренують моделі навіть на піратському контенті.
Друге, це ринок стартапів. У тому вузькому сенсі, як продуктів, які будуються, щоб отримати інвестиції або продати задорого та швидше. Інвесторів легше переконати, коли за тобою стоїть Технологія Майбутнього, Яка Тільки Відтулила Двері Для Найрозумніших — хай то бізнес в інтернеті, соціальні мережі, блокчейн чи тепер AI. Тому серйозні стартапери не шукають революційних ідей, а застрибують в поточний Віз Революції та галасують якомога гучніше, що Віз справжній, а хто на нього закине грошей — поверне їх встократ.
Я поки не добрався до того, що ж все ж таки “AI” здатний чи не здатний робити, як-от генерувати красивий ввічливий лист, або, наприклад, підсумувати задовгий лист до його змісту. (Жартую.) Давайте так — багато на що здатний. Про це іншим разом.
30.04.2025
SwiftUI - рефакторинг та оточення
Сьогодні додав маленьку фічу до свого стохастичного таймтрекера — а саме, можливість передивитися всі пінги, які відмічені конкретним тегом. Що корисно, щоб згадати минуле. Щоправда, я досі не зробив перегляду більше за 50 пінгів, бо для того потрібне ліниве завантаження — тож не дуже далеке минуле.
Фіча звучить зовсім простою. Запит для останніх пінгів вже є. Додаєш до нього фільтр по тегу (до речі, із CTE) та виводиш списком. Але є й проблема.
Натискання на пінг відкриває форму редагування. Така можливість, звісно, потрібна й на новому списку. Ця форма не така проста річ — бо вона є модальним вікном, та на екрані ніколи не повинно бути двох форм. Тому її стан є глобальним.
Цей стан в мене поки зберігався просто в @State var formModel
на структурі застосунку, та передавався глибше через @Binding
. Цього разу я прикинув, через скільки шарів доведеться прокинути @Binding
та вирішив, нарешті, переробити.
У SwiftUI є можливість, схожа на контексти в React - це Оточення, @Environment
. Нею можна передати вглиб структури презентації якесь значення. Але — саме значення, не змінну, редагувати його не можна.
Або… можна? Спочатку я спробував передавати функцію-сетер, setFormModel
. Це спрацювало! Далі пошукав більш ідіоматичне рішення та знайшов, що взагалі-то в @Environment
можна передати Binding(FormModel)
, та тоді його можна буде призначати через formModel.wrappedValue = newFormModel
.
(Binding
, який лежить в основі моделі стану SwiftUI, як раз і є абстракцією над гетером та сетером, яка загортає змінне значення у незмінну обгортку.)
Код став гнучкіше та чистіше. До речі, в останньому SwiftUI цей @Environment
значно спростили, так що якщо давно не бачили — подивіться.
🕜🏷️ Нагадаю, що я пишу Ping - застосунок на iOS для нетрадиційного обліку часу. Якщо цікаво, до бети можна доєднатися тут.
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
можна швидко передивлятися зміст архіву та редагувати його. Але головне, на мою думку, дотримуватися цих двох поширених форматів та не лізти в екзотику.