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

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

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

11.04.2025

Протоколи розумного будинку: Wi-Fi

Почнемо мінісерію. Я багато чого тут вивчаю вперше, тож якщо у вас краща інформація — виправляйте! :) Мені, головне, для себе хочеться розуміти, в чому різниця. Бо різниця абсолютно є, і не тільки в назві. Тут як з меблями: чому є стільки пласких меблів? якщо в мене вже є стіл, чи потрібно мені ще ліжко? та й взагалі, якщо вже є підлога, хіба це не найефективніша поверхня?

Давайте про Wi-Fi - це наша підлога, бо вона у всіх є. Та це наче головна перевага Wi-Fi - достатньо роутера, щоб розпочати свій розумний будинок. Також це найшвидший з протоколів, з великим відривом, тому, скажімо, вебкамера напевно буде з вайфаєм. Також Wi-Fi можна розширювати — хоча це й не ідеально працює, але технічно можна покрити будь-яку територію, особливо якщо є можливість підʼєднати розширювач за Ethernet. Та це ще одна перевага - Wi-Fi є носієм для знайомого стеку протоколів IP, тому доступ до пристроїв може бути дуже простим (як-от нещодавно згадана вебпанель керування прямо на пилососі).

Головний конструктивний недолік Wi-Fi - це високе споживання енергії. Бо клієнти Wi-Fi завжди повинні бути “на звʼязку”. Через це практично будь-який пристрій повинен бути підʼєднаний до електрики (або часто заряджатися.) З цим, звісно, можна жити, тільки пристроїв без дроту не знайдеш.

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

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


10.04.2025

Коли та як документувати код?

Потрапив мені в пазури чужий проєкт, на якому документація коду (тобто коментарі) зроблена так, що я позаздрив.

Чому? Бо кожний клас та кожний атрибут був пояснений влучно, але не багатослівно. Рівно стільки, щоб зрозуміти, що він робить. Всупереч цьому, зазвичай я бачу приблизно нуль документації, а коли її все ж багато, то вона скочується в тавтології на кшталт “ID це ідентифікатор продукту”.

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

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

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

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


09.04.2025

4 способи пришвидшити збірку CI на 10 секунд

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

Зменшити кеш. Ні, серйозно, якщо у вас 500 Мб зайвого кешу, то достатньо його прибрати та збірка стане швидшою. Де взяти 500 Мб зайвого кешу? Наприклад, в тимчасових артефактах гему grpc (про що можна окремо розповідати.)

Навпаки, додати кеш Ну от кешуєте ви пакети, які завантажив yarn. З них можна повністю відтворити node_modules. Але то буде довго! Швидше самі node_modules теж закешувати. Відновлення кешу не моментальне, але швидше за yarn install.

Не робити зайвих анотацій Ясно, перед тестами потрібно промігрувати базу. А після міграцій автоматично запускається анотація моделей. Зручно локально. Абсолютно зайве на CI. Вимикаємо анотації — та замість 21 секунди міграції проходять за 11.

Можна спитати — а кому ті 10 секунд важливі? Самі собою, згодний, нікому. Але якщо 6 разів по 10 секунд - то це вже хвилина. А коли це хвилина паралельної збірки в 10 потоків - то вже 10 хвилин оплачуваного часу. А також одна хвилина, яку ніякою кількістю потоків не пришвидшиш. Так що інколи варто й на 10 секунд пришвидшувати.


08.04.2025

Valetudo - відв'язання пилососа від інтернету

Роботи-пилососи — це революційний винахід. Але мені зовсім не хотілося мати в хаті вебкамеру на колесах. На щастя, існує аматорський проєкт Valetudo, який для деяких моделей пилососів здатний прибрати привʼязку до хмари — так, що навіть офіційного застосунку не доведеться встановлювати.

Що воно таке? Дві окремі зміни. Спочатку рут, тобто відкриття адміністративного доступу. Взагалі пилосос то маленький компʼютер з Linux, тільки ще й на колесах. А потім прямо на пилосос встановлюється Valetudo - сервер, який заміняє хмару. Все забезпечення пилососа залишається без змін. Тобто тут не буде такої ситуації, коли встановлюєш деяку ОС та залишаєшся, наприклад, без блютузу. А от в UI, певно, можуть бути відставання, хоча на мій недосвідчений погляд все добре. Також, зауважу, для Valetudo не потрібно ніякого додаткового домашнього сервера, бо пилосос стає сам сервером — як для себе, так і для керування. 🤯

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

Далі за інструкцією буде потрібний ноутбук з Debian. В мене знайшлася на ігровій машині Ubuntu другою системою. Завелося і з нею. Потім такі кроки лячні… я, мабуть, останній раз таке робив, коли прошивав книжки на свій Siemens C55. Лячні тим, що пилосос в “сервісному режимі” вимикається через пару хвилин, тому всі операції потрібно робити швидко, а не то пилосос стане цеглиною. 🧱

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

Коли вже є рут, то до пилососа можна підʼєднатись по SSH, та градус напруги спадає. Але Valetudo на пилососі ще нема. Далі інструкція каже підʼєднатися до Wi-Fi пилососа… та я розумію, що в мене машина без вайфаю. А там ще залишилося використати якийсь міст, який теж є тільки для Linux. (Та ще для Windows, але в мене вайфай тільки під macOS.) На щастя, міст тільки віддає файл по HTTP, та класична python -m http.server 7777 чудово покрила цю потребу.

