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

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

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

02.03.2024

Любов до таблиць

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

Наприклад, потрібно мені було нещодавно залучити модуль golang.org/x/text/encoding для перекладу тексту з одного кодування в інше. Але ось в чому справа — цей модуль немає абстракції, де кодування визначається назвою. Натомість там є низка реалізацій типу Decoder для різних кодувань; виходить, що ми маємо наперед знати, яку саме Реалізацію взяти. А я знаю тільки назву кодування.

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

…Знаходжу в інтернеті гарний документ, близький до стандартного, з переліком кодувань та їх можливих назв (бо у назв є синоніми: наприклад, ISO-8859-1 та latin1.) Тут включається любов до таблиць, я забуваю про пріоритети та починаю перекладати документ в код. Весь. Хоча ні — цього разу помітив та зупинився, звідки й пост.

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

Так само мене спокушають переклади коду з мови на мову, інтеграції з API, специфікації форматів файлів… все, де можна відключити мозок та писати код рядок за рядком.


01.03.2024

Sync та Async: покрокове програмування

Натрапив на цікаве питання: чому ми кажемо синхронний код на той, що виконується послідовно, та асинхронний — якщо рівночасно? Ніби ж навпаки, “синхронно” має значити “в один час”, тобто виклик, наприклад, Promise простою мовою скоріше “синхронний” ніж “асинхронний”..? Спробую пояснити.

Може, я переграв у Baldur’s Gate 3, але виконання рівночасних програм нагадує покрокову гру. Програма складається з послідовних блоків, які виконуються по черзі. (Принаймні, абстракція така — що там насправді відбувається, нам невідомо — процесор, ОС, та середовище виконання всі накладають свої нюанси.)

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

…Так само в покроковій грі, зміст кроку відбувається послідовно, але без обігу реального часу поза діями поточного гравця, тобто синхронно. Має сенс?


29.02.2024

Майже порожній аркуш

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

Помітив, що існує й друга, більш підступна проблема. В деяких інтерфейсах одного чи двох початкових записів не вистачає для повноцінної роботи. Наприклад, я зіткнувся з цим у WeightPlot: щоб побудувати графік ваги, потрібно хоч тиждень даних. Але що показувати користувачу весь цей перший тиждень?

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

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

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


28.02.2024

Водяне охолодження — керування

🎛️ Як я згадував в пості про компоненти, в системи охолодження немає власного керування. Всі активні компоненти — помпа та вентилятори на радіаторі — керуються звичайним PWM з самого компʼютера.

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

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

Щоб розвʼязати цю головоломку, знайшов надзвичайну програму FanControl. Вона вміє встановити швидкість вентиляторів як функцію комбінації датчиків. Замість простої кривої, як в BIOS, тут справжній ЦОС. Єдине, що FanControl запускається вже з Windows, а до того в BIOS виставлено вмикати помпу на безпечно високу швидкість.

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


27.02.2024

Водяне охолодження — трубки

🚰 Якщо всі вище згадані компоненти відносно взаємозамінні у своєму класі та залишається тільки обрати ті, що подобаються, то на трубки залишається 80% архітектури.

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

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

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

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


26.02.2024

embed.FS - включення файлів у програму на Go

Одна з моїх улюблених та недооцінених можливостей Go - це модуль embed. Завдяки йому можна скомпілювати в програму не тільки окремі файли, а й цілі директорії. Виглядає це приблизно так:

//go:embed resources/*.html resources/*.css
var resources embed.FS

index, err := resource.ReadFile("index.html")

У embed є дві форми: окремий файл та директорія. Файл в програмі стає звичайним рядком: дуже зручно. А директорія перетворюється на тип embed.FS, який сумісний з модулем io та тому підходить для багатьох споживачів — наприклад, можна роздавати ці файли по HTTP за допомогою http.FileServerFS.

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


25.02.2024

Водяне охолодження — з чого воно складається?

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

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


24.02.2024

Водяне охолодження ПК — що воно таке?

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

Мій ігровий ПК стоїть в зачиненій шафці під телевізором — в режимі HTPC - проте це потужний ігровий компʼютер. З самого початку йому не вистачало охолодження. Скільки вентиляторів не додавай в корпус компʼютера, шафка все одно перетворювалась на духовку. Можна було б придумати повітрообмінник з шафи назовні, але, після довгих роздумів, я все ж вирішив піти з водяною системою.

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

На мою думку, водяне охолодження варто своїх коштів… але кошти підуть немаленькі. Історій про фітинги, які протікають, трубки, які розкладаються, і так далі, достатньо, щоб зрозуміти, що заощаджувати не варто. Навпаки, компоненти від надійних виробників служать довго та абсолютно без проблем. Орієнтовно, я б закладав бюджет на систему у $500 - $1000.

Окрім витрат, доведеться мати базово-просунуті навички в цілій низці галузей. Розбирати компʼютер — очевидно. Але також, зняти радіатор з відеокарти (це зовсім не така типова задача, як з процесора!). Зібрати “сантехніку” та перевірити на протікання. З зовнішньою системою — подовжувати кабелі для вентиляторів. Вішати все це на стіну. А потім ще й налаштувати програмну частину, щоб керувати швидкістю помпи та вентиляторів (бо так, є ще й помпа зі своєю фізикою).

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


23.02.2024

10 днів зі стохастичним таймтрекером

Вже трохи більше як тиждень користуюся своїм таймтрекером (який паралельно дописую). Коли виправив надсилання сповіщень, то, фактично, MVP вже був готовий. Нагадаю, що на відміну від типового трекера, цей — стохастичний — самостійно опитує (“пінгує”) тебе у випадкові моменти часу — так само як це роблять статистичні профайлери коду. В середньому, раз на 45 хвилин, але на практиці бачив і раз в 3 хвилини, і 3 години без пінгів.

Поки експеримент мені подобається, далі буде.


22.02.2024

Проблема декількох версій залежностей

Є така проблемка в проєктах на Go, що у транзитивних залежностях може бути декілька версій однієї бібліотеки. Ну, наприклад, github.com/redis/go-redis/v9 та github.com/go-redis/redis/v8. Окрім того, що це збільшує розмір програми (та хто його лічить?) - є й ризик помилки.

(До речі, в Go предивна система версій модулів. Взагалі в Go модуль це тека. Ніякої “збірки” у .gem, .jar, чи навіть .zip немає. Назва модуля дорівнює його URL в Git. А наступна несумісна версія модуля створюється… не в теці v2, як може це здатись, а у гілці з назвою v2. При цьому назва модуля залишається такою самою. Мені доводилося це робити з нашою бібліотекою go-global, коли вона переїхала з AWS SDK v1 на AWS SDK v2, який цій системі не слідує.)

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

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

Така сама тільки гірше проблема в JavaScript - бо там типи не допомагають, а залежностей експоненційно більше.