Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
28.10.2022
Чому робочі питання треба обговорювати в спільному чаті.
💬👥📖 Всі робочі питання в команді краще обговорювати в спільному чаті. Приватний чат залишається для особистих питань - “коли зустрічаємось”, “як справи”, “ходімо на обід” та інше.
Але все, що стосується розробки проєкту — в спільному. На мою думку, саме такої політики треба дотримуватись, та регулярно нагадувати собі та іншим. Чому саме так?
- Питання. Якщо ставити питання приватно, то відповісти має той, кого запитали. Це створює блокер — один чекає, другий має терміново відповідати. Також це підвищує bus factor, бо не дає іншим членам команди використати свої знання. Тому краще питати публічно, навіть якщо здається, що відповідь знає хтось конкретний.
- Обговорення. Ніхто ніколи не тримає весь контекст проєкту водночас, тому завжди є шанс, що дехто з команди відкриє ще невідомий бік питання. Також обговорення в спільному чаті роблять рішення відомими всім та відразу. Якщо ж обговорювати приватно, то хибні рішення будуть помічені пізніше і коштуватимуть дорожче.
- Історія. Зміст публічного чату можна знайти пізніше. Є питання та ситуації, що виникають знову і знову. Так, ідеально було б задокументувати кожне, але я не вірю, що хтось так робить. Але якщо просто обговорювати публічно, то журнал чату — це вже документація. Я часто шукаю (та знаходжу!) висновки з обговорень, зроблених рік чи більше тому. Звісно, документацію це не скасовує. Наприклад, розвʼязок кейсів підтримки можна почати в чаті, а потім перенести в повноцінну базу знань.
Не обовʼязково обмежуватись одним чатом, можна створити хоч скільки за різними призначеннями — головне, це щоб всі зацікавлені особи мали можливість долучитись.
27.10.2022
Зручніше відображення даних з бази HealthKit
⚖️📉💚 Нарешті, можу проілюструвати, що я мав на увазі, коли казав, що вигляд даних у вбудованому додатку Health залишає бажати кращого.
Зліва та справа — одні й ті самі дані, а саме, вага протягом місяця. Залишаючи питання масштабу (над яким я ще планую працювати), основне покращення ось в чому: на моєму графіку лінія — то середнє значення, а саме, рухоме середнє. А крапки — то індивідуальні вимірювання. Кожне вимірювання зсуває середнє вгору чи вниз, це закодоване кольором та відмічено лінією. Так з першого погляду можна зрозуміти, що робиться. А якщо можна дати стислу оцінку, якщо підрахувати крапки за кольором.
Основна теза такого підходу — замість турботи про значення ваги, що постійно коливається, спокійніше дивитись на загальну тенденцію.
Взагалі це тільки початок того що я хочу зробити, але навіть в такому вигляді вже можна отримати користь, тому що додавати та редагувати дані можна через Health.app, як я писав раніше.
Систему з середнім я придумав не сам, а прочитав багато років тому у книзі Hacker’s Diet. То є легендарна книга, яку варто прочитати кожному інженеру, що хоче схуднути. Написав її засновник компанії Autodesk.
До речі, нічний режим у SwiftUI надається автоматично, якщо вживати палітру системних кольорів. Дуже зручно.
26.10.2022
SwiftUI після React - враження
📱📐🎨 Потрохи просуваюсь зі своїм проєктом на HealthKit та тепер на SwiftUI. Скористуюсь нагодою розповісти трохи про SwiftUI і як на ньому писати після React.
Всім відомо, що SwiftUI був створений, щоб йти в ногу з часом саме з React та іншими схожими фреймворками. Це добре.
Перше слабке місце SwiftUI - відсутність JSX. JSX це чудова технологія, бо з одного боку надає можливість описувати структуру елементів та атрибутів наочним чином, а з іншого боку, еквівалентна JavaScript/TypeScript коду та піддається всім технологіям роботи з кодом — рефакторингу на функції та модулі, формальній перевірці та інше.
У SwiftUI структура задається звичайними функціями, а також блоками. При чому модифікатори додаються в кінці функції чи блока, тому розібратись, що до чого, складніше.
Друге слабке місце - Swift це суворо типізована мова, але при цьому з тенденцією автоматичного виведення типів. Тож весь той синтаксис має створювати коректну структуру типів. Я не маю компетенції повністю зрозуміти, як воно працює, але факт, що у великій компоненті можна прийти до неможливості виведення типів. Ще скоріше цю помилку побачиш, якщо вживати блоки if, які, на відміну від JSX, інколи працюють добре, а інколи ламають компілятор. Відповідь — рефакторити на менші компоненти.
Щоб почати, варто відразу зрозуміти, що аналог Redux будується на основі ObservableObject. Тобто в простих випадках можна зберігати стан в компоненті, як і в React, але при подальшому розвитку краще винести логіку в клас з ObservableObject.
З приємного — гнучка система лейаутів — особливо для того, щоб покрити різні розміри екранів, та навіть різні пристрої. Бо у SwiftUI одна і та сама компонента може працювати й на айфоні, і на маці, і на годиннику. Тут все супер.
Ще раджу продивитись офіційний курс по SwiftUI, він багато чого прояснює.
25.10.2022
Ми є то, що ми робимо щодня
☀️🌚🫂 Ми є то, що ми робимо щодня. Це дуже потужна думка.
Майбутнє є неосяжним. Спланувати його, а потім слідувати плану, мало кому вдається.
Натомість можна подивитись на свій типовий день, і що в нього входить. Наше майбутнє складається з нашої рутини, день за днем. Це водночас очевидно та розриває мозок. Бо змінюючи свою повсякденну рутину, ми й можемо поступово впливати на майбутній результат. І для цього не потрібно робити великий план: просто щось додати, щось відняти.
Тому, мені здається, на роботі легко досягати успіхів, а на власних проєктах — ні; бо робота це явище обовʼязково щоденне, тож мало-помалу результату не уникнути. Тоді, включив у свій день хоч трошки роботи над власним проєктом — може, пʼятнадцять хвилин вранці, а може, раз на тиждень чотири години — він теж може стати таким неминучим, як робота.
Так само і з іншими змінами, яких ми прагнемо: не обовʼязково уявляти їх як грандіозний стрибок; треба думати, як включити їх, хоч саму малість, в повсякденне життя.
24.10.2022
Як Сloudflare бореться з атакою DDoS
💩🚚😬 Сьогодні весь вечір боролись з виснажливою DDoS атакою. Довелось випробувати, на що здатний Cloudflare. Отже, декілька спостережень:
-
Платний план захищає суттєво краще, ніж безплатний (а у нас як раз чомусь скасувався платний, можливо, через перемикання картки.) Кількість заблокованих запитів більше у 20 разів. Думаю, це тому, що на безплатних користувачах Cloudflare і дивиться, який клієнт неблагонадійний. Хоча якщо грошей немає, то все одно від чогось Cloudflare вас захистить.
-
Автоматичне блокування не ідеальне, тому раджу в реальному часі дивитись на характер запитів, та вручну створювати правила до фаєрволу. Так надійніше. Та, звісно, автоматичні правила продовжуватимуть роботу.
-
Треба вмикати режим “під атакою”, тоді всі відвідувачі будуть проходити через JS перевірку. (Security level -> Under Attack.) При цьому, щоб не поламати API, для нього за допомогою Page Rules треба поставити інший рівень безпеки (і заздалегідь).
-
Окремо нас порадував плагін Wordfence для WordPress. Здається, атака переповнила його базу, та вичерпала ресурси сервера. Вимкнули плагін повністю, бо за Cloudflare в ньому немає сенсу.
-
Налаштуй сповіщення про DDoS, щоб не чекати скарг клієнтів.
А тепер, буду встановлювати macOS Ventura. 🌻
23.10.2022
HealthKit - все ж таки краще на SwiftUI, ніж на React Native
🍏🪶❣️ Сьогодні пробую свій проєкт з HealthKit почати писати на Swift. Головною причиною є бажання поекспериментувати: я давно хочу зробити на SwiftUI щось реальне, і, може, на цей раз вдасться.
З роками Swift та SwiftUI помітно дорослішають, та писати на них все менш і менш боляче (сказати “приємніше” ще не виходить.) Все тут чуже: мова та її парадигми, стандартна бібліотека, модель додатка, навіть редактор (програє VSCode за можливостями розширення та за зручністю) та документація (не дуже зручна і не дуже гарно написана.) Ніяк не можу заохочувати писати на Swift, якщо воно вам не треба.
Тому, до речі, я великий прихильник React Native: вийде не набагато гірше, але на знайомих технологіях. Цим не варто нехтувати.
Але все ж таки, що у Swift є такого, що у RN немає, або є, але гірше? Головне, що я знаю — це база Core Data, а особливо CloudKit, тобто синхронізація через iCloud. Зараз в RN немає гарного рішення — тож якщо вам потрібна якась синхронізація, треба мати бекенд, авторизацію і таке інше. Натомість у Swift дані синхронізуватимуться між пристроями без зайвих дій та акаунтів. Але, якщо ви робите додаток для вже наявного сервісу, то це не має значення.
Також будь-яка системна інтеграція — а їх чимало — завжди ускладнюється у RN. Наприклад, як в моєму випадку HealthKit: бібліотека у Swift достатньо обʼємна, тому повної обгортки для RN немає.
Можна зробити й гібридне рішення: модуль на Swift, який буде передавати до React Native необхідні значення — тобто замість API загального призначення, зробити вузький API для вашої бізнес-логіки. Це в мене зараз план C.
22.10.2022
Пост посилань. Copilot, Obsidian, Twitter, DuckDuckGo, macOS
🔗🔎📢 Сьогодні буде пост посилань. Давно вже хотів це спробувати, оскільки щосуботи читаю новини.
-
Тривають розслідування порушень авторських прав сервісом GitHub Copilot. Ми в компанії вже вирішили, що краще їм не користуватись. А як альтернатива вже давно є TabNine, що має локальний режим.
-
У програми для збереження нотаток Obsidian вийшла версія 1.0. Вона дуже потужна, попри те, що нотатки зберігаються у звичайних текстових файлах. Але мене поки що зупиняло те, що вона зроблена на Електроні.
-
DHH міркує про те, чи потрібна велика команда великому проєкту. На мою думку, принаймні потрібно достатньо інженерів, що будуть працювати на підтримку та забезпечення стабільності.
-
Цікавий закон Конвея стверджує, що архітектура продукту повторюватиме структуру команди. Тож, якщо продукт роблять три команди, то він опиниться з трьома модулями чи сервісами. Цим можна скористатись, щоб передбачити кількість компонент при плануванні.
-
Вийшов браузер DuckDuckGo для macOS. Він побудований на двигуні WebKit (тобто Safari), та має цікаві функції безпеки. Мені поки власне Safari й вистачає. Єдине, що дійсно визначне в DDG - то урізаний інтерфейс YouTube. Але його нескладно відтворити будь-яким доповненням, що блокує елементи. В мене це давно зроблено через 1Blocker - тобто на YouTube я бачу тільки поточне відео.
-
Нові версії macOS та iOS виходять у понеділок (у Європі ввечері, спасибі й на тому, що нема спокуси зіпсувати робочий понеділок.) Найбільш очікувана мною фіча — то iCloud Shared Photo Library.
-
Ще сьогодні збирали всією сімʼєю табурети з IKEA. Тож ділюся статтею по ефект Ікеї. Він полягає в тому, що ми більше цінуємо те, що побудували самі. Це може бути не тільки меблі, а, наприклад, продукт чи сервіс, який хоч і не найкращий, але самописний, тож продовжуємо підтримувати всупереч рації.
21.10.2022
Метапрограмування в Ruby як наслідок відсутності функцій як значень
🚂🚅🪆 Чому в Ruby метапрограмування — це норма, а в JavaScript його не роблять, віддаючи перевагу функціональній композиції? Ну, може, тому, що JavaScript - справжня функціональна мова, а Ruby - зовсім ні.
От вам треба зробити обгортку для якоїсь логіки. В Ruby, напевно, будете створювати методи через class_eval, який викликає інший метод, названий за деякою договореністю. На цьому побудований весь фреймворк Ruby on Rails.
А в JavaScript замість того можна просто передати в обгортку внутрішню функцію, а результат зберегти у константу, та вживати як будь-яку іншу звичайну функцію. Наприклад, так працює React, Redux, Reselect, та весь сучасний ідіоматичний JavaScript.
Тому вийду і скажу: метапрограмування в Ruby - це милиця, яка існує тому, що передача функції як значення в Ruby - надто повільна операція. Щоб не бути голослівним, побудував бенчмарк, що порівнює різні способи викликати шматок коду на Ruby.
Що виявляється: найшвидше працюють саме названі методи, тобто створені напряму в класі командою def, або через class_eval. На цілих 75% повільніше працює Proc - найближче, що є в Ruby до справжніх функцій. А виклик методу командою send аж в 3 рази повільніше. Гірше над усе робити посилання на метод командою method, яка практично не зустрічається на практиці.
До того ж схоже на те, що кожний вкладений виклик накладає таку саму ціну, тобто в Ruby краще обходитись найпростішою абстракцією.
Тепер, порівняємо з аналогічним бенчмарком для JS. По-перше, в JavaScript варіантів побудови та виклику набагато менше. Функція — це значення, та й годі. Роби з нею, що хочеш.
По-друге, цікаво, що в Google Chrome та в Safari вкладені функції не впливають на швидкість виконання. Як я розумію, це завдяки потужному механізму оптимізації JIT.
Для мене можливість функціонального програмування робить JS набагато привабливішою та елегантнішою мовою, ніж Ruby.
20.10.2022
Як виправити помилковий git push --force
🤠🚒🛟 Сьогодні колега перезаписав мої зміни командою git push --force.
Я не засмутився, бо сам великий любитель пушити примусово. Виправити таку ситуацію досить легко.
Треба розуміти модель Git: в ньому нічого не зникає назавжди (принаймні, відразу.) Git push перезаписує ланцюг комітів, це так. Але старі коміти залишаються в базі даних Гіта аж до виконання команди git gc (вручну або за досягненням межі по розміру.) Їх можна знайти командою git reflog - цю команду має знати кожний, хто любить push --force. Вона перелічить всі нещодавно активні коміти, навіть якщо вони були перезаписані. Далі залишається витягнути втрачений коміт командою git cherry-pick, і пушнути результат.
Чому я користуюсь git push --force? Зазвичай тому, що не люблю коміти-виправлення. А їх інколи доводиться робити багато. А ще, якщо змін багато, я люблю розбивати їх на логічні шматки по комітам. Звісно, відразу такого ніколи не заплануєш (хіба що не комітити до останнього — а це справжня небезпека, не те що push --force). Тому при підготовці пул-реквеста я сортую зміни командою git rebase --interactive.
(До речі, замість --force варто знати та використовувати більш обачливу опцію --force-with-lease.)
19.10.2022
Cloudflare for SaaS - генерація сертифікатів для користувацьких доменів
🔒✨🐇 Сьогодні увімкнули ще одну можливість Cloudflare - а саме, генерацію сертифікатів TLS для користувацьких доменів. Це у них загадково називається Cloudflare for SaaS.
Як це виглядає для користувача: вони роблять CNAME на наш домен, підтверджують його на нашому боці, і отримують на своєму домені HTTPS з правильним сертифікатом (і контент з нашого сервера).
Як це виглядає для нас: наш сервер має бути підключений через Cloudflare Proxy (як це нормально буває, якщо ви користуєтесь Cloudflare.) Потім, після реєстрації клієнтського домену ми по Cloudflare API додаємо його як Custom Hostname. По HTTP домен працює відразу, а з HTTPS через хвилину.
Як це працює: зрозуміло, що Cloudflare, по-перше, має підтвердити власність домену. Це можна зробити або доданням DNS запису, або відповіддю на HTTP запит за заданим шляхом. Так от, HTTP-випробування за нас пройде Cloudflare Proxy - бо домен клієнта вже направлений на нього через CNAME. До нашого додатка цей запит навіть не доходить. Отакою простою магією без жодних зайвих зусиль користувача він отримує TLS-сертифікат (тобто, сам сертифікат — ні, а підтримку HTTPS - так.) Радію від таких рішень.
Фіча доступна навіть на безплатних планах, а коштує $0.10 на домен на місяць, при чому перші 100 доменів безоплатно. Було б добре придумати якесь цікаве некомерційне застосування.

