Кодовите зависимости са дяволът.

„Промяната е единствената константа ...“ - Хераклит (философ)

Инструментите, библиотеките и рамките, които използваме за изграждането на нашите уеб приложения днес, са драстично различни от тези, които използвахме само преди няколко кратки години.

След няколко кратки години повечето от тези технологии отново ще се променят драстично. И все пак много от нас правят тези централна, неразривна част от нашите приложения.

Внасяме, използваме и наследяваме от рамките на аромата на месеца, сякаш всички те ще бъдат наоколо и непроменени завинаги. Ами ... не са. И това е проблем.

След повече от 20 години разработване, проектиране и архитиране на уеб приложения, осъзнах две важни истини:

  1. Външните зависимости представляват голяма заплаха за дългосрочната стабилност и жизнеспособност на всяко приложение.
  2. Все по-трудно е, ако не и невъзможно, да се изгради всякакъв вид нетривиално приложение, без да се използват външни зависимости.

Тази статия е за съвместяването на тези две истини, така че нашите приложения да имат най-голям шанс за дългосрочно оцеляване.

Заешката дупка наистина е много дълбока.

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

  • Мощност
  • Свързаност
  • Защитна стена
  • DNS
  • Сървърния хардуер (CPU, Disk, Ram, ...)
  • Охлаждане
  • Платформа за виртуализация
  • Контейнерна платформа
  • Операционна система
  • Платформа за уеб сървър
  • Платформа за сървър на приложения
  • Уеб браузър

Като разработчици е добре да сме наясно с тези неща, но често не можем да направим много за тях. И така, нека засега да ги игнорираме и да говорим само за кода.

В кода има три вида зависимости:

1. Зависимости, които контролираме

Това е код, написан и притежаван от нас или нашата организация.

2. Зависимости, които не контролираме

Това е код, написан от трета страна доставчик или софтуерна общност с отворен код.

3. Веднъж премахнати зависимости

Това са зависимостите от кода, от които зависят зависимостите на кода ни от трети страни. (Кажете това три пъти бързо!)

Ще говорим главно за зависимости, които не контролираме .

Зависимостите, които контролираме, и зависимостите, след като бъдат премахнати, все още могат да причинят главоболие, но в случай на зависимости, които контролираме, трябва да можем директно да се намесим и да смекчим всички проблеми.

В случай на зависимости, след като бъдат премахнати, обикновено можем да разчитаме на трета страна, която да се погрижи за нас, тъй като и те са зависими от тях.

Защо зависимостите на кода на трети страни са добри

Голяма част от вашето уеб приложение съществува за решаване на често срещани проблеми: удостоверяване, упълномощаване, достъп до данни, обработка на грешки, навигация, регистриране, криптиране, показване на списък с елементи, валидиране на входове във формуляри и т.н. ...

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

Искате да се концентрирате върху код, който или решава необичаен проблем, или решава често срещан проблем по необичаен начин. Това прави приложението ви ценно: кодът, който прилага бизнес правилата, които са уникални само за приложението ви - „тайният сос“.

Алгоритъм на Google за търсене и класиране на страници, филтриране по времевата линия на Facebook, раздел „препоръчва се за вас“ на Netflix и алгоритми за компресиране на данни - кодът зад всички тези функции е „таен сос“

Кодът на трета страна - под формата на библиотеки - ви позволява бързо да внедрите тези кодифицирани функции на вашето приложение, така че да можете да останете фокусирани върху вашия „таен сос“.

Защо зависимостите на кода на трети страни са лоши

Разгледайте всяко нетривиално уеб приложение, създадено през последните няколко години, и ще бъдете абсолютно изумени от количеството код, което всъщност идва от библиотека на трета страна. Какво ще стане, ако една или повече от тези библиотеки на трети страни се променят драстично или изчезнат или се счупят?

Ако е с отворен код, може би можете да го поправите сами. Но колко добре разбирате целия код в тази библиотека, който не притежавате? Голяма причина, поради която на първо място използвате библиотека, е да се възползвате от предимствата на кода, без да се притеснявате за всички подробности. Но сега си заседнал. Напълно сте обвързали богатството си с тези зависимости, които не притежавате и не контролирате.

Може би си мислите, че преувеличавам или говоря от чисто академична гледна точка. Позволете ми да ви уверя - имам десетки примери за клиенти, които напълно са се подхлъзнали, като вграждат кода на трета страна твърде плътно в приложението си. Ето само един скорошен пример ...