Так що останнім кроком підʼєднуюся по Wi-Fi, потім SSH, завантажую valetudo, вмикаю автозапуск, перезавантажую пилосос (reboot), та — успіх — панель керування зʼявляється в локальній мережі! Далі — все прозаїчніше. Або навпаки, починається сама магія! ✨


07.04.2025

Покращення split_tests

Поки я згадав про свою утиліту для розподілу тестових пакетів split_tests, захотілося її оптимізувати — тобто зробити так, щоб вона розділяла тести на комплекти найрівнішої тривалості.

На початку вона використовувала жадібний алгоритм. Сортуєш файли за зменшенням часу. А потім береш по черзі та додаєш до найменшого досі комплекту.

Це чудово, але всі знають, що жадібні алгоритми неефективні. Дослідив цю тему. Виявилося, що задача має назву планування ідентичних машин та вже має декілька розвʼязків. (Хоча і є NP-складною.)

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

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

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

Втім, новий алгоритм причешу та опублікую: може, в когось інші обставини.


06.04.2025

Чим покращити свій досвід роботи з SQL?

Коли вже довелося писати SQL, який в один екран більше не влазить, не все втрачено. Є підходи до того, щоб його взяти під контроль та, наприклад, забезпечити підтримку в майбутньому замість переписування.


05.04.2025

Чи потрібний SQL, якщо є ORM?

Потрапила на очі фраза “хто ж пише SQL, коли вже н-цять років існують ORM?” Хотілося прокоментувати. Тут є цікавий розподіл.

Головна міць реляційних баз даних — це, власне, ота реляційна модель, яку ніхто (включаючи мене) досконало не розуміє. (Пропоную задати собі питання — про яке відношення йдеться?) Але суть в тому, що ми можемо обʼєднувати розрізнені факти, щоб отримати сукупний результат.

Наразі існує достатньо нереляційних баз, щоб побачити, що ця можливість не є універсальною. От в OpenSearch все, що ми можемо — це шукати документи за критеріями та агрегувати. Все інше — дорого (та реалізується тим самим пошуком.) У CoreData немає COUNT. В DynamoDB взагалі кожний запит треба задумати наперед.

А у реляційній базі всі дані доступні для поєднання. Роби з ними що хочеш. Причому поєднання ще й буде ефективним — це і є основна пропозиція будь-якої реляційної бази. Та хто працює з аналітикою, бачив ті кілометрові запити на SQL, які генерують звіт з двадцяти таблиць з усіх околиць компанії. (Користуюся нагодою прорекламувати наш продукт Coupler, який допомагає зібрати ті дані з розрізнених джерел.)

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

При тому ж для розробки типових застосунків складних запитів не потрібно. Ми маємо справу або з окремими записами, або з колекціями записів, та збереження стану — далеко не найцікавіше місце логіки. Тому я радий, що є ORM, та вони дозволяють нам робити запити з нашої зручної мови програмування загального призначення. ORM - для застосунків, SQL - для звітів та відношень. А головне, одне іншому не заважає!


04.04.2025

Прискорення тестів на CI

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

Неприємність тут в тому, що не вийде прискорити тести простим киданням грошей на більші машини. Вигода від того буде обмежена. (Хоча якщо тестам не вистачає, скажімо, памʼяті, то збільшення машини точно буде вартим.)

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

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

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

Але зрештою, якщо налаштувати split_tests в режимі JUnit, то виходить дуже непогано! Рекомендую.


03.04.2025

Як я писав екзамени

Я ніколи не був дуже старанним учнем. Інтересів в мене завжди було багато, але рідко вони перетиналися зі шкільними предметами. Зате я був начитаний та загально обізнаний. Тому багато, якщо не більшість, екзаменів я складав з вигаданими відповідями. 💭

Як воно працює: спочатку потрібно взагалі щось знати, для того достатньо прослухати достатньо лекцій і ти вже принаймні чув, якою мовою тут розмовляють та на які аспекти звертають увагу. Плюс, корисно знати загальні речі — може, по видах тварин савани ти не готувався, але багато дивився “У світі тварин”. 🦁

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

Звісно, багато залежить від предмета. З літератури, якщо ти хоч приблизно знаєш зміст твору, залишається тільки красно додати подробиць. Біологія — теж нормально. Історія — вже не все вийде, бо дати потрібно знати точно. Ну, а з математикою можна навіть не починати — тут мусиш готуватися. 📏

Ще я навчився, наскільки важливий впевнений тон. Якщо вдасться у відповіді вдати вигляду, що ти знаєш тему — оцінка вже в кишені, навіть коли фактів та конкретики було мало. Особливо, коли ти ще й вмієш розмовляти мовою підручника та викладача — бо тоді ж точно все знаєш, еге ж? Просто може питання було поставлено не точно, от і відповідь пішла трохи не в той бік. 😉

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


02.04.2025

Docker та стан у файлах

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

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

Якщо вже сервіс розрахований на зберігання стану в файлах, я просто не знаю гарного рішення для запуску його в Docker. Окрім баз даних, це стосується, наприклад, WordPress, який погано почувається без можливості редагування власних файлів. Стан у файлах не є частиною застосунку 12 факторів. (Звісно, реальність така, що десь на файлах сидить база даних.)

Це не те щоб провина Docker - очевидно, що дві копії PostgreSQL в принципі не можна запустити одночасно з однієї директорії. Але з традиційною моделлю розгортування такої потреби й не виникає. (Щоправда, способу оновити PostgreSQL без простою я теж не знаю.)