Залежності коду - це диявол.

«Зміни - це єдина константа ...» - Геракліт (Філософ)

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

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

Ми імпортуємо, використовуємо та успадковуємо рамки аромату місяця так, ніби всі вони будуть навколо та незмінними назавжди. Ну ... вони ні. І це проблема.

Після 20 років розробки, проектування та архітектури веб-додатків я зрозумів дві важливі істини:

  1. Зовнішні залежності становлять велику загрозу довгостроковій стабільності та життєздатності будь-якої програми.
  2. Створювати будь-який нетривіальний додаток без використання зовнішніх залежностей стає все складніше, а то й неможливо.

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

Кроляча нора справді дуже глибока.

Якщо ми почнемо думати про те, від чого залежать наші веб-програми, легко думати про десяток і більше, ще не дійшовши до коду:

  • Потужність
  • Підключення
  • Брандмауер
  • DNS
  • Серверне обладнання (CPU, Disk, Ram,…)
  • Охолодження
  • Платформа віртуалізації
  • Контейнерна платформа
  • Операційна система
  • Платформа веб-сервера
  • Платформа сервера додатків
  • Веб-браузер

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

У коді є три типи залежностей:

1. Залежності, які ми контролюємо

Це код, написаний і належить нам або нашій організації.

2. Залежності, які ми не контролюємо

Це код, написаний стороннім постачальником або спільнотою програмного забезпечення з відкритим кодом.

3. Залежності, що видаляються

Це залежності коду, від яких залежать незалежні залежності коду. (Скажіть це три рази швидше!)

Ми будемо говорити головним чином про залежності, які ми не контролюємо .

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

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

Чому незалежні кодові залежності хороші

Велика частина вашої веб-програми існує для вирішення загальних проблем: автентифікація, авторизація, доступ до даних, обробка помилок, навігація, реєстрація, шифрування, відображення списку елементів, перевірка вводу форми тощо ...

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

Ви хочете зосередитись на коді, який або вирішує незвичайну проблему, або вирішує загальну проблему незвично. Саме це робить вашу програму цінною: код, який реалізує ділові правила, унікальні лише для вашого додатка, - «секретний соус».

Алгоритм пошуку та ранжування сторінок Google, фільтрація часової шкали Facebook, розділ Netflix "рекомендується для вас" та алгоритми стиснення даних - кодом усіх цих функцій є "секретний соус".

Код третьої сторони - у вигляді бібліотек - дозволяє швидко реалізувати ці комерційні функції вашого додатка, щоб ви могли зосереджуватися на своєму "секретному соусі".

Чому залежності сторонніх кодів погані

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

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

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

Колишній мій клієнт створив свій додаток за допомогою постачальника сервісних послуг, що належить Facebook, під назвою Parse. Вони використовували клієнтську бібліотеку JavaScript, надану Parse, для використання служби Parse. В процесі цього вони щільно пов’язали весь свій код - включаючи код “секретного соусу” - до цієї бібліотеки.

Через три місяці після першого запуску продукту мого клієнта - саме тоді, коли вони почали отримувати хорошу тягу з реальними платними клієнтами - Parse оголосив, що він закривається.

Тепер, замість того, щоб зосередитися на повторенні свого продукту та зростанні клієнтської бази, мій клієнт повинен був розібратися, як перейти на власну версію Parse з відкритим кодом або повністю замінити Parse.

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

Балансування хорошого і поганого

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

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

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

Це добре звучить на папері. Коли у вас є самостійні залежності, які надають лише кілька функцій, це зробить трюк. Але все може стати негарно швидко.

Чи можете ви уявити, що вам потрібно обернути всю бібліотеку React (включаючи JSX) перед використанням будь-якої з них? Як щодо обгортання jQuery, або Angular, або Spring Spring в Java? Це швидко стає кошмаром.

У наші дні я рекомендую більш тонкий підхід ...

Для кожної залежності, яку ви хочете додати до своєї кодової бази, оцініть рівень ризику, який вона створить, помноживши два фактори:

  1. Ймовірність того, що залежність зміниться матеріально.
  2. Розмір шкоди, яку істотна зміна залежності завдасть вашій заявці.

Бібліотека чи фреймворк сторонніх розробників рідше змінюється, коли виконуються деякі або всі наступні речі:

  • Він існує вже кілька років і мав кілька основних релізів.
  • Він широко використовується багатьма комерційними програмами.
  • Він має активну підтримку великої організації - бажано, компанії з назвами, що називається, або установи.

Стороння бібліотека або фреймворк завдасть меншої шкоди вашому додатку, якщо виконуються деякі або всі наступні речі:

  • Він використовується лише невеликою частиною вашої програми, а не використовується повсюдно.
  • Код, який залежить від нього, не є частиною того “секретного соусу”, про який я говорив раніше.
  • Видалення вимагає мінімальних змін у вашій кодовій базі.
  • Уся ваша програма дуже мала і її можна швидко переписати. (Будьте обережні з цим - це рідко дуже довго.)

Чим щось є більш ризикованим, тим більша ймовірність того, щоб ви його загорнули або взагалі уникали.

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

Іноді це означає сказати «ні» сторонній бібліотеці, яку ви вважаєте справді крутою, або яку ви дійсно хочете використовувати з тієї чи іншої причини. Будь сильним. Повірте мені, це окупиться. Просто запитайте всіх людей, які вклали великі кошти в перший реліз Angular, або мого колишнього клієнта, який використовував Parse скрізь. Це не весело. Повір мені.

Якщо говорити про веселощі, погляньте на це ...

На зображенні вище наведено графік залежностей для програми під назвою TinyTag Explorer.

Створення графіку залежностей для ваших існуючих додатків - це чудовий спосіб зрозуміти рівень ризику, який вводять ваші залежності. Я склав список безкоштовних інструментів для створення графіків, подібних до вищезазначених, на різних мовах, включаючи JavaScript, C #, Java, PHP та Python. Ви можете отримати його тут.

Допоможіть мені допомогти іншим

Я хочу допомогти якомога більшій кількості розробників, поділившись з ними своїми знаннями та досвідом. Будь ласка, допоможіть мені, натиснувши кнопку ❤ рекомендувати (зелене серце) нижче.

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