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

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

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

06.10.2023

Використання Promise для побудови лінивих обчислень

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

Коли у вас уже є Promise, на ньому можна викликати .then() (та .catch()) скільки завгодно разів. Такі виклики призведуть до невідкладного виконання відповідного обробника. Після завершення поточного фрейму виконання, звісно, тобто семантика зберігається.

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

Можна звісно зробити менеджер стану (як Redux), а також механізм повідомлення про готовність. Може, використати EventEmitter та підписки.

Але як альтернатива до всього цього, можна зберігати сам Promise. Тобто результат виконання fetch(). При першому виклику робимо завантаження та зберігаємо Promise; а при наступних просто повертаємо той самий Promise. Споживачі нічого не знають про ці деталі реалізації, а просто отримують Promise з потрібними даними. В тому числі не буде проблеми, якщо другий виклик відбудеться до отримання результату, тобто Race Condition.

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


05.10.2023

Помилка тих, хто починає з AWS: не створити декількох акаунтів

Може, найбільш відома помилка у роботі з AWS - це коли зловмисники отримують доступ до ключів. Та і я про це вже писав. Ризики, повʼязані з ключами, можна значно знизити, якщо окрім головного акаунта мати також акаунт-пісочницю.

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

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

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


04.10.2023

Найбільша помилка тих, хто починає з AWS: власні витрати

Я вже писав про те, як легко в AWS спалити гроші. Проте не встиг розповісти, що можна робити, щоб запобігти цьому.

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

Мій улюблений приклад: якщо “по уму” зробити безпечну мережу, де внутрішні ресурси сховані в приватну підмережу, то для доступу з цих ресурсів в інтернет доведеться також додати шлюз NAT. Здавалось би, це абстрактна сутність, така сама як підмережі. Але ні - NAT-шлюз коштує $30 на місяць. За ці гроші на fly.io вже можна захостити потужний додаток. І це тільки “фундамент наших витрат”, так би мовити.

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

Також можна налаштувати Cost Anomaly Detection - вона повідомляє про надзвичайні витрати за окремою категорією, а не загалом. Тому це кращий механізм для більших проєктів, де значного перебільшення бюджету раптово не відбудеться, проте 100 pounds is still 100 pounds. Cost Anomaly Detection точно не проґавить зайву копію СУБД, забуту зі стрес-тесту.

Завтра — про другу за важливістю помилку.

PS: також завтра я візьму участь в стрімі DOU про безпеку AWS тут. Запрошую долучитись!


03.10.2023

Робота з файлами безпосередньо в браузері

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


02.10.2023

Як працювати з кодом JavaScript, коли вже звик до TypeScript?

Коротка відповідь — навпомацки. Відсутність типів відбирає приємне відчуття що код “звʼязався до купи.” Втім — доводиться стикатися з проєктами де TypeScript немає.

На щастя, VS Code й у JavaScript робить часткову типізацію. Підказки до коду та автодоповнення враховують ті типи, які можна зʼясувати з оточення. Це більш потужно, ніж можна подумати — на типах з пакетів залежностей можна далеко доїхати.

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

В JSDoc можна робити все те ж саме, що й просто в TypeScript - імпорти з інших модулів, складні типи, дженеріки, оголошення типів за іменем. Не раджу, наприклад, власний підхід JSDoc до типізації обʼєктів тегами @property; краще просто оголосити тип-обʼєкт в синтаксисі TypeScript в тезі @typedef, а потім використати його.

На останнє, якщо в файлі JavaScript написати магічний коментар //@ts-check, то для нього увімкнеться повноцінна перевірка на типи та вкаже всі помилки. Так хоч би тимчасово (або ні) можна переконатись в правильності коду та отримати ту дозу дофаміну.


01.10.2023

Змінні CSS

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

Змінна оголошує значення в контексті каскаду стилів та успадковується схоже до звичайних властивостей CSS. Стилі, які знаходяться глибше за визначення, можуть цю змінну використати. Таким чином каскадність стилів розширюється; тепер в наших компонентах ми можемо не просто спиратись на атрибути, які визначені вище (наприклад, колір шрифту), а й додавати власну логіку (наприклад, зробити рамку такого ж кольору, як шрифт, а скоріше, узагальненого кольору на кшталт var(--color-fg).)

Коли я вчив CSS, то змінних там ще не було. Зате змінні були в Sass. Між ними та змінними CSS є суттєва різниця: в Sass змінні мають синтаксичний контекст, тобто вони привʼязані не до таблиці стилів, а до початкового коду Sass. Так що змінні CSS це не просто заміна змінним Sass, а інший підхід, що має кращу синергію зі семантикою каскадних таблиць стилів.

