Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS · 📢 Канал в Telegram @stendap_sogodni
20.11.2024
Як я робив 3D-рушій
🎈🐴🧑🚀 В далекому 2004 році я писав той самий “другий проєкт”, про який тут згадували в коментарях: а саме, ідеальний рушій для 3D-ігор у вакуумі. На той час я вже трохи наробив ігор на Паскалі, але треба було кудись рости… Тому новий рушій був на С++. Тоді мене в C++ закохала можливість перевантаження операторів та, порівняно з C, можливість ООП (яка й в Паскалі вже була знайома.)
💯 Почав з математики. (Та, як можна уявити, я все хотів писати самостійно.) Лінійна алгебра вона наче не дуже складна, але в реалізації легко заплутатись, бо всі ті формули з підручників потрібно було переписати. (А про юніт-тести я тоді ще й не знав.) Вектори, матриці то ще добре, а от від кватерніонів досі жахаюсь. Кватерніонами робляться оберти в 3D-просторі - про ті оберти цілий айсберг нюансів.
🎥 На базовій математиці будується модель простору. Бо щоб щось показати на екрані, для початку треба визначитись, де камера, та як відносно неї розташовані предмети. Це все купа матриць; матрицями задаються перетворення систем координат. За основу я взяв OpenGL - низькорівневий графічний API. Так от йому подавай матрицю камери та світові координати точок… суцільна математика.
🚛 А далі — що показувати? Обʼєкти та їхні текстури потрібно завантажувати з файлів. Тому я, звісно, сам написав завантажувач з BMP (найпростіший формат графічних файлів, до речі!) та моделей Milkshape 3D (оце вебдизайн!)
🏗️ Зверху того рушію потрібна модель виконання (тобто петля з таймером, кадри, таке інше), інтерфейс (вікна, HUD, шрифти), механізми керування. І це ще ми не дійшли до головного — до гри!
🍰 От і я не дійшов. Попри такий докладний підхід, нічого окрім простих демок я так і не зробив. Та якби зараз собі радив, то почати з “вертикального зрізу”, тобто з простої, але завершеної гри, а потім вже узагальнювати.
🏆 Але я не думаю, що проєкт був повною дурнею. Для програміста писати рушій це найчистіша форма самовиявлення. Плюс, з цим рушієм в резюме я потім знайшов першу серйозну роботу (хоч і зовсім не про ігри, а про веб та PHP.)
19.11.2024
Користуйтеся посиланнями замість буквальних імен
З Terraform метрику AWS CloudWatch видалив, а тривога за метрикою залишилась. Та ще й негайно стривожилася. Та підняла інцидент в PagerDuty. (Гарно хоч, що не посеред ночі.) Цього можна було уникнути, якби ресурс тривоги посилався на ресурс метрики:
resource "aws_cloudwatch_metric_alarm" "foo" {
# ✅
alarm_name = aws_cloudwatch_log_metric_filter.foo.name
# ❌
alarm_name = "foo"
}
Звісно, схожа проблема зустрічається у всіх мовах та постійно. Рядки повинні бути в константах або ідентифікаторах. В одному місці. В решті місць — посилання на ті константи. Тоді в коді легко відстежити використання термінів.
Статична типізація трохи допомагає, бо в багатьох місцях мова вимагає чіткості. Мені подобаються вирази-шляхи у Swift. Але там теж є ключі в словниках та всілякі “магічні значення” (які фактично є неоголошеними константами). Добре коли в мові є тип enum
.
В динамічних мовах гірше, бо там менше різниці між рядками та ідентифікаторами. Он, в Ruby багато всього працює через :символи
. Все одно, коли символ використовується всюди в проєкті, краще покласти його в якусь константу чи метод. (Всім знайомий приклад: Rails.env.development?
замість Rails.env == "development"
)
А ще в Ruby є погана тенденція конструювати ті імена на ходу, як-от "#{attribute}_exists?"
. Та й в Terraform такого багато. Тоді взагалі ходи шукай ті назви.
18.11.2024
Варто починати дослідження з написання тесту
Коли треба щось перевірити — баг чи просто незрозумілу поведінку — я починаю з тесту. Зазвичай інтеграційного, але не обовʼязково.
Для мене в цьому більше сенсу, ніж в “test-driven development”, оскільки я не люблю писати тести на порожньо. Ще я не люблю вручну відтворювати обставини — особливо на неповноцінній локальній версії — а тест дозволяє це автоматизувати.
Наприклад, показали дивну поведінку в продакшні — що легше буде — шукати причину з журналів та обмеженого доступу до даних, чи спробувати відтворити в тесті та мати для дослідження вичерпний стан? Або згадали на нараді неочевидну ситуацію — достатньо написати тест, щоб побачити її на власні очі.
Тому в мене час від часу зʼявляються ПРи, в яких є тільки пара тестів, та ще може коментарі по коду. Написав, перевірив, код виявився вірним, а тест — навіщо його викидати?
Звісно, для того, щоб так робити, потрібна структура запуску тестів. Та це непоганий аргумент її мати, навіть коли ви не плануєте серйозно покривати проєкт тестами. В мене був проєкт, де тестів спочатку не було, а почалися вони саме з ось таких “дослідницьких” тестів.
Скажу по секрету, коли мені потрібно надати знімок екрана з якогось функціоналу, я часто роблю його з інтеграційного тесту, бо так легше підготувати оточення, а якщо потрібно буде щось поміняти — то і відтворити.
17.11.2024
Переїзд сайту з Vercel на Cloudflare Pages
Давно вже обмірковую цей переїзд. Зараз мій сайт і так доступний через Cloudflare, але розміщений на Vercel. Хочеться консолідувати майно; та можливо навіть почати платити за Cloudflare гроші — бо там багато є гарного по аналітиці та по захисту. (Але базовий статичний хостинг що там, що там безплатний.) До Vercel в мене найбільше нарікання — що час від часу Ahrefs скаржиться на повільність сторінок, що для статичного сайту дуже підозріло.
Сьогодні спробував перенести. Власне, сам зміст майже тривіально переноситься, і це сучасне досягнення. Обидва сервіси забирають сайт з GitHub, та обидва здатні викликати Hugo для збірки. Тобто майже без налаштувань зʼявляється нова копія. Єдине, що вилізло — це на CF Pages встановлений Yarn 3 та він чомусь не погоджувався з моїм Yarn 1. Але, оновити собі Yarn справа недовга.
(До речі, також всі схожі сервіси використовують спочатку тестові домени, тому підготувати переїзд можна спокійно на тестовому, а потім перемкнути DNS, коли вже буде впевненість.)
З несподіваного: у CF Pages є обмеження на розмір файлу — до 25 Мб. В мене є пара архівів, що його перебільшують. Але їх можна перенести кудись в S3 чи на його аналог - Cloudflare R2.
А ось де справжня проблема, так це з перенаправленнями. В мене після змін архітектури залишився список з близько 1000 застарілих шляхів. В Cloudflare є зручний файл _redirects, але вони надто примітивні для моїх потреб. Наприклад, у Vercel можна написати /page(/?)
, а у CF тільки двома правилами /page
та /page/
. Так я починаю упиратися в обмеження на кількість перенаправлень (2000 + 100 динамічних.)
В мене очевидно надлишковий список, можливо, доведеться його обрізати до реально потрібних. Або взагалі почати з порожнього та спостерігати за 404-ми. (Можна було б, за всі ці роки вже зібрати “живий” список старих посилань, але кому він був потрібний?)
Є ще варіант замінити 404-ту на функцію та обробляти перенаправлення там. Безплатно доступні 100 тисяч викликів функцій, вистачить з головою. Функції в Cloudflare потужні, там і база даних є, тож цікаво випробувати.
16.11.2024
Виконання задач за порядком Final Version
Чесно, поки писав пост про порядок виконання задач, тільки під кінець згадав про існування “системи” Final Version (Perfected). А я їй колись користувався в блокноті, з непоганими результатами. Цього разу вирішив адаптувати систему для власного домашнього застосунку для ведення справ. Далі більше про систему FVP та деталі реалізації.
Нащо воно потрібно? Бо чим довше список задач, тим важче обрати, що з нього робити наступним. Та найстрашніше те, що природна реакція на те — взагалі нічого не робити. Тому люди вигадують всякі системи, як я писав в попередньому пості, а також розставляють пріоритети, плани на сьогодні та таке інше.
FVP пропонує елегантне та просте рішення, яке все ж включає постійний перегляд всього списку — тому важливі задачі будуть виконані якнайшвидше. Це, якщо хочете, розвʼязок задачі динамічним програмуванням.
Для FVP тобі потрібний список, де можна відмічати задачі. (На папері — ідеально.) Відмічати будемо задачу, яку робити наступною.
-
Спочатку — відмічаємо першу задачу (як початковий стан).
-
Далі шукаємо в списку задачу, яку треба зробити до відміченої.
-
Знайшли — відмічаємо її, та продовжуємо порівнювати решту задач вже з нею.
-
Дійшли до кінця списку — тепер остання відмічена задача є найпріоритетнішою. Робимо її.
-
Повертаємося до попередньої відміченої задачі, та продовжуємо перебір вниз по списку.
Сила цього метода в тому, що доводиться тільки порівнювати по дві задачі, та лише N раз. Ніби нічого революційного, але дуже дієво. (Залишається ще чистити список від того, що там застрягає, але то окрема історія.)
15.11.2024
Чому вам потрібний відділ підтримки?
Продовжимо розмову про професії, необхідні для програмного продукту, які не є інженерами. Я схиляюся перед терпінням, емпатією та розумінням працівників підтримки, це святі люди.
В інженерних колах існують деякі зневажливі стереотипи щодо підтримки: що там ніхто нічого не розуміє, що підтримка працює машинально, що її аутсорсять низькооплачуваним, незацікавленим найманцям. Звісно, все це можна було б застосувати й до самих інженерів, тож нічого особливого для підтримки тут немає. З єдиною різницею: з підтримкою ми знайомі на власному досвіді.
Бо, якщо маркетинг створює перші враження від продукту, то підтримка відповідає за весь шлях користувача. Та гарна, людяна підтримка не менш важлива для успіху, ніж якісне програмування.
Я навіть більше скажу: підтримка перекриває недоліки інженерів. Бо хоч я й працюю в компанії, де майстерність інженерів на найвищому рівні, але все одно наші продукти отримують десятки звернень до служби підтримки щодня.
Інженер скаже: PEBKAC, це все тупі юзери. Саме тому між інженерами та користувачами потрібний відділ підтримки. Проблеми користувачів — завжди проблема продукту, та щоб користувачі залишились, їм потрібно допомогти. Та якщо інженер ставиться до продукту, як тато, а маркетолог — як мати, то підтримка — це для продукту друг: знає підхід до нього, які в нього кращі сторони та тригери, та допоможе вам познайомитись ближче.
До того ж мені здається, що емпатія підтримки розповсюджується й на самих інженерів, бо з ними теж буває важко.Гарний інженер прислухається до підтримки, намагається побачити, де плани були хибними, та що можна зробити краще. Ну, а якщо продукт індивідуальний, то треба вчитись вдягати “капелюха” підтримки, на додачу до всіх інших.
14.11.2024
Ефективна робота зі сповіщеннями GitHub
Колись майже два роки тому мене дратував надлишок сповіщень з GitHub, та я навіть намагався зробити для того застосуночок. Погані новини: за весь час, що я витратив на перегляд PRів, такий застосунок не написати.
(Апарт: зі стохастичним трекером я “точно” знаю, скільки це часу. За минулі 9 місяців — близько 30 годин.)
Гарні новини: зі сторінкою сповіщень можна працювати ефективно. Та, якщо в одних обставинах має сенс збирати всі вхідні в один “кошик”, то тут, навпаки, варто розділити. Причому розділити за кількістю уваги, яку PR вимагає. Бо якщо дивитися на всі сповіщення разом, то доведеться кожному приділяти достатньо уваги, щоб нічого не пропустити.
Для цього звертаємо увагу, що на бічній панелі є посилання “Add new filter”. Туди можна окрім вбудованих фільтрів, назбирати власних, за обставинами. Можна або фільтрувати те, що варте уваги, або навпаки — те, що не варте, та масово “відмічати як прочитане”. Ось кілька ідей:
-
Дуже просте, це відокремити “підписку” від “запитів на погодження”. Принаймні в мене є репозиторії, де я хочу стежити за активністю (тому на них підписаний), але дій вони здебільшого не вимагають. Так можна швидко переглянути заголовки та відмітити більшість як прочитані. Ну, а там де є запит, звісно, я проводжу більшість часу.
-
Активність CI я отримую заради сповіщень на десктопі, але далі всі ці сповіщення можна не дивитись.
-
Фільтр за автором дозволить зібрати до купи PRи власної команди, або навпаки, прибрати PRи
нецікавих осібботів.
13.11.2024
Рушії для блогу
Взагалі я, звісно, переписував колись блог на новий рушій. Коли я починав щось публікувати, здається, ще взагалі “рушіїв” ніяких безплатних не було, а платити тоді не було чим. Перший сайт був на рукописному HTML.
Втім, я все ж був програмістом, тому знайшов таку цікаву технологію як SSI (включення на стороні сервера), якими можна замінити повторюваний початок та кінець сторінки. Хоч SSI не давав справжніх шаблонів, бо не було ані параметрів, ані “обгорток” - тільки пряме включення.
На початку 2008 в мене зʼявився перший віртуальний сервер, а також перша версія блогу на WordPress. Не памʼятаю, як обрав саме його. Я на той час працював на PHP та й фрілансив для WordPress, тож, мабуть, тому. Здається, в мене була власна тема та чомусь багато всього складного… Хоча найбільший мінус WordPress як я бачу зараз це його вразливість. Для найпопулярнішої платформи в інтернеті, в ній надто багато дірок, чим без кінця користуються спамери. Сайт на WordPress потребує постійної уваги та оновлень. Або просто будеш інколи помічати, що вже пару місяців хтось розсилає пошту з твого VPS/
Іронія в тому, що в тому самому 2008 я почав дивитись на RubyOnRails, а невдовзі й працювати з ним професійно… тож підтримка WordPress подобалася ще менше. Я не знайшов нічого кращого, ніж у 2011 переписати все на Rails.
З плюсів — ламати припинили, код став приємніше (HAML/SASS, між іншим). Блог перетворився на справжній проєкт-хобі. З мінусів - Ruby on Rails значно ненажерливіше. Особливо коли не розробляти сайт з розрахунком на кешування повних сторінок. Бо, якщо чесно, якщо кешувати, то недалеко від наступного рішення…
У 2016 мені набридло підтримувати Rails, та я переписав блог на Hugo - щоб він знову став статичним сайтом. Бо, дійсно, від блогу одного автора не потрібно багато динамічності. До речі, статичність не означає, що в сайті відсутня логіка та програмування; їх тут повно — але весь код виконується в момент компіляції. Головне, від чого довелося позбавитися — це коментарі — а точніше, замінити на зовнішнє рішення. Спочатку на Disqus, а зараз на власний скрипт. Втім, коментарі на сайтах все одно відійшли в минуле.
(Також, очевидно, зникла адміністративна панель та вебредактор. Тут я не бачу проблем, бо на розробку гідної адміністративної панелі часу не вистачало — а у статичного сайту замість неї звичний IDE та Git.)
Виходить, блог я переписував двічі: спочатку на Rails, а потім — з них. За цим трендом у 2023 пора було переписувати наново. Але, я переконаний, що статичний сайт — це найкраще рішення для мене, тому нікуди не поспішаю.
12.11.2024
У вас, певно, не буде часу на це переписування
Безперечно, переписати проєкт наново приваблива пропозиція. Можна нарешті врахувати все розуміння, виправити всі помилки… Під час це звучить настільки привабливо, що всі інші покращення відкладаються “на після переписування”. От тільки зараз часу переписувати немає, але як руки дійдуть… Тоді все зробимо як треба.
Уявлення про переписаний проєкт завжди буде вигравати у справжнього проєкту просто тому, що воно уявне. Тому в ньому немає всіх майбутніх багів, недоліків, та й просто витраченого часу.
Таких аргументів для переписування недостатньо. Потрібні вагомі, категоричні переваги нового рішення, до того ж релевантні для проєкту. Навіть більше, старе рішення мусить мати такі ж категоричні вади. Тоді переписування з мрій перетворюється на потребу.
Але про такі переписування довго не думають — їх роблять. А я кажу про інші. Ті, що робляться, гадаю, з нестачі розуміння… приблизно так само, як і переїзди на новий трекер задач. Тоді краще сісти та зʼясувати, що ж все ж таки не влаштовує в поточному проєкті та як це виправити послідовними змінами.
Наприклад, я нещодавно думав переписувати наново рушій для блогу. Бо… надто складний він зараз. Але нічого технологічно нового я не планував: той самий Hugo. Та от бачу, що краще поступово додавати функції та оновлювати дизайн на місці. (Цими днями додав посилання на Mastodon… а також замінив значки на обрізаний Nerd Fonts.) Бо переписувати буде нереально довго.
11.11.2024
Порядок виконання задач
Загально прийнятно планувати виконання задач крайньою датою (due date). Але, як вам повідомить кожний студент, крайня дата не є дієвою для планування роботи. Як на мене, то крайні дати взагалі є засобом комунікації, а не планування. Ми домовляємось з кимось (або з самими собою) про очікуваний результат. Але є мало сенсу робити задачі в порядку крайніх дат.
Зараз є інший досить популярний підхід — це дати виконання (do date). Або їхній спрощений варіант “зробити сьогодні / завтра”. Так трохи легше, в першу чергу тому, що дати виконання можна розставляти сміливіше, ніж крайні дати. А точніше, сміливіше їх порушувати.
Але, гадаю, проблема взагалі в тому, що ані система задач, ані ми самі не можемо гарантувати ті дати виконання. Виходить ще один шар крайніх дат, тільки менш надійний. Системи, де я ставив плани на день, закінчувались переповненням тих планів та банкрутством. Причому інколи достатньо пару несподівано складних днів, щоб хвиля недовиконаних планів почала наздоганяти. А з іншого боку, це абсолютно надумана проблема, бо на відміну від крайніх дат, ніхто нас не змушував призначати дати виконання чи плани на день.
Тому для мене краще працює виконання зверху вниз — перша задача, друга, третя. В такій системі зрозуміло, як запланувати задачу на скоріше: просто пересунути її нагору. Так, це не дає впевненості, що задача буде зроблена сьогодні чи завтра, але така впевненість взагалі є надуманою.
Для вибору порядку виконання є й більш просунуті системи: наприклад, Autofocus чи Final Version. Але головне, що можна зробити, це частіше звертатися до списку та щось з нього виконувати, а не тільки планувати та розставляти дати.