“verandering is de enige constante …” – Heraclitus (filosoof)
de tools, bibliotheken en frameworks die we vandaag gebruiken om onze webapplicaties te bouwen zijn drastisch verschillend van degenen die we slechts een paar jaar geleden gebruikten.
over een paar jaar zullen de meeste van deze technologieën opnieuw ingrijpend zijn veranderd. Toch maken velen van ons deze een centraal, onlosmakelijk onderdeel van onze apps.
WE importeren, gebruiken en erven van de flavor-of-the-month frameworks alsof ze allemaal voor altijd onveranderd blijven. Nou … dat zijn ze niet. En dat is een probleem.
na meer dan 20 jaar webapplicaties te hebben ontwikkeld, ontworpen en ontworpen, ben ik twee belangrijke waarheden gaan waarderen:
- externe afhankelijkheden vormen een grote bedreiging voor de stabiliteit en levensvatbaarheid op lange termijn van elke toepassing.
- het wordt steeds moeilijker-zo niet onmogelijk-om elke vorm van niet-triviale app te bouwen zonder gebruik te maken van externe afhankelijkheden.
dit artikel gaat over het verzoenen van deze twee waarheden, zodat onze apps hebben de grootste kans op overleven op lange termijn.
het konijnenhol is zeer diep.
als we beginnen te denken van alle dingen onze web apps afhankelijk van het is gemakkelijk om te denken van een dozijn of meer voordat we zelfs naar de code:
- Voeding
- Connect
- Firewall
- DNS
- Server Hardware (CPU, Schijf, Ram, …)
- Koeling
- Virtualisatie Platform
- Container Platform
- Operating Systeem
- Web Server Platform
- App Server Platform
- Web Browser
Als ontwikkelaars, het is goed om bewust te zijn van deze dingen, maar er is vaak niet veel wat we kunnen doen. Dus, laten we ze negeren voor nu en praten alleen over de code.
in code zijn er drie soorten afhankelijkheden:
1. Afhankelijkheden wij beheren
dit is code geschreven en eigendom van ons of onze organisatie.
2. Afhankelijkheden we hebben geen controle
dit is code geschreven door een derde partij leverancier of open-source software gemeenschap.
3. Afhankelijkheden eenmaal verwijderd
zijn dit de code afhankelijkheden waarvan onze derde partij code afhankelijkheden afhankelijk zijn. (Zeg dat drie keer snel!)
WE gaan het voornamelijk hebben over afhankelijkheden die we niet beheersen.
afhankelijkheden die we controleren en afhankelijkheden na verwijdering kunnen nog steeds hoofdpijn veroorzaken, maar in het geval van afhankelijkheden die we controleren, moeten we in staat zijn om direct in te grijpen en eventuele problemen te beperken.
in het geval van afhankelijkheden na verwijdering, kunnen we meestal vertrouwen op een derde partij om het voor ons te verzorgen, omdat ze ook afhankelijk zijn van deze.
waarom codeafhankelijkheden van derden goed zijn
een groot deel van uw webapplicatie bestaat om veelvoorkomende problemen op te lossen: authenticatie, autorisatie, toegang tot gegevens, foutafhandeling, navigatie, logging, encryptie, het weergeven van een lijst met items, het valideren van formulierinvoer, enzovoort…
ongeacht welke technologiestack u gebruikt, er is een goede kans dat er gemeenschappelijke oplossingen voor deze problemen bestaan, en beschikbaar zijn als bibliotheken die u gemakkelijk kunt verwerven en plug-in op uw codebase. Het schrijven van een van deze dingen volledig vanaf nul is over het algemeen een verspilling van tijd.
u wilt zich concentreren op code die een ongewoon probleem oplost of een veel voorkomend probleem op een ongewone manier oplost. Dat is wat uw applicatie waardevol maakt: de code die de bedrijfsregels implementeert die uniek zijn voor uw app alleen – de ” secret sauce.”
Google ’s Zoek-en pagina-ranking algoritme, Facebook’ s tijdlijn filtering, Netflix ‘s” aanbevolen voor u ” sectie en data compressie algoritmen— de code achter al deze functies is “secret sauce.”
Third-party code — in de vorm van bibliotheken-stelt u in staat om snel die commoditized functies van uw app te implementeren, zodat u zich kunt concentreren op uw “geheime saus.”
Why third-party code dependencies are bad
neem een kijkje op een niet-triviale web-app gebouwd in de laatste paar jaar en je zult absoluut verbaasd zijn over de hoeveelheid code die eigenlijk afkomstig is van een third-party bibliotheek. Wat als een of meer van die bibliotheken van derden drastisch verandert, of verdwijnt, of breekt?
als het open-source is, kunt u het misschien zelf repareren. Maar hoe goed begrijp je alle code in die bibliotheek die je niet bezit? Een grote reden waarom u gebruik maken van een bibliotheek in de eerste plaats is om de voordelen van de code te krijgen zonder zorgen te maken over alle details. Maar nu zit je vast. Je hebt je fortuin volledig verbonden aan deze afhankelijkheden die je niet bezit en niet beheerst.
misschien denkt u dat ik overdrijf, of spreek vanuit een puur academisch standpunt. Laat me je verzekeren — Ik heb tientallen voorbeelden van klanten die zich volledig snookered door het inbedden van derden code te strak in hun app. Hier is slechts een recent voorbeeld…
een voormalige klant van mij bouwde hun app met behulp van een Backend-as-a-Service provider eigendom van Facebook, genaamd Parse. Ze gebruikten een JavaScript client bibliotheek die door Parse om de Parse dienst te consumeren. Tijdens het proces koppelden ze al hun code — inclusief de “secret sauce” — code-strak aan deze bibliotheek.
drie maanden na de eerste productlancering van mijn klant — net toen ze begonnen met een goede tractie met echte, betalende klanten-kondigde Parse aan dat het werd afgesloten.
nu in plaats van zich te concentreren op het herhalen van hun product en het vergroten van hun klantenbestand, moest mijn klant uitzoeken hoe hij kon migreren naar een self-hosted, open-source versie van Parse, of Parse volledig kon vervangen.
de verstoring die dit veroorzaakte voor een jonge, beginnende applicatie was zo groot dat mijn cliënt uiteindelijk de app volledig heeft geschrapt.
evenwicht tussen goed en slecht
enkele jaren geleden, mijn go-to oplossing voor het overwinnen van de risico ‘ s met behoud van de voordelen van derden-bibliotheken was om ze te wikkelen met behulp van de Adapter patroon.
in wezen wikkel je de code van derden in een adapter klasse of module die je hebt geschreven. Dit werkt dan om de functies van de bibliotheken van derden bloot te leggen op een manier die u beheert.
met behulp van dit patroon, als een bibliotheek of framework van derden verandert of verdwijnt, hoeft u slechts een beetje adaptercode te repareren. De rest van je app blijft intact.
dit klinkt goed op papier. Als je op zichzelf staande afhankelijkheden hebt die slechts een paar functies bieden, zal dit de truc doen. Maar dingen kunnen snel lelijk worden.
kunt u zich voorstellen dat u de hele React-bibliotheek (inclusief JSX) moet inpakken voordat u er een van gebruikt? Hoe zit het verpakken van jQuery, of hoekig, of de lente framework in Java? Dit wordt al snel een nachtmerrie.
deze dagen raad ik een meer genuanceerde aanpak aan …
voor elke afhankelijkheid die u aan uw codebase wilt toevoegen, evalueer het risiconiveau dat het zal introduceren door twee factoren te vermenigvuldigen:
- de waarschijnlijkheid dat de afhankelijkheid op een materiële manier zal veranderen.
- de hoeveelheid schade die een materiële verandering in de afhankelijkheid zou veroorzaken voor uw toepassing.
een bibliotheek of raamwerk van derden zal minder snel veranderen als sommige of alle volgende dingen waar zijn:
- het bestaat al enkele jaren en heeft meerdere grote releases gehad.
- het wordt veel gebruikt door veel commerciële toepassingen.
- het heeft de actieve steun van een grote organisatie — bij voorkeur een bekend bedrijf of instelling.
een bibliotheek of framework van derden zal minder schade toebrengen aan uw applicatie als sommige of alle van de volgende dingen waar zijn:
- het wordt alleen gebruikt door een klein deel van uw toepassing, in plaats van te worden gebruikt in de hele.
- de code die ervan afhangt maakt geen deel uit van die” geheime saus ” waar ik het eerder over had.
- het verwijderen vereist minimale wijzigingen in uw codebase.
- uw gehele toepassing is zeer klein en kan snel worden herschreven. (Wees voorzichtig met deze – het is zelden waar voor zeer lang.)
hoe riskanter iets is, hoe groter de kans dat je zou moeten zijn om het in te pakken of helemaal te vermijden.
als het gaat om de code die echt centraal staat in de waardepropositie van uw toepassing —uw “geheime saus” — moet u er extreem beschermend voor zijn. Maak die code zo onafhankelijk mogelijk. Als u absoluut een afhankelijkheid moet gebruiken, overweeg dan om het te injecteren in plaats van er direct naar te verwijzen. Zelfs dan, wees voorzichtig.
soms betekent dit “nee” zeggen tegen een bibliotheek van derden waarvan je denkt dat het echt cool is, of die je echt wilt gebruiken om een of andere reden. Wees sterk. Geloof me, het zal vruchten afwerpen. Vraag maar aan al die mensen die zwaar geïnvesteerd in de allereerste release van Angular, of mijn voormalige klant die Parse overal gebruikt. Het is niet leuk. Geloof me.
over plezier gesproken, kijk hier eens naar…
de afbeelding hierboven is de afhankelijkheidsgrafiek voor een toepassing genaamd TinyTag Explorer.
het genereren van een afhankelijkheidsgrafiek voor uw bestaande apps is een geweldige manier om het risiconiveau te begrijpen dat door uw afhankelijkheden wordt geïntroduceerd. Ik heb samen een lijst van gratis tools voor het genereren van grafieken vergelijkbaar met de bovenstaande in een verscheidenheid van talen, waaronder JavaScript, C#, Java, PHP, en Python. Je kunt het hier krijgen.
Help me anderen te helpen
Ik wil zoveel ontwikkelaars helpen als ik kan door mijn kennis en ervaring met hen te delen. Help me alsjeblieft door op de knop recommend aanbevelen (groen hart) hieronder te klikken.
ten slotte, vergeet niet om hier uw lijst van vrije dependency graph generators te pakken.