Та окрема перевага — те, що змінні CSS залишаються в кінцевому коді. Це дуже зручно для розробки всіляких доповнень, оскільки стилі доповнення можуть легко використати базові стилі, якщо ті визначені через змінні. Так, в Obsidian тема оголошує змінними всі свої параметри. Якщо я хочу підсвітити термінову задачу червоним — мені не потрібно вигадувати колір, який буде сумісний з темою користувача — можна просто взяти --color-red або, можливо, --text-warning. Шкода що не можу знайти другого прикладу такої системи.


30.09.2023

Перехід з віджета до документа з задачею

Плагін потроху набуває форму. Одна з необхідних функцій це перехід з віджета активних задач до документа, в якому задача розташована. Спочатку хотів вставляти звичайне посилання, тобто <a>; посилання на файли в Obsidian працюють, але немає можливості відправити посилання на конкретний рядок. А без цього якось некрасиво. (Можна тільки посилання тільки на заголовки та на попередньо проставлені якорі.)

Тому пішов іншим шляхом — через API. Все ж віджет це повноцінний додаток, в якому можна написати будь-яку логіку. В Obsidian є така прикольна функція Workspace.getLeaf, яка утворює нові панелі редактора у вказаному розташуванні. Або бере поточну, що мені й треба. Далі робимо openFile() та файл відкритий. Цікавий нюанс: якщо панель закріплена, то openFile автоматично утворює нову, тобто покриває за нас поведінку самого Obsidian.

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

Мені жоден варіант не сподобався, бо знайти курсор серед тексту все одно важко. Придумав гарне рішення: додатково виділяти відрізок тексту — виділення помітніше. (Для того є функція setSelection.) Але що виділяти, щоб це було корисно? На мою думку, найбільш корисним є виділяти статус задачі, оскільки найчастіша дія це саме зміна статусу. (Поки не вирішив, чи треба додавати таку фічу в сам віджет, та в якій формі.)


29.09.2023

Про екрани завантаження в іграх Bethesda

Попалося мені порівняння завантаження зони в Cyberpunk проти Starfield. А саме: в Cyberpunk перехід з будівлі на вулицю відбувається безперервно, а в Starfield двері відкриваються через екран завантаження. Та не секрет що в усіх іграх Bethesda були такі екрани завантаження. Задумався, чому це так. Я не думаю, що Bethesda навмисно користуються застарілим рушієм просто щоб заощадити гроші — тож яка може бути причина?

Знайшов один показник, за яким ігри Bethesda абсолютно виділяються. Це величезна кількість модів, що додають до гри локації та квести. Дійсно, під час зміст модів перевищує зміст самої гри (Morrowind) або утворює повноцінну нову гру (Enderal на базі Skyrim, наприклад.) Серед рольових ігор з відкритим світом немає нічого навіть близького.

У Bethesda завжди був неперевершений редактор для модів - Creation Kit. Ще з часів Morrowind в ньому було досить нескладно додати свої будівлі, персонажів, діалоги. Тільки, як відомо інженерам, одного редактору мало — потрібна зручна ментальна модель.

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


28.09.2023

Головний програміст в пласкій команді

У нас інженерна організація абсолютно пласка. Кожний програміст на проєкті є потужним індивідуальним вкладником. Старшинства немає — щоб зробили “по твоєму”, треба це обґрунтувати та “продати”. Питання вирішуються демократією Втім, я бачу потребу в головному інженері (lead of engineering).

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

Якщо головного інженера немає, то в обовʼязки кожного інженера входить: а) повідомляти всю команду про свої архітектурні зміни, та б) стежити за змінами, що надходять від інших інженерів, та реагувати на них. Чим більше проєкт, тим складніше бути в курсі всього, що відбувається. Ба більше, постійна потреба не пропустити важливу зміну веде до тривоги та конфліктів в команді.

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


27.09.2023

Використання засобів AI для написання коду

Я вже писав про Tabnine - помічник для написання коду, яким я користуюся. Проте Tabnine дає мені тільки доповнення в межах рядка. А більш просунуті помічники навіть не хочеться пробувати. Спробував зʼясувати, чому.

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

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

Де б я хотів помічника, так це для пошуку по малознайомих проєктах. Я витрачаю на це чимало часу. Наприклад, відкриваю franz-go та питаю: “як визначити, скільки залишилось непрочитаних записів?”. Або, взагалі, для пошуку самих проєктів: було б чудово сказати “мені потрібно розібрати Markdown в синтаксичне дерево з відстеженням позицій вузлів” та отримати хорошу рекомендацію. Може, у вас знайдеться рекомендація такого сервісу?