У Льоні сьогодні

Нотатки архітектора систем та майстра на всі руки.
Що я зробив, що з того вийшло, і що це все значить.
Детальніше в статті

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

23.05.2026

Код має значення — навіть коли його пише LLM

Та звісно ж, питання було риторичним. Тільки чому? Не тому же ж, що нам за нього платять, та страшно, що буде, коли LLM здатна видавати тисячі рядків коду на будь-яку примху. (Втім, сподіваюся, тобі насправді платять не за код, а за розуміння. Але про те не сьогодні.)

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

Я от тільки вчора згенерував з телеграм-каналу інформаційний сайт. За пів години. Код взагалі не бачив. Причому тут два шари згенерованого коду: спочатку скрипти для збору та впорядкування змісту, а потім вже власне сам сайт. Оце для мене чудовий — чарівний навіть — результат LLM.

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

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

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

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

Я не вірю, в широкому сенсі, що можна обмежити власну увагу планами та специфікаціями та залишити шар коду суто для ШІ. Не виключаю, що певним чином можна переконати LLM писати гарний код, але для цього потрібно принаймні її для того інструктувати. Та якщо у тебе виходить, напиши, будь ласка, i am trapped in an LLM prompt please send help.


22.05.2026

Чи має значення код, коли його пише LLM?

Знаєте трикутник “дешево, швидко, якісно: обери два”?

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

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

Але. Ніхто такі зміни не брав в продукт на віру! Яким би визнаним та досвідченим інженером ти не був, нормальна практика була почитати той код, та якщо він виявився погано структурованим та незрозумілим - попросити доробити, впорядкувати, і таке інше.

До речі. Раніше взагалі тільки круті інженери могли видавати код, що працює, з такою швидкістю. Тому, гадаю, раз LLM пише код ну настільки швидко, ми опиняємося під впливом гало-ефекту та високо ставимося до її розуміння теж. Втім, за досвідом, результат більше нагадує зграю мало оплачуваних, зате завзятих кодерів з прямим підключенням до Stack Overflow.

(От вам щеплення від гало-ефекту - ставтеся до агента не як до rockstar 100x developer, а як до найманої команди фрілансерів з біржі. Бо воно, бляха, так і є, якщо подумати.)


09.04.2026

LLM для дослідження

В моїй роботі найбільше користі від LLM навіть не в написанні коду, а в дослідженні та операціях.

Ну тобто код воно генерує — проте тут зміни кількісні, не якісні. Ну швидше генерує, ніж я пишу. Ну можна через це згенерувати більше коду, як всі ми знаємо. Але в цілому, цінність коду відʼємна, та впровадження LLM ніяк це не змінило.

Зате із дослідженням… Якщо дати агенту достатньо інструментів - CLI, API, MCP - байдуже — то він настільки вправно збирає дані та аналізує, як я по-людськи ніколи не зможу.

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

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

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

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

Звісно, агент не розуміє всіх подробиць та нюансів, але на то є я та є діалог. Я направляю дослідження, а агент робить. І так я отримую доступ до стількох джерел інформації, які до LLM й уявити не міг.


08.04.2026

Приготування їжі наперед

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

Отже, що я дізнався.

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

Звісно, також воно й швидше виходить. Хоча поки готуєш, так не виглядає! Бо замість звичних двох кесаділь доводиться готувати всі десять. Але то лише перше враження.

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

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

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

Отже… Якщо в тебе є улюблений рецепт приготування наперед — поділись, будь ласка. А якщо ні - раджу теж спробувати.


07.04.2026

15 хвилин про bike shedding

В мене, якщо не писати щодня, прокидається бажання писати серйозніше, але не зараз, а коли буде час. (Ніколи.) Тож спробую нову тактику: нехай пост займає не довше 15 хвилин; є що сказати — ділюся.

Bike Shedding - це відоме явище в плануванні, при якому певній неважливій частині приділяється неадекватно багато часу. Назва походить від байки, де під час планування електростанції комісія захопилася подробицями гаража для велосипедів. Чи щось таке.

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

