Dependențele de cod sunt diavolul.

Dependențele tale te vor arde de fiecare dată.
„Schimbarea este singura constantă ...” - Heraclit (Filozof)

Instrumentele, bibliotecile și cadrele pe care le folosim pentru a construi aplicațiile noastre de astăzi sunt drastic diferite de cele pe care le-am folosit acum câțiva ani.

În câțiva ani de acum încolo, majoritatea acestor tehnologii se vor schimba din nou dramatic. Cu toate acestea, mulți dintre noi facem din acestea o parte centrală, inextricabilă a aplicațiilor noastre.

Importăm, folosim și moștenim din cadrele cu aroma lunii ca și cum toate vor fi în jur și vor fi neschimbate pentru totdeauna. Ei bine ... nu sunt. Și asta este o problemă.

După peste 20 de ani de dezvoltare, proiectare și arhitectură de aplicații web, am ajuns să apreciez două adevăruri importante:

  1. Dependențele externe reprezintă o mare amenințare la stabilitatea pe termen lung și viabilitatea oricărei aplicații.
  2. Este din ce în ce mai dificil - dacă nu chiar imposibil - să creezi orice fel de aplicație non-banală fără a folosi dependențele externe.

Acest articol este despre împăcarea acestor două adevăruri, astfel încât aplicațiile noastre să aibă șansele cele mai mari de supraviețuire pe termen lung.

Gaura iepurelui este într-adevăr foarte adâncă.

Dacă începem să ne gândim la toate lucrurile de care depind aplicațiile noastre web, este ușor să ne gândim la o duzină sau mai multe înainte de a ajunge chiar la cod:

  • Putere
  • Conectivitate
  • Firewall
  • DNS
  • Hardware Hardware (CPU, Disc, Ram, ...)
  • Răcire
  • Platforma de virtualizare
  • Platforma containere
  • Sistem de operare
  • Platforma server web
  • Platforma server de aplicații
  • Browser web

Ca dezvoltatori, este bine să fim conștienți de aceste lucruri, dar deseori nu putem face multe despre ele. Deci, să le ignorăm deocamdată și să vorbim doar despre cod.

În cod, există trei tipuri de dependențe:

1. Dependențe pe care le controlăm

Acesta este codul scris și deținut de noi sau organizația noastră.

2. Dependențe pe care nu le controlăm

Acesta este codul scris de către un furnizor terț sau o comunitate software liberă.

3. Dependențele au fost eliminate odată

Acestea sunt dependențele de cod de care depind dependențele noastre de cod ale unei terțe părți. (Spune asta de trei ori rapid!)

Vom vorbi în principal despre dependențe pe care nu le controlăm.

Dependențele pe care le controlăm și dependențele odată înlăturate pot provoca încă dureri de cap, dar în cazul dependențelor pe care le controlăm, ar trebui să fim capabili să intervenim direct și să diminuăm orice probleme.

În cazul dependențelor îndepărtate, putem, de obicei, să ne bazăm pe o terță parte care să aibă grijă de aceasta pentru noi, din moment ce ei depind și de acestea.

De ce dependențele de cod ale terților sunt bune

O mare parte din aplicația dvs. web există pentru a rezolva probleme comune: autentificare, autorizare, acces la date, gestionarea erorilor, navigare, logare, criptare, afișarea unei liste de elemente, validarea intrărilor de formular, etc.

Indiferent de stiva tehnologică pe care o utilizați, există șanse mari să existe soluții comune la aceste probleme și sunt disponibile ca biblioteci pe care le puteți achiziționa și conecta cu ușurință la baza dvs. de cod. Scrierea oricărei chestii complet de la zero este, în general, o pierdere de timp.

Doriți să vă concentrați pe un cod care fie rezolvă o problemă neobișnuită, fie rezolvă o problemă comună într-un mod neobișnuit. Asta face ca aplicația dvs. să fie valoroasă: codul care implementează regulile de afaceri care sunt unice doar pentru aplicația dvs. - „sosul secret”.

Algoritmul de căutare și clasare a paginilor Google, filtrarea cronologiei Facebook, secțiunea „recomandată pentru tine” de Netflix și algoritmii de compresiune a datelor - codul din spatele tuturor acestor funcții este „sosul secret”.

Codul terțelor părți - sub formă de biblioteci - vă permite să implementați rapid acele caracteristici personalizate ale aplicației dvs., astfel încât să puteți rămâne concentrat pe „sosul tău secret”.

De ce dependențele de cod ale unor terțe părți sunt rele

Aruncați o privire la orice aplicație web non-banală construită în ultimii doi ani și veți fi absolut uimiți de cantitatea de cod care provine de fapt dintr-o bibliotecă terță parte. Ce se întâmplă dacă una sau mai multe dintre acele biblioteci terțe se schimbă drastic sau dispare sau se rupe?

Dacă este open-source, poate o puteți remedia singur. Dar cât de bine înțelegeți tot codul din biblioteca aceea pe care nu o dețineți? Un mare motiv pentru care utilizați o bibliotecă în primul rând este să obțineți beneficiile codului, fără a fi nevoie să vă faceți griji pentru toate detaliile. Dar acum ești blocat. Ți-ai legat complet averea de aceste dependențe pe care nu le deții și nu le controlezi.

Nu vă faceți griji, până la sfârșitul acestui articol, veți găsi o nouă speranță.