Бивш мой клиент създаде приложението си с помощта на доставчик на услугата Backend-as-a-a-услуга, собственост на Facebook, наречена Parse. Те използваха клиентска библиотека на JavaScript, предоставена от Parse, за да консумират услугата Parse. В процеса те тесно свързаха целия си код - включително кода на „тайния сос“ - към тази библиотека.

Три месеца след първоначалното пускане на продукта на моя клиент - точно когато те започнаха да получават добро сцепление с реални, плащащи клиенти - Parse обяви, че се изключва.

Сега, вместо да се съсредоточи върху повторяването на техния продукт и да разшири клиентската си база, клиентът ми трябваше да измисли как да мигрира към самостоятелно хоствана версия на Parse с отворен код или да замени напълно Parse.

Прекъсването, причинено от младото, новопоявяващо се приложение, беше толкова голямо, че клиентът ми в крайна сметка премахна приложението изцяло.

Балансиране на доброто и лошото

Преди няколко години решението ми за преодоляване на рисковете, запазвайки предимствата на библиотеките на трети страни, беше да ги опаковам с помощта на адаптерния модел.

По същество обвивате кода на трета страна в клас или модул на адаптер, който сте написали. Тогава това работи, за да изложи функциите на библиотеките на трети страни по начин, който контролирате.

Използвайки този модел, ако библиотека или рамка на трета страна се промени или изчезне, трябва да поправите само малко код на адаптера. Останалата част от приложението ви остава непокътната.

Това звучи добре на хартия. Когато имате самостоятелни зависимости, които предоставят само няколко функции, това ще свърши работа. Но нещата могат да станат грозни бързо.

Можете ли да си представите, че трябва да обвиете цялата библиотека на React (включително JSX), преди да използвате някоя от нея? Какво ще кажете за опаковане на jQuery, или Angular, или Spring структурата в Java? Това бързо се превръща в кошмар.

В наши дни препоръчвам по-нюансиран подход ...

За всяка зависимост, която искате да добавите към вашата кодова база, оценете нивото на риска, което ще въведе, като умножите два фактора:

  1. Вероятността зависимостта да се промени по съществен начин.
  2. Размерът на щетите, които съществената промяна на зависимостта би причинила на вашето приложение.

Библиотека или рамка на трета страна е по-малко вероятно да се промени, когато някои или всички от следните неща са верни:

  • Той съществува от няколко години и има няколко големи издания.
  • Той се използва широко от много търговски приложения.
  • Той има активната подкрепа на голяма организация - за предпочитане компания или институция с име на домакинство.

Библиотека или рамка на трета страна ще нанесе по-малко щети на вашето приложение, когато някои или всички от следните неща са верни:

  • Той се използва само от малка част от вашето приложение, вместо да се използва навсякъде.
  • Кодът, който зависи от него, не е част от онзи „таен сос“, за който говорих по-рано.
  • Премахването му изисква минимални промени в кодовата ви база.
  • Цялото ви приложение е много малко и може да бъде пренаписано бързо. (Внимавайте с това - рядко е вярно за много дълго време.)

Колкото по-рисковано е нещо, толкова по-вероятно е да го увиете или да го избегнете изобщо.

Що се отнася до кода, който наистина е от основно значение за ценното предложение на вашето приложение - вашият „таен сос“ - трябва да сте изключително предпазливи към него. Направете този код възможно най-независим. Ако абсолютно трябва да използвате зависимост, помислете дали да не я инжектирате, вместо директно да я препращате. Дори тогава бъдете внимателни.

Понякога това означава да кажете „не“ на библиотека на трета страна, която смятате за наистина страхотна или която наистина искате да използвате по една или друга причина. Бъди силен. Повярвайте ми, ще се изплати. Просто попитайте всички онези хора, които са инвестирали сериозно в първото издание на Angular, или моя бивш клиент, който използва Parse навсякъде. Не е забавно. Вярвай ми.

Говорейки за забавление, погледнете това ...

Горното изображение е графика на зависимост за приложение, наречено TinyTag Explorer.

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

Помогнете ми да помогна на другите

Искам да помогна на колкото се може повече разработчици, като споделям своите знания и опит с тях. Моля, помогнете ми, като щракнете върху бутона ❤ препоръчвам (зелено сърце) по-долу.

И накрая, не забравяйте да вземете тук списъка си с безплатни генератори на графики за зависимост.