Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
30.05.2023
Пакування інформації в зашифрований пакет найменшої довжини
Турбує мене ця тема. Ну, наприклад, є невеличкий набір параметрів (на кшталт JWT). Потрібно зробити з них якнайкоротший зашифрований рядок. Може, для посилання, може, для QR-коду, і так далі. Що з цим можна зробити?
-
Кодування інформації. Логічно обрати формат, в якому структура даних не кодується разом з даними, а міститься в програмі, яка кодує та декодує. (Власне, так робить будь-який формат файлів.) Це значить, що точно не JSON та навіть не msgpack. Мені здається, що найкраще для такої задачі підходить формат Cap’n’Proto - він є логічною еволюцією формату protobuf. Тут структура пакетів задається схемою.
-
Насправді, можна обрати й msgpack, якщо кодувати не структуру, а масив. Масив — найбільш очевидна “компактна” структура даних. Проте тоді доведеться вручну збирати та розбирати ці масиви, а згодом ще й вручну версіонувати. Тож якщо є доступ до Cap’n’Proto або protobuf, то сенсу в цьому мало.
-
Компресія може згодитись й для маленьких рядків. Компресія GZIP будує словник з послідовностей, які повторюються. Тому якщо в рядках присутні повторення, то є можливість заощадити. Але є проблема — сам словник теж має бути включений у пакет. Тому важко досягти корисної компресії на маленьких рядках. Тут є корисний трюк. Замість того, щоб будувати словник з нуля для кожного пакету, можна підготувати спільний словник та тримати його окремо в коді. Це допоможе, якщо деякі фрази повторюються у більшості пакетів. Такий підхід, між іншим, використовує Cloudflare.
-
Шифрування. Тут не уникнути збільшення пакета, бо окрім даних, треба включити вектор ініціалізації та підпис. Підпис потрібний для того, щоб пакет не можна було підробити — а також щоб помітити, якщо він зіпсується Якщо я не помиляюся, то треба брати симетричне шифрування з аутентифікацією
AES-GCM, та не вигадувати нічого свого. -
Кодування двійкового рядка в текст. Зашифрований рядок буде двійковим. Зазвичай його треба перетворити на текст. Тут можна вже обрати те, що підходить під потреби. Є Base64. Є Base58. Є Base85. Все залежить від того, який набір символів прийнятний. В ідеалі — просто залишити у двійковому вигляді.
29.05.2023
Як апгрейдиться React Native
Сьогодні апгрейдив React Native, бо стара версія (ну як — стара? минулого року) відмовилася компілюватися на XCode 14.3. До речі, гарна метрика зрілості технології — наскільки довго старі версії продовжують працювати без підтримки.
Кожному, хто працює з RN, обовʼязково треба знати про React Native Upgrade Helper. Це утиліта, яка порівнює код демонстраційного додатка з різних версій React Native. Вона незамінна для впровадження базових змін в коді, від нових версій бібліотек до коментарів з розʼясненнями. (Однак редагувати ваш код доведеться вручну.)
Цього разу після заміни версій пакетів yarn install не зміг завершити роботу за браком памʼяті. Збільшення виділеної йому памʼяті (корисна команда: env NODE_OPTIONS="--max-old-space-size=8192" yarn) тільки робило агонію довше, але так само не призводило до успіху.
Тому спробував оновлювати поступово, одна мінорна версія за іншою. Це допомогло. Для останньої версії також довелося оновлювати по одному пакету за раз. Але, в решті решт, все оновилось.
Потім ще цікаві ручні оновлення React-Native-Navigation та React-Native-Firebase; обидві бібліотеки мають глибоку інтеграцію в додаток та тому потребують редагування коду на Objective C.
Окрім банальної сумісності з поточною версією XCode, я також отримав так звану “нову архітектуру”, хоча поки не знаю, що це дає на практиці. Як бачите, React Native ще серйозно розвивається. Це з одного боку добре — бо проєкт є успішним, попри те що багато людей його зневажають. А з іншого боку — про стабільність можна тільки мріяти.
28.05.2023
Cyberpunk 2077 - гра наступного покоління, яку підвів її сюжет
Напевно, те, що більшість знає про Cyberpunk 2077 - останню гру від польської компанії CD Projekt Red, творців Відьмака та GOG - це те, що вона була сповнена багів та погано йшла на старих системах, в першу чергу, на Playstation 4. Що прикро, бо насправді гра вийшла варта уваги.
Я тільки-но пройшов цю гру, та хочу поділитися враженнями після 100+ годин з нею. Щодо швидкодії, то здається, вони багато виправили, хоча в мене на ПК проблем і з початку не було.
Що є видатного в Cyberpunk 2077:
-
Величезний, щільний світ. Він поділений на райони, які кожний мають свій “вайб”, тож валасатися вулицями від завдання до завдання приємно. На жаль, вони пішли з моделлю GTA, тобто місто заповнене випадковими людьми та машинами, та не має стійкого стану. Проте я був вражений, коли ближче до кінця гри натрапив на знайоме місце — колись давно я вичищав базу стервʼятників, а тепер там було мирне поселення. Дрібниця, але хоч щось зберігається. Також, як і в GTA, заходити можна тільки в окремі будинки.
-
Дійсно разюча графіка. При такому масштабі світу зробити ще й трасування променів — дуже круто. Освітлення створює мальовничі пейзажі, як вдень, так і вночі. Якщо не прискіпуватися до кожного багу, то загальне враження чудове. Треба розуміти, що це не просто три квартали якогось Deus Ex, а ціле місто.
-
Декілька можливих стилів гри, з якими цікаво експериментувати та знаходити комбінації. Я починав гру зі скритності та хакерства, потім спробував бути снайпером, а на кінець відкрив навичку “Cold blood”, яка робить можливим “run and gun”. До того, багато різновидів зброї та спорядження. Та, головне, гра збалансована так, що робити все “в лоб” неприємно складно, тому відточування власного стилю гри має сенс.
Що поганого:
-
Найгірше то сюжет та все що з ним повʼязано. Світ Cyberpunk 2077, як і весь жанр кіберпанк, несерйозний. Ніхто не аналізує, що значить для людини відпиляти всі кінцівки та замінити на залізні. Або як живе місто, де вбивство — це абсолютно нормальна, легітимізована річ. Це домовленості світу, та ми їх приймаємо, як є. Але ж сюжет Cyberpunk 2077 максимально мелодраматичний. Герої поводяться, як у Шекспіра. Головному герою в рота пхаються фрази, які несумісні з обраним стилем гри. Та якщо з Відьмаком це проходить, бо Геральт — вже зафіксована особистість, то тут повний людонаративний дисонанс. Моральних виборів у грі майже немає, а геймплей обертається навколо вбивства — звичайних, хоч, може, й морально сірих, людей. При цьому наш герой виставляється протилежністю анархіста, якого грає Кіану Рівз.
-
Решта завдань недостатньо повʼязані між собою. Окрім купки сюжетних ліній, решта це просто окремі “рівні гри”. Прийшов на локацію — виконав — отримав гроші. Тому немає відчуття місця. Я б хотів, щоб у світі були хаби, куди ти приходиш багато разів, та з якими можна поріднитися. Бо я помітив, що за 100 годин гри в мене майже не має місць, які я можу знайти на карті та повернутись туди. Світ яскравий та різноманітний — але в ньому немає за що зачепитись. `
-
Система нагород та предметів не цікава. Майже все, що ти знайдеш у світі — це зброя та одяг. Але не потрібне ані те, ані те. Зброя — випадкова варіація невеликої кількості моделей, так що рідко знайдеш щось новеньке для себе. Одяг — його безліч, але зовнішній вигляд мало що значить у грі від першого лиця. Ефектів одягу, окрім броні, майже немає. Тож виходить, що окрім унікальної зброї час від часу, грі немає чим нас нагородити.
Чи можу я порадити Cyberpunk 2077 сьогодні? Так, якщо ти будеш грати на ПК, та тебе цікавить механічна сторона. Тоді тут є з чим погратись. А от якщо хочеться “Відьмака з кіберімплантантами”, то такого не буде.
27.05.2023
Hugo як фреймворк для фронтенду
При створенні поста про похід довелося випробувати вбудовані в Hugo інструменти для компіляції JavaScript.
Висновок такий, що Hugo здатний замінити як сервер розробки, так і бандлер JavaScript. Це для мене дуже привабливо, бо використання Hugo дозволить поєднати статичний маркетинговий сайт та додаток в єдине ціле. Або міксувати блог та різні цікаві експерименти на JavaScript.
Для компіляції JavaScript Hugo містить бандлер ESBuild. Оскільки ESBuild написаний на Go та Hugo написаний на Go, то інтеграція відбувається на внутрішньому рівні. З поганого: конфігурація ESBuild прихована всередині, тому нічого з нею не зробиш. Наприклад, зараз вона не дає імпортувати SVG файли через технічно простий брак налаштувань. Але взагалі того, що є, цілком вистачає. Для Typescript можна редагувати tsconfig.json як звичайно.
Ще з поганого: плагіни ESBuild не підтримуються, бо для них потрібний інтерпретатор JavaScript. Тому — ніякого Svelte - шкода. А JSX та відповідно React вбудовані, та з ними проблем немає. (Взагалі в мене дуже поганий досвід використання Svelte як з ESBuild, так і з Babel, тільки з Vite все задовільно працює.)
Зате вбудована підтримка Babel, а для стилів - Sass, та PostCSS. Перезавантаження наживу добре працює. Причому файли JS та CSS включаються в шаблони звичайних сторінок, тому можна, скажімо, деякий скрипт додавати тільки на окремих сторінках (як я зараз роблю зі скриптом карти.) Також, само собою, вбудована мініфікація та хешування. А ще Hugo вміє підготувати зображення.
Щоб зробити SPA з внутрішніми шляхами, його базовий шаблон треба помістити в layouts/404.html; тоді всі сторінки, що не є статичними, будуть оброблені в SPA. Це працює як в локальному режимі, так і в продакшні, якщо правильно налаштувати (а саме, вказати вірну сторінку 404.)
26.05.2023
Capybara - найкращий інструмент для інтеграційних тестів
Люблю фреймворк інтеграційних тестів Capybara. Дванадцять років тому я робив презентацію про те, яка вона класна. Та, за цей час, вона стала тільки краще. Хоча що дійсно стало краще, то можливості емуляції браузера, через що “само-багів” в тестах значно поменшало.
В чому перевага Капібари? Я бачу дві.
-
Синтаксис Ruby найкраще підходить для створення DSL, а рубішний підхід до асинхронності не ускладнює код конструкціями на кшталт
then,await, оголошеннями функцій, типами та так далі. При цьому тести залишаються справжнім кодом, та його можна рефакторити, міксувати з кодом, що не стосується інтеграційних тестів, та інше. -
Останній пункт дуже важливий. Бо в тестах Capybara ми маємо повний доступ до контексту додатка. Наприклад, ми можемо наповнити базу тестовими даними, використовуючи ті самі фабрики, що і юніт-тести. (До речі, фабрики на Ruby теж незрівнянні, але зараз не про них.) Але ми також можемо безпосередньо впливати на код додатка — наприклад, замокати метод, щоб відтворити необхідну ситуацію.
Звісно, що найкраще Capybara працює з додатком на Ruby on Rails. (Проте це не є обовʼязковим, капібарою можна тестувати будь-що.) Можна сказати, що це обмежує її потенціал, але обмеження — це те, що очікує всіх, хто не обрав Rails. :)
Чого справді не вистачає в Capybara - це такого журналу виконання, який є в Cypress або Playwright. Дивно що хтось його ще не зробив.
25.05.2023
Engineering vs Marketing
Хочу розібратися з уявленням інженерів про маркетинг, яке часто є зневажливим. Типу, маркетологи тільки й роблять, що брешуть, а інженери такі хороші та чесні.
Робота інженера складається з того, щоб побудувати найякісніший продукт (та не тільки інженера — а всієї продуктової трійки.) Тому інженери багато піклуються та розмовляють про недоліки. Бачити та виправляти недоліки — повсякденні будні.
Робота маркетолога в тому, щоб продукт купили. Це здебільшого покладається на уявлення про продукт, тобто що про нього знають та думають. Та, так само як задача інженера — зробити якісний продукт, задача маркетолога — щоб про продукт думали найкраще. Та для маркетолога природно висвітлювати переваги та не зважати на недоліки. Погані сторони продукта цікавлять маркетолога тільки настільки, наскільки вони впливають на нішу ринка та портрет клієнта.
Якщо ти не займався маркетингом, може здатись, що це зайве, що продукт сам за себе говорить, та якщо він гарний, то ніякого маркетингу не треба. Це абсолютно не так. Без маркетингу продукт не будуть “сприймати таким, як він є”. Про нього просто ніхто не дізнається. Можу проілюструвати розповіддю про сервіс аналітики Plausible - сервіс чудовий, але поки не прийшов маркетолог, користувачів у нього не було.
Так хоч неприємно стикатися з випадками, де маркетинг привабливий, а продукт — ніякий, мені завжди прикріше, коли продукт — гарний, але маркетинг або відсутній, або навпаки, надто агресивний та відразливий. В нашому житті враження значать більше, ніж суть, бо можливість пізнати речі такими, як вони є, у нас обмежена.
Інженер та маркетолог дійсно мають різний погляд на продукт та на його майбутнє, але їх цілі синергічні. Щоб маркетинг менше брехав, інженер має, як завжди, комунікувати, а саме — знаходити в продукті реальні, важливі обмеження та наголошувати на них. А не валити на маркетолога всю вагу своїх тривог та турбот. Тобто теж стати трохи маркетологом.
24.05.2023
Мета одночасного програмування — застосувати всі ядра процесора
…Коли я писав свій перший сервіс на Go, мене захопила легкість, з якою там створюються паралельні процеси — горутіни. Мені як раз треба було обчислювати структуру, що складалась з більш ніж 1000 значень. Чудове застосування для горутін, думав я, та створював в циклі всі 1000 штук — по одній на значення.
Через декілька днів після запуску сервіс почав падати через нестачу памʼяті. Виявилось, що хоч горутіни є легковажними, та їх можна створити багато, але тисяча горутін, помножена на сотні паралельних запитів, споживала всю наявну памʼять. Та коли колега поділився статтею про створення мільйона горутін, вона підняла ці спогади.
Моє бачення в тому, що абстракції одночасного програмування існують не для того, щоб “розділити незалежні обчислення” чи “щось швидше обчислити”. Одночасне програмування розв’язує задачу ефективного використання процесора. Та, хоч технічно горутін можна створити навіть мільйон, це буде така сама помилка програміста, як і алгоритми експоненційної складності й інше. Суто теоретично воно має сенс, але на реальному залізі так робити ніколи не треба.
Реальний процесор може виконувати паралельно тільки обмежену кількість операцій. Якщо мовити про сервери, то типова реальна машина — не більше 4, а в абсолютному максимумі - 64. Ніяк не тисячі. Створення тисяч одночасних процесів не прискорить їх виконання, а тільки впровадить невизначеність, оскільки ти більше не контролюєш порядок виконання. (Не кажучи про проблеми з памʼяттю.)
Якщо треба виконати багато обчислень в одночасному режимі, створюється [пул]`(https://github.com/panjf2000/ants) за кількістю ядер процесора. Пул саме й дозволяє використати всі ядра, та нічого більше. Саме до такого рішення я й перейшов після того, як мій сервіс звалювався під вагою тисяч горутін.
Якщо наш додаток делегує роботу базі даних, то в пулі може бути більше процесів, ніж ядер, бо процеси будуть чекати (це якщо база на іншій машині.) Більше настільки, наскільки багато часу процес проводить в базі; якщо третину часу, то на третину більше. Задача та сама — пустити в дію всі ядра більшість часу.
Окремо стоїть славнозвісна мірка мови — підтримка тисяч підключень. Що точно не потребує окремого процесу, це мережеве підключення. Бо багато підключень — це абстракція. Насправді у компʼютера, навіть у сервера, тільки одне, послідовне підключення до зовнішнього світу. Скільки б не було клієнтів, процес на них потрібний тільки один. Буферів в памʼяті треба багато, це так. Та типовий сервер обробляє їх послідовно, завдяки виклику select(). Для паралелізації буде 2, 4, 8 послідовних обробників select(). Мати по процесу на підключення — ще одна хибна абстракція.
23.05.2023
Смуга прокрутки для анімації Greensock
Як і планував, увечері переробив анімацію на прокрутку на більш традиційну анімацію з власною смугою прокрутки, яка зазвичай буває у відео.
Власне, викинути прокрутку просто — прибрав конфігурацію та прибрав CSS, який створював довжелезний контейнер - “предмет” прокрутки. Ну та й додав саму смугу (до речі, чомусь Unicode media control symbols на айфоні перетворюються в емоджі — поки не знайшов, як це виправити.)
Щодо реалізації смуги. Її стан оновлюється в тій самій функції render(), що малює сцену. Для цього у Greensock є функція timeline.progress(), яка повертає значення від 0 до 1 - дуже зручно.
Щоб керувати анімацією, треба лише виставити той самий прогрес, що я роблю на події mousedown, mousemove, touchmove - обчислити прогрес як дріб нескладно. Для паузи теж є функції timeline.pause() та timeline.play().
З паузою й почалися складнощі. На відміну від анімації прокруткою, нову анімацію потрібно створювати в стані паузи та починати, коли карта зʼявляється на екрані. Для цього підійшов код з IntersectionObserver, який я вчора написав для автопрокрутки. Але це не все.
Анімація, що створюється в паузі, при першому старті починалася з незрозумілого сміття. Почитав документацію, дійшов висновку, що це через те, що я всюди вживаю інтерполяцію fromTo(): а саме, всі значення from застосовуються миттєво та псують початковий стан анімації. Щоб виправити це, переписав все на команду to(); вона інтерполює з поточного стану до заданого. Там де потрібні були стрибки значення — впровадив їх командою set().
22.05.2023
Прогрес-бар для сторінки зі світлинами. Автопрокрутка
Сьогодні доробляв вчорашній пост. За першими відкликами побачив дві проблеми.
-
Світлин багато та вони важкі — а без них сторінка, фактично, поламана. Це досить легко побачити на повільному підключенні. Гарно було б робити для мобільної ширини більш компактні світлини, але це складніше. Поки що зайшов з іншого боку — прокрутка блокується, доки всі світлини не будуть завантажені. Для цього на титульному екрані додав прогрес-бар. Прогрес оновлюється на подію
img.onload. Єдине, що якщо світлина вже закешована, то подія не відбудеться, тому треба спочатку перевіряти значенняimg.complete. -
Анімація карти прокруткою неочевидна. Добре якби вона була ще повноекранною. Але повноекранна не впевнений що буде та що потрібна. Особливо на вузьких телефонних екранах, виходить все одно робоча площа буде маленька. Сьогодні зробив автопрокрутку — там вилізла купа логіки, наприклад, якщо сторінка прокручується зверху, то автопрокрутка потрібна, а якщо відкритий якір посередині, то ні. Ще автопрокрутку треба вимикати, якщо користувач намагається крутити власноруч. Проте найгірше те, що автопрокрутка на айфоні не працює, а тільки здригається. (Реалізація самої прокрутки така: позиція визначається інтерполяцією Greensock, а далі передається у
window.scrollTo. І все це відбувається вrequestAnimationFrame. Може, я щось роблю неправильно, але ж помітно це тільки на iPhone.)
Одним словом, скоріше за все, взагалі приберу анімацію на прокрутку та зроблю більш очевидний елемент прокрутки на кшталт відеопрогравачів.
21.05.2023
Пост про похід
🥳 Нарешті пост про похід закінчений та його можна подивитись: Похід на Клаферкесель. Ви перші глядачі, тож якщо щось поламане, прошу поділитися.
Пару зауважень: треба почекати, поки завантажиться — бо світлин близько 26 Мб. На десктопі чи планшеті має кращий вигляд, ніж на телефоні. Бо я хотів красивий великоекранний досвід, а про телефон думав в другу чергу. В майбутньому, сподіваюсь, придумаю щось гарне для телефону, бо оригінальний задум на маленький екран не перекладається.
Ще, анімацію карти треба прокруткою вниз докрутити до кінця; після цього відімкнеться прокрутка нижче. Я вже бачу, що треба це або пояснювати, або зробити інакше (може, автоскрол.)
Карту довелося обмежити квадратом, бо з прямокутним вікном текстури або виходять надто розтягнуті, або їх просто не вистачає. Над цим ще подумаю, бо в ідеалі карта має бути на весь екран.
А все, що нижче, зроблено на шорткодах Hugo та чистому CSS. Сподіваюся, колись стане опен-сорсом. Майже все легко адаптується під інші розповіді — бо я хочу робити більше постів. А також тому, що для інженера рушій то найцікавіша частина. :)