От, проєктуєте ви JSON API. І все з ним зрозуміло. Але. Чи повертати поля результату на верхньому рівні {"foo": "bar"}, а може, загорнути в {"data": {"foo": "bar"}}, чи response, чи entity, чи все ж за назвою сутності {"fooser": {"foo": "bar"}}?

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

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

А от що дійсно важливо — то дбати про узгодженість в межах власного API.


13.03.2026

Як не бути рабом ШІ

Коли я починав користуватися Курсором, в оточенні агенту не запускався Ruby. Тому кожний тест чи іншу команду я власноруч запускав в терміналі, а потім копіював в чат. (Ну, ще раніше я ще й команди сам писав та обирав, що саме скопіювати.)

Звісно, потім я це полагодив. Проте, оскільки я остерігався дозволити агенту запускати все підряд, то сидів та погоджував кожний rspec. А ще нагадував агентам проганяти rubocop - зазвичай вже після того, як на CI впало.

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

Щоб такого уникнути, вдався до кількох мір. Ні, я досі не збираюся дозволяти агентам повну свободу. Натомість опановую allowlist. Це перелік команд, які дозволено запускати автоматично, без погодження. Цікаво, що allowlist містить префікси кожної команди, тож можна туди додати комбінації на кшталт bundle exec rspec.

В allowlist критично важливо запхати всі команди, які не потребують справжнього рішення з мого боку. От, якщо будемо видаляти базу в продакшні — тут я краще подивлюся. А тести, лінтер, дрібні команди збірки та організації по типу git - усі роблю дозволеними.

(До речі, саме Ruby в мене не працює в sandbox, бо доступу до зовнішніх файлів. Тож це не вихід)

Як виявилося, в Cursor цей allowlist сидить в базі SQLite, тож його не так легко відредагувати напряму. А хотілося саме напряму, тому навайбкодив скрипт, який переганяє allowlist з простого текстового переліку в налаштування.

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

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

Тепер я можу залишати Cursor на довгі проміжки часу та отримувати вагомі результати. (Звісно, це після фази планування — про яку теж можна окремо.)


12.03.2026

ШІ-вигоряння

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

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

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

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

Це веде до наступного пункту. Критично важливо дозволити агенту достатньо операцій, щоб він міг завершувати вагому частину роботи без втручання. Ну як мінімум — це запускати тести! Але про це я ще окремо напишу.


03.03.2026

Знову з робочим ноутбуком

