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

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

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

17.03.2023

Що робити з invalid byte sequence in UTF-8

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

UTF-8 класне кодування; для латиниці воно дуже компактне, але при цьому дозволяє використати більш мільйона різних символів, що легко покриває всі мови світу, а також емоджі, системні символи та все інше. Але недоліки UTF-8 - це змінна довжина символу та те, що не кожна послідовність байтів є дійсним рядком UTF-8. Перше заважає, коли треба порахувати “наочну” довжину рядка, або розбити його за символами. А про друге доводиться деколи згадувати. Класична дірява абстракція!

Якби будь-який рядок був дійсним UTF-8, то можна було б хоча б ігнорувати кодування та обробляти всі рядки в UTF-8. Для випадків, де не треба інтерпретувати зміст рядка, цього цілком достатньо — ну є незрозумілі символи та і є. Але ж ні — деякі рядки мають недійсні послідовності символів, та їх не можна інтерпретувати як рядки UTF-8 в принципі, принаймні, не без втрати цих недійсних послідовностей. Тому стандартні бібліотеки, коли натраплять на недійсний символ, не проковтнуть його, а викличуть помилку — в Ruby це класично nvalid byte sequence in UTF-8.

Ми стикнулись з цією проблемою при обробці DNS записів; вони не мають визначеного за стандартом кодування. Ясно, що в більшості випадків DNS містить рядки ASCII, який фактично є підмножиною UTF-8, тому ми їх обробляли як UTF-8 і все було добре. Проте знаходяться записи, що викликають помилку кодування. Тому доводиться всі рядки приводити до UTF-8 перед обробкою. В Ruby для цього є метод encode: string.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: '�'). Тільки так можна “вичистити” рядок від недійсних символів. Є ще метод force_encoding, але він нам не підходить — бо він не перетворює рядок, а тільки встановлює кодування. force_encoding корисний, коли відомо, що рядок не в UTF-8, а в іншому кодуванні.


16.03.2023

Мої трохи контроверсійні погляди на приготування кави вдома

Кава, кава, кава. Не знаю, як так вийшло, що за двісті з лишком постів я ще писав про каву, бо приготування кави — то моє найтриваліше хобі. Сьогодні відкрив для себе сервіс Спеш — це підписка на каву з підбором до смаку, яка починається з чотирьох примірників кави без маркування, тож можна занулити свої преференції та дійсно звернути увагу на смак, а не бренд чи назву. Як на мене, ідея чудова, якщо хочеш спробувати, то з моїм промокодом 7832 знижка 10%.

Але взагалі, хотів поділитися своїми трохи контроверсійними поглядами на приготування кави вдома.

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

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

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


15.03.2023

Як не поламати продакшн для всіх

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

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

Запуск інтеграційних тестів перед випуском нового коду теж не допомагає; це знайде регресії, але ж автоматизоване тестування теж обмежено передбачуваними сценаріями.

Так званий blue-green деплой допоможе відкотити зміни та не випускати зовсім поламаний код. Але нічого не зробить для багів, яки не впливають на деплой, тобто для більшості багів.

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

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

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


14.03.2023

Мій підхід до безперебійного перенесення даних

За останній час довелося декілька разів стикатися з потребою перенесення даних з одного місця на інше без перебоїв сервісу. Наприклад, вирішили поміняти базу для зберігання подій. Розробив для себе підхід, в якому впевнений.


13.03.2023

Неявні перешкоди в розробці

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

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


12.03.2023

Порівняння крісел Steelcase Gesture та IKEA Markus

Нещодавно купив собі робоче крісло Steelcase Gesture. Це одне з найбільш шанованих крісел, та, відповідно, коштує купу грошей. Вагався з цим, без перебільшень, багато років. Хочу зробити огляд, порівнявши його з IKEA Markus - кріслом, на якому сидів багато років.

Декілька добрих слів про Markus. Це, на мою думку, крісло №1 з адекватної цінової категорії. Воно надійне — не поламалось піді мною років за сім, а я важу 90 кг. Воно легкодоступне — в Україні можна без проблем купити на Home Club). Воно точно краще, ніж крісла з JYSK або з місцевих меблевих магазинів — хоча б по надійності. Тож якщо потрібне хороше крісло, раджу саме IKEA Markus.

