”förändring är den enda konstanten …” – Heraclitus (filosof)
verktygen, biblioteken och ramarna vi använder för att bygga våra webbapplikationer idag skiljer sig drastiskt från de vi använde för bara några korta år sedan.
om några korta år kommer de flesta av dessa tekniker att ha förändrats dramatiskt igen. Än, många av oss gör dessa till en central, oupplöslig del av våra appar.
vi importerar, använder och ärver från månadens ramar som om de alla kommer att vara runt och oförändrade för alltid. Det är de inte. Och det är ett problem.
efter 20 + år av att utveckla, designa och architecting webbapplikationer, jag har kommit att uppskatta två viktiga sanningar:
- externa beroenden utgör ett stort hot mot långsiktig stabilitet och lönsamhet för alla applikationer.
- det blir allt svårare — om inte omöjligt-att bygga någon form av icke-trivial app utan att utnyttja externa beroenden.
den här artikeln handlar om att förena dessa två sanningar så att våra appar har störst chans att överleva på lång sikt.
kaninhålet är verkligen mycket djupt.
om vi börjar tänka på alla saker som våra webbappar beror på är det lätt att tänka på ett dussin eller mer innan vi ens kommer till koden:
- ström
- anslutning
- brandvägg
- DNS
- serverhårdvara (CPU, Disk, Ram, …)
- kylning
- virtualiseringsplattform
- Containerplattform
- operativsystem
- Webbserverplattform
- Appserverplattform
- webbläsare
som utvecklare är det bra att vara medveten om dessa saker, men det finns ofta inte mycket vi kan göra åt dem. Så, låt oss ignorera dem för nu och prata bara om koden.
i kod finns tre typer av beroenden:
1. Beroenden vi kontrollerar
detta är kod skriven och ägs av oss eller vår organisation.
2. Beroenden vi kontrollerar inte
detta är kod skriven av en tredje part eller öppen källkod.
3. Beroenden när du har tagit bort
dessa är de kodberoenden som våra tredjepartskodberoenden beror på. (Säg det tre gånger snabbt!)
vi kommer främst att prata om beroenden som vi inte kontrollerar.
beroenden vi kontrollerar och beroenden när de har tagits bort kan fortfarande orsaka huvudvärk, men när det gäller beroenden vi kontrollerar bör vi kunna ingripa direkt och mildra eventuella problem.
när det gäller beroenden som en gång tagits bort kan vi vanligtvis lita på en tredje part för att ta hand om det för oss, eftersom de också är beroende av dessa.
varför kodberoende från tredje part är bra
en stor del av din webbapplikation finns för att lösa vanliga problem: autentisering, auktorisering, dataåtkomst, felhantering, navigering, loggning, kryptering, visning av en lista med objekt, validering av formuläringångar och så vidare…
oavsett vilken teknik stack du använder, det finns en god chans att gemensamma lösningar på dessa problem finns, och finns som bibliotek som du enkelt kan skaffa och plug-in till din kodbas. Att skriva något av det här helt från början är i allmänhet slöseri med tid.
du vill koncentrera dig på kod som antingen löser ett ovanligt problem eller löser ett vanligt problem på ett ovanligt sätt. Det är det som gör din ansökan värdefull: koden som implementerar affärsreglerna som är unika för din app ensam — ”secret sauce.”
Googles sök— och sidrankningsalgoritm, Facebook: s tidslinjefiltrering, Netflix avsnitt” rekommenderas för dig ”och datakomprimeringsalgoritmer-koden bakom alla dessa funktioner är” secret sauce.”
tredjepartskod-i form av bibliotek — låter dig snabbt implementera de commoditiserade funktionerna i din app, så att du kan hålla fokus på din ” hemliga sås.”
varför tredjepartskodberoenden är dåliga
ta en titt på någon icke-trivial webbapp byggd under de senaste åren och du kommer att bli helt förvånad över mängden kod som faktiskt kommer från ett tredjepartsbibliotek. Vad händer om ett eller flera av dessa tredjepartsbibliotek förändras drastiskt, eller försvinner eller går sönder?
om det är öppen källkod, kanske du kan fixa det själv. Men hur väl förstår du all kod i det biblioteket du inte äger? En stor anledning till att du använder ett bibliotek i första hand är att få fördelarna med koden utan att behöva oroa dig för alla detaljer. Men nu är du fast. Du har helt bundit din förmögenhet till dessa beroenden som du inte äger och inte kontrollerar.
kanske tror du att jag överdriver, eller talar ur en rent akademisk synvinkel. Låt mig försäkra er — Jag har dussintals exempel på kunder som helt snookered sig genom att bädda in tredjepartskod för hårt i sin app. Här är bara ett nytt exempel…
en tidigare kund av mig byggde sin app med en Backend-as-a-Service-leverantör som ägs av Facebook, kallad Parse. De använde ett JavaScript-klientbibliotek som tillhandahålls av Parse för att konsumera Parse-tjänsten. I processen kopplade de tätt all sin kod-inklusive” secret sauce ” – koden-till detta bibliotek.
tre månader efter min kunds första produktlansering — precis som de började få lite bra dragkraft med riktiga betalande kunder — meddelade Parse att det stängdes av.
nu istället för att fokusera på att iterera på sin produkt och växa sin kundbas, var min klient tvungen att ta reda på hur man antingen migrerar till en egen värd, öppen källkodsversion av Parse eller ersätter Parse helt.
störningen som detta orsakade för en ung, nybliven applikation var så stor att min klient så småningom skrotade appen helt.
balansera det goda och det dåliga
för flera år sedan var min go-to-lösning för att övervinna riskerna och samtidigt behålla fördelarna med tredjepartsbibliotek att sätta ihop dem med Adaptermönstret.
i huvudsak sätter du in tredjepartskoden i en adapterklass eller modul som du har skrivit. Detta fungerar sedan för att exponera funktionerna i tredjepartsbiblioteken på ett sätt som du kontrollerar.
med det här mönstret, om ett tredjepartsbibliotek eller ramverk ändras eller försvinner, behöver du bara fixa lite adapterkod. Resten av din app förblir intakt.
detta låter bra på papper. När du har fristående beroenden som bara ger några funktioner, kommer detta att göra susen. Men saker kan bli fula snabbt.
kan du tänka dig att behöva packa in hela React-biblioteket (inklusive JSX) innan du använder något av det? Vad sägs om att förpacka jQuery, eller Angular, eller Spring framework i Java? Detta blir snabbt en mardröm.
dessa dagar rekommenderar jag ett mer nyanserat tillvägagångssätt…
för varje beroende du vill lägga till i din kodbas, utvärdera risknivån det kommer att introducera genom att multiplicera två faktorer:
- sannolikheten för att beroendet kommer att förändras på ett materiellt sätt.
- mängden skada som en väsentlig förändring av beroendet skulle göra för din ansökan.
ett tredjepartsbibliotek eller ramverk är mindre benägna att förändras när några eller alla av följande saker är sanna:
- det har funnits i flera år och har haft flera stora utgåvor.
- det används ofta av många kommersiella applikationer.
- den har aktivt stöd av en stor organisation — helst ett känt namn företag eller institution.
ett tredjepartsbibliotek eller ramverk kommer att göra mindre skada på din ansökan när några eller alla av följande saker är sanna:
- det används bara av en liten del av din ansökan, snarare än att användas hela tiden.
- koden som beror på den är inte en del av den ”hemliga såsen” jag pratade om tidigare.
- att ta bort det kräver minimala ändringar i din kodbas.
- hela din ansökan är mycket liten och kan skrivas om snabbt. (Var försiktig med den här — det är sällan sant för mycket länge.)
ju mer riskfyllda något är, desto mer sannolikt bör du vara att slå in det eller undvika det helt och hållet.
när det gäller koden som verkligen är central för värdepropositionen för din ansökan —din ”hemliga sås” — måste du vara extremt skyddande för den. Gör den koden så oberoende som möjligt. Om du absolut behöver använda ett beroende, överväga att injicera det snarare än att direkt referera till det. Även då, var försiktig.
ibland betyder det att säga ”nej” till ett tredjepartsbibliotek som du tycker är riktigt coolt, eller som du verkligen vill använda av en eller annan anledning. Var stark. Lita på mig, det kommer att löna sig. Fråga bara alla de människor som investerade mycket i den allra första utgåvan av Angular, eller min tidigare klient som använde Parse överallt. Det är inte kul. Tro mig.
på tal om kul, ta en titt på detta…
bilden ovan är beroendediagrammet för ett program som heter TinyTag Explorer.
att skapa ett beroendediagram för dina befintliga appar är ett bra sätt att förstå risknivån som introduceras av dina beroenden. Jag har sammanställt en lista med gratis verktyg för att generera grafer som liknar ovanstående på olika språk, inklusive JavaScript, C#, Java, PHP och Python. Du kan få det här.
Hjälp mig att hjälpa andra
jag vill hjälpa så många utvecklare som jag kan genom att dela min kunskap och erfarenhet med dem. Snälla hjälp mig genom att klicka på knappen rekommenderar att du rekommenderar (grönt hjärta) nedan.
slutligen, glöm inte att ta din lista över Gratis beroende graf generatorer här.