Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS · 📢 Канал в Telegram @stendap_sogodni
24.06.2024
Перевірка "тільки один" в Rails
Сьогодні написав одну дуже дивну валідацію. Потрібно було перевірити, що в базі є тільки один запис із позначкою “за замовчуванням”. Виявляється, для того є декларативна форма:
validates :default, uniqueness: { if: :default }
Ну, бо просто унікальність не дала б створити більш ніж один “звичайний” запис. А так все працює (та проходить тести, які я написав заздалегідь.) До речі, хоч ми користуємось Shoulda Matchers (давно вже не бачив проєкту без них), але в цьому разі писав перевірку без них. Бо Shoulda Matchers зазвичай повторюють означення валідатора, а я ще його не знав. Міг тільки описати поведінку. Тобто це такий класичний приклад для TDD: коли краще знаєш, що повинно вийти, а не що потрібно зробити.
Якщо поміркувати, таку валідацію можна перенести й в базу:
CREATE UNIQUE INDEX only_one_default WHERE default
Як завжди, якщо база про валідацію не знає, можна опинитись в несумісній ситуації. Причому якщо після помилкового збігу двох записів можна врятуватися через застосунок, то якщо їх стане три, то застосунок не дозволить прибрати один з дублікатів — валідація не пройде. Краще не лінуватися та дублювати кожну валідацію в базі.
23.06.2024
Вам потрібна надійна система "мабуть/колись"
В останній (та поки досить успішної) ітерації самоменеджменту в мене зʼявився новий елемент: надійна та зручна система для зберігання справ на майбутнє, тобто того, що в GTD називається “мабуть/колись”. В мене це Obsidian та канва, але міг би бути якийсь Notion або навіть кращі спеціалізовані рішення, як DEVONthink.
Що тут погано працює, так це програми для керування задачами. В них занадто багато структури, яка для “мабуть/колись” абсолютно надмірна. Більшість “мабуть/колись” до мене приходить у вигляді ідей та думок, які складно перекласти у задачі чи проєкти.
Наприклад: думка “зробить в шафці відділ для робота-пилосмока”. Це схоже на проєкт, та раніше всі такі ідеї в мене ставали проєктами. Принаймні, не загубиться. Але… насправді навіть шафки ще не існує, тому такий проєкт буде висіти без шляху розвʼязання. …А коли незрозумілих проєктів стане 100, система розчавиться під власною вагою.
З системою “мабуть/колись” така ідея йде в купу ідей навколо проєктування шафки. Потім, коли справа дійде до планування, всі такі ідеї можна зібрати до купи та перетворити на конкретний план дій. (Та вже на цьому етапі зрозуміти, чи той відділ взагалі потрібний, чи буде для нього місце і так далі.)
“Мабуть/колись” має фрактальний характер: більша ідея розкладається на менші (шафка сидить в купі ідей про кімнату, кімната — в купі про оселю). Десь я матиму уявлення до дрібних деталей, а в інших місцях тільки малюнок широкими штрихами. Наперед невідомо, якого рівня буде кожна ідея, тому зручно, якщо система організації підтримує таку фрактальність. Причому треба бути готовим записувати думки будь-якого рівня: щоб вони не сиділи в голові. Від “нам потрібна інша база даних” до “додати підказку до поля у формі.”
Також не можна звалювати все до купи: як-то список закладок або беклог в Jira. Ідеї повинні групуватися за змістом, щоб знайти їх в майбутньому. Це, напевно, головний аспект: коли ти додаєш думку в “мабуть/колись”, маєш бути впевненим, що повернешся до неї тоді, коли це буде актуально. Тоді можна дійсно розвантажити голову від гадок на майбутнє та сфокусуватися на поточних проєктах.
22.06.2024
Obsidian: канва у список
Зробив скриптець для перетворення канви Obsidian у список Markdown. На диво, готової альтернативи не знайшов.
Скрипт спирається на звʼязки між вузлами, щоб обійти граф та побудувати дерево від кореня: вузла, на який ніхто не посилається. (Або — коренів.) На виході отримуємо список в Markdown.
Обхід поки наївний та не обробляє цикли (а точніше, якщо корінь є частиною циклу, то він не вважатиметься коренем та той цикл не зʼявиться в списку.) Також можна було б робити щось гарне з групами; вузли стають вкладеними в групу суто за розташуванням; хоч явних звʼязків немає, в списку група може бути батьком своїх вузлів.
Навіщо таке потрібно? Коли канва така хороша? Наприклад, щоб перетворити плани з канви у список задач в традиційному планувальнику. Та й взагалі, ділитися списком значно зручніше. Я можу захотіти зробити конспект у вигляді майндмепу, а потім синтезувати список та додати до загальної документації.
21.06.2024
Колір та фарби
Щільно зайнявся ремонтом, тому не залишається часу ані на роботу, ані на проєкти. Втім, цікавим для мене відкриттям була фізична фарба. Бо веде вона себе зовсім не так, як на екрані.
Я, звісно, все життя стикаюся з кольором: цифровим. Система RGB - найпряміший опис кольору на екрані — перекладається прямо на інтенсивність пікселів. Система HSL - не така пряма, зате як легко з нею коригувати та поєднувати кольори. Навіть з друком все зрозуміло: там система CMYK.
Але фарба себе поводить зовсім інакше; на відміну від пікселів на екрані та крапок в принтері, фарба не є дискретною, а натомість наповнена часточками пігментів. Неможливо “надрукувати пігмент правильного кольору”, тому навіть з цифровими машинами для змішування ми все одно обмежені фізичними властивостями вхідних пігментів.
Ну, тобто звісно, теоретично ми можемо намішати нескінченно багато комбінацій. Але щоб робити це повторювано, доведеться покластись на ті тисячі кольорів, які закладені в можливості машини. В тому й лежить вся складність: фарбу не можна просто обрати за палітрою з 16 мільйонів кольорів.
Замість того доводиться брати віяло зразків… Що мене перед усім дратує у віялі — то обмеженість рухів (порівняно з RGB, де я легко знаю, як додати, наприклад червоного.) Тут допомагає знання системи NCS, в якій кольори вписані в трикутник “чорний — білий — відтінок”. Звісно, можна конвертувати RGB в NCS, але далеко не всі кольори будуть дійсно збігатися.
20.06.2024
Стилі для Obsidian Canvas - реалізація
Ось перша версія стилів для канви. Не знаю, наскільки вони універсальні, бо мені більше подобається ідея стилів для індивідуальних потреб — в кого як голова працює.
Що в мене: по-перше, обовʼязково треба бачити, які вузли потребують додаткового опрацювання. Це задачі (червоним), питання (жовтим) та ідеї (синім). Далі, відзначаю закінчені (зеленим), скасовані (сірим), та заблоковані (крижано-блакитним) вузли, щоб не звертати увагу на них. Тип та стан можна поєднувати: заблоковане питання. Нарешті, для кращої організації додав великі та дуже великі вузли; вони грають роль заголовків.
Про технічну реалізацію. В Obsidian потужна система змінних CSS. Через неї, в сукупності з сучасними функціями CSS як calc та color-mix, можна вийти на власний набір кольорів. Масштабування вузлів зробив через атрибут zoom; так вони зберігають внутрішню структуру.
До речі, всі ці стилі можна додавати не тільки до текстових вузлів, а й до будь-яких — малюнків, вебсторінок тощо. Сторінки на канві я не люблю, бо це виходить повільно, до того ж більше хотілося б додавати вирізки, а не весь зміст. А малюнки навпаки, революційно зручно. Почав розуміти, чому Obsidian Sync надає 40 Гб місця — для тексту точно занадто.
Весь пакет можна забрати тут, але зручності поки на альфа-рівні. Пізніше, теоретично можна навіть написати скрипт, який зробить все повністю автоматично, оскільки всі налаштування — це зміст файлів JSON, не більше.
19.06.2024
Семантичні графи в Obsidian Canvas
У форматі JSON Canvas мене відразу привабило те, що у вузлів та ребер можуть зʼявлятися власні атрибути; таким чином, канва набуває не тільки вигляду, а й змісту, тобто стає семантичною.
Наприклад, якщо порівняти моє виконання схеми BRIDGeS (див. малюнок вище) в Obsidian та офіційне в Figma, то в останньому схема має суто візуальний характер: це вузли різного кольору та приліплені до них візуально відмітки пріоритетів. А в Obsidian кожен тип вузла та кожен пріоритет стає атрибутом.
Мені зараз для планування потрібне рішення, щоб було помітно, де задача, де питання, де ідея, а де просто факт. Поки що просто придумав фарбувати активні задачі червоним, а виконані — зеленим (це єдина вбудована можливість оформлення, якщо не рахувати Markdown). Але хочу зробити власні атрибути, та за допомогою Obsidian Canvas Style Menu їх оформити.
Це стане корисним для автоматичної обробки. Наприклад, скрипт може знайти в канві всі задачі, та зробити список за пріоритетом. Також, звісно, оформлення допомагає розрізняти вузли, причому можна навіть комбінувати класи: на ілюстрації зверху дуже просте поєднання типу (за кольором) та пріоритету (міткою); але можна робити навіть на кшталт “якщо це задача та вона виконана, показати галочку.”
18.06.2024
Труднощі статичного хостингу
Статичний хостинг (тобто такий, що вміє тільки віддавати файли) - ніби найпростіша річ, абсолютний commodity. Втім, обрати між ними не так легко, як здається. Все залежить від того, які у вас очікування. Але ось в чому нюанс: як тільки скористуєшся одним статичним хостингом, то очікування поведінки фіксуються, та під час переїзду доведеться з ними рахуватися (або дізнатися, що сайт працює не до кінця, тільки пізніше.)
Нюанси починаються з правил перенаправлення. Будь-який сайт стикається рано чи пізно зі зміною адрес. Будь-який чемний сайт підтримуватиме старі адреси через механізм перенаправлень. Він всюди налаштовується за власними правилами — ось, наприклад, Vercel. А ось Cloudflare Pages. Все так, та не зовсім. Доведеться вручну коригувати та перевіряти. Коли перенаправлень сотні (так трапляється після реструктуризації сайту) - це вже ціла пригода.
Деякі хостинги підтримують адреси без слеша на кінці, а інші — ні. Технічно, ніби присутність слеша “правильніша”, оскільки ми віддаємо index.html
для директорії — а не файл без розширення. Але те, що адреса сторінки виглядає як директорія, це принаймні дивно. Раніше мене це обурювало, зараз вже змирився та зробив все зі слешами (Звісно, через перенаправлення.) Також не всі хостинги готові взагалі показати index.html
(бо це вже не просто “віддавати файли”, авжеж?)
Характер відвантаження файлів на хостинг теж відрізняється. Ось на Vercel примусово потрібно мати репозиторій на GitHub. Що гарно, поки в тебе немає величезних світлин або взагалі — завантажень на гігабайти. На Cloudflare Pages можна відвантажити на пряму, але не можна замінити єдиний файл — тільки все разом. На AWS S3 можна просто оновити окремі файли.
Нарешті, хоч і здається, що статичний хостинг — найшвидше, що може бути в вебі, насправді провайдери, особливо безплатні, не гарантують швидкості. В мене Ahrefs не раз скаржився на повільні сторінки на Vercel. А найшвидше сайт працював на власному сервері — але ж то незрівнянно складніше в підтримці. А ще, на власному сервері буде максимальна кількість особливих умов, та з нього найскладніше буде зʼїхати.
Хотілося закінчити на рекомендації конкретного хостингу, але її в мене немає. Хіба можу порадити не вигадувати власні обмеження (як я зі слешами), а триматися ближче до базової парадигми “сторінка = файл”.
17.06.2024
Miniflux: персональний агрегатор RSS
📢 Останній раз я згадував про Miniflux ще два роки тому. Відтоді та й досі він залишається моїм агрегатором стрічок RSS. Останнім часом їх стало тільки більше: особисті блоги знову набувають популярності.
Miniflux - чудовий застосунок для власного хостингу. Він написаний на Go, тож просто розгортується та потребує мінімум ресурсів. Єдине, що наразі Miniflux працює тільки з PostgreSQL, тож доведеться розгорнути також її. (До речі, Fly.io вміє це робити під ключ.
Неочевидним потужним інструментом в Miniflux є правила переписування. Це готові рішення для типових недоліків RSS: наприклад, він вміє робити підписи зображень видимими, підставляти відеопрогравач, та перетворювати зміст постів. А може взагалі, звернутись до оригінальної сторінки, та отримати з неї зміст: це вже правила скрейпера. Ну та й зрозуміло, що можна фільтрувати зміст стрічки — прибирати нецікаві категорії та інше.
Все це виводить агрегацію RSS на якісно інший рівень. Хоча потреба в RSSHub залишається — наприклад, щоб забирати стрічки з Twitter та Telegram.
Один неприємний момент: за замовчуванням в Miniflux надто лінивий графік повторної перевірки стрічок після помилки: тимчасові помилки швидко стають постійними. Щоб те виправити, можна змінити POLLING_PARSING_ERROR_LIMIT=0
та стрічки будуть перевірятися нескінченно. Все одно не так легко помітити, що конкретна стрічка має помилку — особливо якщо читати Miniflux через програму-клієнта, а не напряму.
16.06.2024
Айсберг технічного боргу
Нещодавно використав цю фразу, та хотілося зупинитися детальніше. Технічний борг не просто сидить та чекає, поки ви за нього візьметеся. В будь-якому проєкті є багато рівнів технічного боргу — від нешкідливого до такого, що змусить вас виправляти продакшн вночі на вихідних.
(Під технічним боргом я розумію все, де виконання розбігається з очікуваними стандартами. Так, це коли не встигли рефакторити код. Але ще й коли поміняли підходи, але частина коду залишилась зі старими. Або не коду, а структури бази даних. Або ще гірше, інфраструктури — її не так швидко змінити. Або CI займав десять хвилин пів року тому, а тепер триває двадцять. Або застаріла версія фреймворку.)
Винищити технічний борг — неможливо. Тому важливо 1) про нього памʼятати та 2) мати розуміння про пріоритети. Це один з обовʼязків головного інженера. Ще один обовʼязок: стежити за сигналами та впроваджувати зміни в доцільний час. Наприклад, не дати CI уповільнюватися надалі. Або оновити бази в “повільний сезон”.
Що б не було, але рішення про виправлення технічного боргу ніколи не прийде від менеджменту. Це суто задача інженерів. Менеджмент може тільки спитати: чому тут повільно / багато помилок / робота гальмує? Але то вже поганий знак: айсберг загрожує кораблю. Краще, щоб інженери помітили потребу раніше; але мали глузд не виправляти кожну дрібницю.
15.06.2024
Балконні сонячні панелі — досвід
🔆 Чули про балконну сонячну систему від EcoFlow? Я чув, та мене спокусило. Ось власний досвід (пишу, поки немає світла 🕯️.) Мій рівень в електриці — зʼєднувати розʼєми та клеми, тож я орієнтуюся на більш-менш готові системи — впевнений, що з більшим хистом можна побудувати щось дешевше та при тому спеціалізоване.
🧶 Перше, що спокусило — це гнучкі панелі. Та ще й легкі. Я придбав комплект з двох панелей по 200 Вт. Одна панель має розміри квадрата стороною метр з гаком та вагу 4.5 кг. Таку вагу досить легко закріпити: навіть на спеціальний дюбель в пінопласт, або на монтажний клей. Або взагалі поставити на карниз, чи зачепити мотузкою за віконний профіль (це стане важливо нижче.)
🔌 Панелі підʼєднуються до павербанка EcoFlow кабелем, який потрібно придбати окремо; сам розʼєм стандартний, на станції Anker є такий самий. Щоб заряджати павербанк від панелі, більше нічого не потрібно. Тому така сонячна панель — гарний, повністю автономний спосіб підзарядити батарею — аби було сонце. Пристрій, що називається інвертором, потрібний тільки для підключення панелі до електромережі, в чому я сенсу не бачу, про що далі.
⚡ Тепер, яку потужність здатна видати вертикальна сонячна панель? На моєму південному боці у червні я побачив від 40 Вт вранці до 90 Вт вдень з теоретичних 200. Зазначу що потужність суттєво змінюється від невеликих змін кута нахилу; коли панель на 3 градуси нахилилась донизу, генерація впала на 20%!
💸 Але… як їх не крути, дві панелі згенерують не більше 1.5 кВт*год на день, і це за щедрою оцінкою. Тобто для не тільки для автономного живлення не вистачить, а й економії електроенергії вийде лише 200 грн на місяць — з новими тарифами.
🌞 Висновок мого експерименту: купувати мікроінвертор та монтувати панелі на постійне місце сенсу немає, але я радий мати їх як незалежний резерв (тому й важливо мати можливість легко їх повісити та зняти). Взагалі, це маленьке диво — бачити, як в павербанк тече енергія просто з сонця!