Чого мені в ньому не вистачало, це зручних підлокітників. По-перше, для мене вони були занизькі, та руки все одно висіли. По-друге, винесені надто вперед, через що крісло не заїжджало під стіл, та я не міг з прямою спиною дотягнутись до клавіатури. Тож, мабуть, не дарма я обрав крісло, яке славиться саме досконалими підлокітниками - Steelcase Gesture.

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

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

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


11.03.2023

Прості середовища для написання ігор

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

Це наштовхнуло мене на думку: коли я вчився програмувати - а ігри були одним з того що я робив на початку - то моїм “гейм мейкером” був MS DOS та Borland Pascal. Простота цього середовища дозволила навіть без досвіду робити доволі складні проєкти. Причому це було в 2001 році, коли час DOS давно минув, та всі вже грали в Counter Strike. Але якби мені в той час дали OpenGL або DirectX, навряд чи я опанував би їх так же ж, як і SetColor або LineTo з графічної бібліотеки Borland Pascal.

А зараз, коли роблять гру на кшталт Undertale, то беруть Game Maker. Хоча мені особисто хотілося б чогось це простішого, але орієнтованого на програмістів. От ще давно цікавить PICO-8 - це “віртуальна консоль”, тобто фактично середовище програмування - суворо обмежене в можливостях, та в цьому схоже на мої часи з Паскалем. До речі, пишуть для PICO-8 на Lua - про цю мову варто знати, бо вона розроблена для вбудовування в інші програми - компактна та безпечна.


10.03.2023

Як всиновлюють бібліотеки

Коли ми почали розробляти бібліотеки для інтеграції з нашим продуктом, виявилося, що наше брендове імʼя було зайняте. Я зголосився домовитись про передачу прав, та тому у нас зʼявився гем mailtrap та пакет NPM mailtrap. Замість того, щоб це були якісь mailtrap-sdk. Що в ізоляції, може, й прийнятне, але поруч з обманливим пакетом mailtrap створюватиме зайве непорозуміння.

Як це робиться. Знаходиш контакти автора, та пишеш листа. Звісно, для цього пакет має бути без активної підтримки. В нашому випадку минулий гем був з 2007 року та, здається, містив посилання на Rubyforge (в кого досвід по рубі 15 років, той памʼятає.) NPM-пакет був свіжіший, але все одно заархівований автором 2 роки тому. Втім, для пакета я додав у README посилання про те, що трапилось та де знайти старі версії. Загалом, для передачі прав достатньо було ввічливо попросити.

А от з Python все цікавіше, бо є цілий протокол передачі прав PEP-541. (Для мене це якийсь новий рівень бюрократії.) Треба зробити пул-реквест в особливий репозиторій за всіма правилами. Іронія в тому, що потім 3 тижні ніхто з команди на нього не відповідає. Непогана ілюстрація до принципу Agile “люди понад процеси” - замість довжелезної документації краще б була відповідальна команда підтримки. (Можна, звісно, домовитись з автором напряму.)

Почесна згадка - Go, бо там кожний пакет має URL. Тож конфліктів імен не може виникнути, та коли будемо робити свій, то це буде просто github.com/railsware/maltrap-go.


09.03.2023

Merlin Bird ID - Pokemon Go, але для птахів

🦜 Знаєте Pokemon Go? Так от, минулого року я дізнався про додаток, який вміє впізнавати птахів за співом - Merlin Bird ID. Для мене цей додаток перетворився на “реальну” версію Pokemon Go: почув спів незнайомої пташки, я вмикав розпізнання співу, та, якщо пощастило, “ловив” птаха у свій каталог. Розпізнання працює приблизно як з музикою, тобто будується спектрограма наявного звуку, та порівнюється з базою даних співів. Я ні в якому разі не орнітолог, та й взагалі, на початку мої знання обмежувались банальними горобцями та сороками. Але, Merlin працює так гарно, що за минулий сезон я дізнався чимало видів пернатої фауни.

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

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

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


08.03.2023

Відтворення стану бази для тестів з FactoryBot.

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

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

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

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

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