Дробимо моноліт Рефакторинг архітектури Web-додатків

моноліт

Разом із Віктором gritzko Грищенком, творцем swarm.js (https://twitter.com/gritzko), розглянемо сучасні підходи до побудови архітектури JS додатків як на сервері, так і на клієнті.

— Коли ми говоримо про монолітні Web-додатки, зазвичай мається на увазі архітектура, що стала вже класичною. Так званий шаруватий моноліт добре прижився у багатьох корпоративних рішеннях. Розкажіть, з якими недоліками даної архітектури вам доводилося боротися у реальних проектах?

рефакторинг
— З такою класичною архітектурою я вперше зіткнувся ще 2000 року в Банку України. Причому виникла вона сама собою, у процесі аврального застосування. Вийшов цілком звичайний enterprise Java кошмар, коли систему можна було запускати тільки цілком і лише на сервері, з повною БД. Щось зробити з монолітом, що вийшов, було вже важко, все залежало від усього. Пізніше я бачив такі ж самі факапи в Яндексі. Це неминучий етап, якщо програма переростає свою архітектуру.

— Як зрозуміти, що монолітний проект настав час розділяти на сервіси? Існують характерні ознаки?

— «Пора розділяти» — це із серії «пора ампутувати». Поділ великої задачі на дрібні ортогональні підзавдання необхідно здійснювати на етапі проектування.

— Node.js дуже активно розвивається, статті та посібники швидко застарівають. Чи існують хороші практики, на які варто дорівнювати сьогодні? Можливо, є еталонні рішення для побудови мікросервісної архітектури?

Мені особисто здається, що мікросервіси на основі REST - це ті ж мініййони, тільки в профіль. Так чи інакше потрібний асинхронний зв'язок між підсистемами. У класиці це черги повідомлень, їх використовують скрізь і завжди скрізь використовували. Зараз є трендові штучки - Kafka,Akka.

— Для монолітної програми зазвичай достатньо мати балансувальник навантаження та потрібну кількість копій. Але у випадку з мікросервісами потрібно також розуміти, який компонент системи слід масштабувати.

— Балансувальник як такий вирішує проблему лише для дуже простих, в ідеалі stateless-додатків. Інакше починаються проблеми синхронізації та конкурентного доступу до даних, у підвалі відкривається портал і з нього лізуть демони. А компонент із однією зрозумілою функцією однозначно простіше масштабувати. Спеціалізація та економія масштабу – це друга половина XVIII століття, Адам Сміт.

Загалом доповідь не про мікросервіси. Я прикладаю ідеї «імутабельної інфраструктури» безпосередньо до фронтенду, до того, що працює у браузері.

- Добре, давайте обговоримо код на клієнті. Які проблеми зараз актуальні?

Витягування даних на клієнта йде повним ходом - спочатку витягли код, з'явилися SPA, тепер поступово витягуємо дані, хочемо offline-first, швидкий час відгуку та інші плюшки.

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

— Справді, розмір середньої веб-програми тільки збільшується. У вас є пропозиції, як можна покращити ситуацію?

— Моя витівка в тому, щоб суворо розділити все, що відбувається на фронтенді, на (А) дані та (Б) все інше (компоненти, код). Причому, все, що не дані - функції. А функції теж дані, якщо подумати. Коли ми кладемо код у систему контролю версій, він стає даними. Тобто у нас є версіоновані дані та версіоновані функції, які ми доставляємо на клієнт однаково, однаково кешуємо та оновлюємо.

— А якщотрохи докладніше?

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

Це схоже на мікросервіси частково - таке собі розпилювання маси коду на іммутабельні/версіоновані компоненти. До речі, я особисто волію все-таки називати це версіонуванням, а не іммутабельністю. Версія, хоч даних, хоч коду, за визначенням іммутабельна, і фокус саме в цьому.

Зрештою, фундаментальна проблема тут одна — і код, і дані повинні працювати на безлічі пристроїв одночасно. Ми будуємо розподілені системи просто тому, що процесори вже скрізь. Телефон – комп'ютер, книга – комп'ютер, телевізор – комп'ютер. Клієнт-серверне мислення відійде у минуле так само, як мейнфрейми пішли. А що прийде на зміну – цікаве питання.

— Звучить цікаво, але як це сумісне з існуючими бібліотеками та фреймворками? Навіть для часткової роботи програми знадобляться великі основні залежності (AngularJS, jQuery, …).

- Ну, preact уклалися в 3KB якось. Angular застосовувати в такому контексті дійсно нема чого.

— Ця концепція вже сформувалася в окремий проект? Де можна дізнатися подробиці?