За два з гаком роки робота за стаціонарним Mac Mini мені добряче набридла. Цього тижня, нарешті, приїхав на заміну новий Macbook Pro (той що 14" на M5, якщо вам таке цікаве.) Здивувався, наскільки я цьому щасливий.

Для початку, я знову можу працювати на дивані! Чи на кухні! (Чи в гамаку!) Такі дрібниці, але як воно приємно. Особливо для дзвінків та інших неконцентрованих задач.

Нагадаю, що Mac Mini я завів щоб краще розділяти роботу та життя. Не працює. Певно, якби в мене був окремий фізичний офіс, то був би ефект. А поки цей робочий комп стоїть за тим же ж столом, що й “домашній”, в тій же ж кімнаті — не відчуваєш різниці. Тільки ускладнення. Хоча, окремий ноутбук для роботи в мене залишається. Розділення контекстів таким чином — і корисно, і безпечно.

Також я знову можу принести ноутбук в кафе чи до коворкінгу. Якщо спосіб життя не дозволяє з 9 до 5 сидіти за одним столом — то стаціонарне робоче місце тільки обтяжує. Отже, не з того почав! Хоча й розклад дня в мене у 2023 був більш спокійний.

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

З плюсів Mac Mini - хіба що його компактність. Тут питань нема. (Особливо з новішими моделями! Вони ж як Raspberry Pi!) А якщо хотіли огляду нового макбуку — здивував своєю товщиною, бо я вже звик до Air, а тут такий бутузик. Навіть значно товще за моделі з початку 2010-х. А так ну макбук та й макбук.


28.02.2026

Рівно два роки тому (навіть не знаю, як такі збіги відбуваються! магія!) я писав про керування водяним охолодженням — а саме, програму FanControl для Windows.

Досі нею користуюся, програма гарна. Я її запускаю як сервіс за допомогою іншої чудової програми - Non-Sucking Service Manager (NSSM). NSSM вміє будь-яку програму зробити системним сервісом — а значить, вона не буде маячити на робочому столі та буде надійно запускатися та перезапускатися.

От тільки змінювати конфігурацію такої загорнутої FanControl стало незручно. Треба зупинити сервіс, відкрити у звичайному режимі, відредагувати, закрити, запустити сервіс наново… А ще вона ж не під головним користувачем системи, а під адміністраторським. А Windows не дає одночасно зайти двома користувачами, тож потреба все зупинити перетворює навіть тривіальну зміну в справу хвилин на 20.

Звучить як ідеальна задача для агентів! В мене вже налаштований SSH, то й кажу “от комп, на ньому FanControl, збільш стартову швидкість помпи на 3%.” Хотів перевірити, чи воно зрозуміє стільки деталей.

З SSH проблем ніяких. Чудово, що агент розуміє командний рядок Windows та PowerShell значно краще за мене. (Окрім: SSH не мав authorized_keys. А для того, щоб агент зробив все, потрібний безпарольний доступ. та виправлення цього навіть з агентом зайняло значно більше часу, ніж решта справи. Як завжди. Але принаймні це разове покращення.)

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

Місце, яке треба змінити, агент теж знайшов серед багатьох профілів вентиляторів. Конфігурація у JSON, зате потрібний параметр є однією з двох координат ламаної функції на кшталт ["50,35", "70,100"] - що значить, до 50 градусів увімкнути помпу на 35 відсотків, до 70 поступово збільшувати до 100, та там і тримати. От, агент зрозумів, що перше значення потрібно замінити на 50,38. Ну, за тим він почав вигадувати скрипти PowerShell для часткової заміни рядка в файлі, що ніяк не виходило. Аж поки я не сказав “та скопіюй вже файл на нашу машину, виправ та поверни на місце”.

Ну й з перезапуском сервісу все зовсім просто та прямолінійно.

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


22.02.2026

Zigbee: дійсно гарно

Коли я майже рік тому писав про Zigbee - то не мав ніякого досвіду. Відтоді в моєму розумному будинку зʼявився й цей протокол, тож ділюся враженнями.

По-перше, якщо в тебе вже є HomeAssistant, то підтримка Zigbee додається через USB-адаптер - наприклад, Sonoff ZBDongle-E. А не окремою коробочкою. Це відразу набагато краще коробочки, бо звʼязок HomeAssistant з пристроями Zigbee є безпосереднім та не покладається на Wi-Fi чи навіть Ethernet.

(Бо, якщо подумати, як Wi-Fi, так і всі протоколи з коробочкою-шлюзом ходять через роутер. Це і повільніше, і додає точку відмови.)

Підключення пристроїв безболісне та нагадує Bluetooth, тільки без кодів підтверджень. Відбувається прямо з HomeAssistant. Далі пристрій стає частиною мережі. “Мережа”, до речі, визначається ключами доступу — які дуже важливо зберегти. В мене один з пристроїв під навісною стелею, не хотілося б туди лазити, щоб привʼязувати його наново.

Також приємною несподіванкою було те, що мої лампи Philips Hue підтримують Zigbee. (І навіщо я той міст Philips Hue Bridge купував?) От прямо береш їх та спарюєш із HomeAssistant. Так само і пульти до тих ламп. Окрім простоти, воно стало надійніше.

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

Так що якщо ти вагаєшся, раджу вкластися один раз в цю екосистему — воно того варте.