“forandring er den eneste konstante …” – Heraclitus (filosof)
de værktøjer, biblioteker og rammer, vi bruger til at opbygge vores internetapplikationer i dag, er drastisk forskellige fra dem, vi brugte for kun få korte år siden.
om få år vil de fleste af disse teknologier have ændret sig dramatisk igen. Endnu, mange af os gør disse til en central, uløselig del af vores apps.
vi importerer, bruger og arver fra månedens smagsrammer, som om de alle vil være omkring og uændrede for evigt. Det er de ikke. Og det er et problem.
efter 20 + års udvikling, design og arkitektur af internetapplikationer er jeg kommet til at sætte pris på to vigtige sandheder:
- eksterne afhængigheder udgør en stor trussel mod den langsigtede stabilitet og levedygtighed af enhver applikation.
- det bliver stadig vanskeligere — hvis ikke umuligt — at opbygge nogen form for ikke-triviel app uden at udnytte eksterne afhængigheder.
denne artikel handler om at forene disse to sandheder, så vores apps har den største chance for langsigtet overlevelse.
kaninhullet er faktisk meget dybt.
hvis vi begynder at tænke på alle de ting, vores apps afhænger af, er det let at tænke på et dusin eller mere, før vi endda kommer til koden:
- strøm
- forbindelse
- DNS
- serverudstyr (CPU, Disk, Ram,…)
- køling
- virtualiseringsplatform
- Containerplatform
- operativsystem
- Internetserverplatform
- Appserverplatform
- internetserver
som udviklere er det godt at være opmærksom på disse ting, men der er ofte ikke meget, vi kan gøre ved dem. Så lad os ignorere dem for nu og kun tale om koden.
i kode er der tre slags afhængigheder:
1. Afhængigheder vi kontrollerer
dette er kode skrevet og ejet af os eller vores organisation.
2. Afhængigheder vi kontrollerer ikke
dette er kode skrevet af en tredjepartsleverandør eller et open source-programfællesskab.
3. Afhængigheder når fjernet
dette er de kodeafhængigheder, som vores tredjeparts kodeafhængigheder afhænger af. (Sig det tre gange hurtigt!)
vi skal primært tale om afhængigheder, vi ikke kontrollerer.
afhængigheder, vi kontrollerer, og afhængigheder, når de først er fjernet, kan stadig forårsage hovedpine, men i tilfælde af afhængigheder, vi kontrollerer, skal vi være i stand til direkte at gribe ind og afbøde eventuelle problemer.
i tilfælde af afhængigheder, når de først er fjernet, kan vi normalt stole på, at en tredjepart tager sig af det for os, da de også er afhængige af disse.
hvorfor tredjeparts kodeafhængigheder er gode
en stor del af din internetapplikation findes for at løse almindelige problemer: godkendelse, autorisation, dataadgang, fejlhåndtering, navigation, logning, kryptering, visning af en liste over emner, validering af formularindgange og så videre…
uanset hvilken teknologi stack du bruger, er der en god chance for, at der findes fælles løsninger på disse problemer, og er tilgængelige som biblioteker, som du nemt kan erhverve og plug-in til din kodebase. At skrive noget af dette helt fra bunden er generelt spild af tid.
du vil koncentrere dig om kode, der enten løser et usædvanligt problem eller løser et almindeligt problem på en usædvanlig måde. Det er det, der gør din ansøgning værdifuld: koden, der implementerer de forretningsregler, der er unikke for din app alene — den “hemmelige sauce.”
Googles søge— og siderangeringsalgoritme, Facebooks tidslinjefiltrering, Facebook ‘s Sektion” anbefalet til dig “og datakomprimeringsalgoritmer-koden bag alle disse funktioner er” hemmelig sauce.”
Tredjepartskode-i form af biblioteker — giver dig mulighed for hurtigt at implementere de kommercielle funktioner i din app, så du kan holde fokus på din ” hemmelige sauce.”
hvorfor tredjeparts kodeafhængigheder er dårlige
se på enhver ikke-triviel NetApp, der er bygget i de sidste par år, og du vil blive helt forbløffet over mængden af kode, der faktisk kommer fra et tredjepartsbibliotek. Hvad hvis et eller flere af disse tredjepartsbiblioteker ændrer sig drastisk, eller forsvinder, eller går i stykker?
hvis det er open source, kan du måske rette det selv. Men hvor godt forstår du al koden i det Bibliotek, du ikke ejer? En stor grund til, at du bruger et bibliotek i første omgang, er at få fordelene ved koden uden at skulle bekymre dig om alle detaljerne. Men nu sidder du fast. Du har helt bundet din formue til disse afhængigheder, som du ikke ejer og ikke kontrollerer.
måske tror du, Jeg overdriver eller taler fra et rent akademisk synspunkt. Lad mig forsikre dig — jeg har snesevis af eksempler på klienter, der helt snookered sig selv ved at indlejre tredjeparts kode for stramt ind i deres app.
en tidligere klient af mig byggede deres app ved hjælp af en Backend-as-a-service udbyder ejet af Facebook, kaldet Parse. De brugte et JavaScript-klientbibliotek leveret af Parse til at forbruge Parse-tjenesten. I processen koblede de tæt hele deres kode — inklusive “secret sauce” — koden-til dette bibliotek.
tre måneder efter min klients første produktlancering — ligesom de begyndte at få noget godt trækkraft med rigtige betalende kunder — Parse meddelte, at det lukkede ned.
nu i stedet for at fokusere på at gentage deres produkt og udvide deres kundebase, måtte min klient finde ud af, hvordan man enten migrerer til en selvhostet open source-version af Parse eller erstatter Parse helt.
forstyrrelsen dette forårsagede for en ung, ny applikation var så enorm, at min klient til sidst skrottede appen helt.
balance mellem det gode og det dårlige
for flere år siden var min go-to-løsning til at overvinde risiciene og samtidig bevare fordelene ved tredjepartsbiblioteker at pakke dem ved hjælp af Adaptermønsteret.
i det væsentlige pakker du tredjepartskoden i en adapterklasse eller et modul, du har skrevet. Dette fungerer derefter for at afsløre funktionerne i tredjepartsbibliotekerne på en måde, som du kontrollerer.
brug af dette mønster, hvis et tredjepartsbibliotek eller en ramme ændres eller forsvinder, skal du kun rette en smule adapterkode. Resten af din app forbliver intakt.
det lyder godt på papir. Når du har selvstændige afhængigheder, der kun giver et par funktioner, vil dette gøre tricket. Men tingene kan blive grimme hurtigt.
kan du forestille dig at skulle pakke hele React-biblioteket, før du bruger noget af det? Hvad med indpakning af jøns, eller vinkel, eller Fjederrammen i Java? Dette bliver hurtigt et mareridt.
i disse dage anbefaler jeg en mere nuanceret tilgang…
for hver afhængighed, du vil føje til din kodebase, skal du evaluere risikoniveauet, det vil introducere ved at multiplicere to faktorer:
- sandsynligheden for, at afhængigheden vil ændre sig på en materiel måde.
- mængden af skade en væsentlig ændring af afhængigheden ville gøre for din ansøgning.
et tredjepartsbibliotek eller-ramme er mindre tilbøjelige til at ændre sig, når nogle eller alle følgende ting er sande:
- det har eksisteret i flere år og har haft flere store udgivelser.
- det bruges i vid udstrækning af mange kommercielle applikationer.
- det har aktiv støtte fra en stor organisation — helst et husstands navn firma eller institution.
et tredjepartsbibliotek eller en ramme vil gøre mindre skade på din ansøgning, når nogle eller alle følgende ting er sande:
- det bruges kun af en lille del af din ansøgning, snarere end at blive brugt hele vejen igennem.
- koden, der afhænger af den, er ikke en del af den “hemmelige sauce”, jeg talte om tidligere.
- fjernelse af det kræver minimale ændringer i din kodebase.
- hele din ansøgning er meget lille og kan omskrives hurtigt. (Vær forsigtig med denne — det er sjældent sandt i meget lang tid.)
jo mere risikabelt noget er, jo mere sandsynligt bør du være at pakke det eller undgå det helt.
når det kommer til den kode, der virkelig er central for værdipropositionen for din ansøgning —din “hemmelige sauce” — skal du være ekstremt beskyttende over for den. Gør denne kode så uafhængig som muligt. Hvis du absolut har brug for at bruge en afhængighed, skal du overveje at injicere den i stedet for direkte at henvise til den. Selv da, vær forsigtig.
nogle gange betyder det at sige “nej” til et tredjepartsbibliotek, som du synes er rigtig sejt, eller som du virkelig vil bruge af en eller anden grund. Vær stærk. Tro mig, det vil betale sig. Bare spørg alle de mennesker, der investerede meget i den allerførste udgivelse af Angular, eller min tidligere klient, der brugte Parse overalt. Det er ikke sjovt. Tro mig.
Apropos sjov, tag et kig på dette…
billedet ovenfor er afhængighedsgrafen for et program kaldet TinyTag Stifinder.
generering af en Afhængighedsgraf for dine eksisterende apps er en fantastisk måde at forstå risikoniveauet, der introduceres af dine afhængigheder. Jeg har sammensat en liste over gratis værktøjer til generering af grafer svarende til ovenstående på en række sprog, herunder JavaScript, C#, Java, PHP og Python. Du kan få det her.
Hjælp mig med at hjælpe andre
jeg vil hjælpe så mange udviklere som muligt ved at dele min viden og erfaring med dem. Hjælp mig venligst ved at klikke på knappen til at anbefale (grønt hjerte) nedenfor.
endelig, glem ikke at få fat i din liste over gratis afhængighed graf generatorer her.