Poate crezi că exagerez sau vorbesc din punct de vedere pur academic. Permiteți-vă să vă asigur - am zeci de exemple de clienți care s-au strecurat complet prin încorporarea prea strânsă a codului terților în aplicația lor. Iată doar un exemplu recent ...

Un fost client de-al meu a construit aplicația folosind un furnizor de Backend-as-a-Service deținut de Facebook, numit Parse. Au folosit o bibliotecă de clienți JavaScript furnizată de Parse pentru a consuma serviciul Parse. În acest proces, ei au cuplat strâns toate codurile lor - inclusiv codul „sos secret” - la această bibliotecă.

La trei luni de la lansarea inițială a produsului meu de client - la fel cum au început să obțină o tracțiune bună cu clienții reali și plătitori - Parse a anunțat că se va opri.

Acum, în loc să se concentreze pe iterarea produsului lor și creșterea bazei de clienți, clientul meu trebuia să-și dea seama cum să migreze către o versiune open-source a lui Parse, sau să înlocuiască Parse complet.

Întreruperea cauzată de o aplicație tânără și plină de forță a fost atât de mare încât clientul meu a scos în cele din urmă aplicația în întregime.

Echilibrarea binelui și răului

Cu câțiva ani în urmă, soluția mea de a depăși riscurile, păstrând avantajele bibliotecilor terțe a fost să le înfășurați folosind modelul adaptorului.

În esență, înfășurați codul terților într-o clasă sau modul adaptor pe care l-ați scris. Apoi funcționează pentru a expune funcțiile bibliotecilor terțe într-un mod pe care îl controlezi.

Folosind acest model, dacă o bibliotecă sau un cadru terță parte se schimbă sau pleacă, nu trebuie decât să repari un pic de cod adaptor. Restul aplicației dvs. rămâne intact.

Schema modelului adaptorului de la Dofactory.com

Acest lucru sună bine pe hârtie. Când aveți dependențe independente care oferă doar câteva funcții, acest lucru va face trucul. Dar lucrurile pot deveni urât repede.

Vă puteți imagina că trebuie să înfășurați întreaga bibliotecă React (inclusiv JSX) înainte de a folosi ceva? Ce zici de ambalarea jQuery, sau Angular, sau cadrul Spring în Java? Acest lucru devine repede un coșmar.

În aceste zile vă recomand o abordare mai nuanțată ...

Pentru fiecare dependență pe care doriți să o adăugați la baza dvs. de cod, evaluați nivelul de risc pe care îl va introduce, înmulțind doi factori:

  1. Probabilitatea ca dependența să se schimbe în mod semnificativ.
  2. Cantitatea de daune pe care o va aduce o modificare materială a dependenței la cererea dvs.

O bibliotecă sau un cadru terță parte este mai puțin probabil să se schimbe atunci când unele sau toate următoarele lucruri sunt adevărate:

  • A trecut de câțiva ani și a avut mai multe versiuni importante.
  • Este utilizat pe scară largă de multe aplicații comerciale.
  • Are sprijinul activ al unei organizații mari - de preferință a unei companii sau instituții cu nume gospodăresc.

O bibliotecă terță parte sau un cadru va face mai puține daune aplicației dvs. atunci când unele sau toate următoarele lucruri sunt adevărate:

  • Este folosit doar de o porțiune mică din aplicația dvs., mai degrabă decât să fie utilizat în întregime.
  • Codul de care depinde nu face parte din acel „sos secret” despre care am vorbit mai devreme.
  • Îndepărtarea necesită modificări minime ale bazei de coduri.
  • Întreaga aplicație este foarte mică și poate fi rescrisă rapid. (Fii atent cu acesta - rareori este adevărat de foarte mult timp.)

Cu cât este ceva mai riscant, cu atât este mai probabil să fiți înfășurat sau evitat cu totul.

Când vine vorba de codul care este într-adevăr esențial pentru propunerea de valoare a aplicației dvs. - „sosul tău secret” - trebuie să fii extrem de protector împotriva lui. Faceți codul respectiv cât mai independent. Dacă trebuie să utilizați absolut o dependență, luați în considerare injectarea acesteia, mai degrabă decât referirea directă a acesteia. Chiar și atunci, fii atent.

Uneori, acest lucru înseamnă să spui „nu” unei biblioteci terțe părți despre care crezi că este într-adevăr misto, sau pe care vrei să o folosești cu adevărat dintr-un motiv sau altul. Fii puternic. Credeți-mă, va plăti. Întreabă-i pe toți acei oameni care au investit foarte mult în prima versiune a lui Angular, sau fostul meu client care a folosit Parse peste tot. Nu este distractiv. Crede-mă.

Vorbind de distracție, aruncă o privire la acest ...

Graficul de dependență pentru exploratorul TinyTag

Imaginea de mai sus este graficul de dependență pentru o aplicație numită TinyTag Explorer.

Generarea unui grafic de dependență pentru aplicațiile dvs. existente este o modalitate excelentă de a înțelege nivelul de risc introdus de dependențele dvs. Am creat o listă de instrumente gratuite pentru generarea de grafice similare celor de mai sus într-o varietate de limbi, inclusiv JavaScript, C #, Java, PHP și Python. Puteți obține aici.

Ajută-mă să-i ajut pe ceilalți

Vreau să ajut cât mai mulți dezvoltatori, împărtășind cunoștințele și experiența mea cu ei. Vă rugăm să mă ajutați făcând clic pe butonul ❤ recomand (inima verde) de mai jos.

În cele din urmă, nu uitați să vă ocupați de generatoarele de grafice gratuite de dependență aici.