Code-Abhängigkeiten sind der Teufel.

Ihre Abhängigkeiten werden Sie jedes Mal verbrennen.
"Veränderung ist die einzige Konstante ..." - Heraklit (Philosoph)

Die Tools, Bibliotheken und Frameworks, mit denen wir heute unsere Webanwendungen erstellen, unterscheiden sich drastisch von denen, die wir vor wenigen Jahren verwendet haben.

In wenigen Jahren werden sich die meisten dieser Technologien wieder dramatisch verändert haben. Viele von uns machen diese jedoch zu einem zentralen, untrennbaren Bestandteil unserer Apps.

Wir importieren, verwenden und erben von den Frameworks des Monatsgeschmacks, als ob sie alle für immer existieren und unverändert bleiben würden. Nun ... sie sind es nicht. Und das ist ein Problem.

Nach mehr als 20 Jahren Entwicklung, Design und Architektur von Webanwendungen habe ich zwei wichtige Wahrheiten erkannt:

  1. Externe Abhängigkeiten stellen eine große Bedrohung für die Langzeitstabilität und Lebensfähigkeit einer Anwendung dar.
  2. Es wird immer schwieriger - wenn nicht unmöglich -, eine nicht triviale App zu erstellen, ohne externe Abhängigkeiten zu nutzen.

In diesem Artikel geht es darum, diese beiden Wahrheiten miteinander in Einklang zu bringen, damit unsere Apps die größten langfristigen Überlebenschancen haben.

Das Kaninchenloch ist in der Tat sehr tief.

Wenn wir an all die Dinge denken, von denen unsere Web-Apps abhängen, fällt es uns leicht, an ein Dutzend oder mehr zu denken, bevor wir überhaupt zum Code gelangen:

  • Leistung
  • Konnektivität
  • Firewall
  • DNS
  • Serverhardware (CPU, Festplatte, RAM,…)
  • Kühlung
  • Virtualisierungsplattform
  • Containerplattform
  • Betriebssystem
  • Webserver-Plattform
  • App Server-Plattform
  • Webbrowser

Als Entwickler ist es gut, sich dieser Dinge bewusst zu sein, aber wir können oft nicht viel dagegen tun. Ignorieren wir sie also zunächst und sprechen nur über den Code.

Im Code gibt es drei Arten von Abhängigkeiten:

1. Abhängigkeiten, die wir kontrollieren

Dies ist Code, der von uns oder unserer Organisation geschrieben wurde und deren Eigentümer wir sind.

2. Abhängigkeiten, die wir nicht kontrollieren

Dies ist Code, der von einem Drittanbieter oder einer Open-Source-Software-Community geschrieben wurde.

3. Abhängigkeiten einmal entfernt

Dies sind die Code-Abhängigkeiten, von denen unsere Code-Abhängigkeiten von Drittanbietern abhängen. (Sag das dreimal schnell!)

Wir werden hauptsächlich über Abhängigkeiten sprechen, die wir nicht kontrollieren.

Abhängigkeiten, die wir kontrollieren, und Abhängigkeiten, die einmal entfernt wurden, können immer noch Kopfschmerzen verursachen. Bei Abhängigkeiten, die wir kontrollieren, sollten wir jedoch in der Lage sein, direkt einzugreifen und Probleme zu mindern.

Bei einmal entfernten Abhängigkeiten können wir uns in der Regel darauf verlassen, dass ein Dritter sich um uns kümmert, da diese ebenfalls von diesen abhängig sind.

Warum Code-Abhängigkeiten von Drittanbietern gut sind

Ein großer Teil Ihrer Webanwendung ist vorhanden, um häufig auftretende Probleme zu lösen: Authentifizierung, Autorisierung, Datenzugriff, Fehlerbehandlung, Navigation, Protokollierung, Verschlüsselung, Anzeigen einer Liste von Elementen, Überprüfen von Formulareingaben usw.

Unabhängig davon, welchen Technologie-Stack Sie verwenden, besteht eine gute Chance, dass gemeinsame Lösungen für diese Probleme existieren und als Bibliotheken verfügbar sind, die Sie einfach erwerben und in Ihre Codebasis einbinden können. Es ist im Allgemeinen Zeitverschwendung, all diese Dinge komplett von Grund auf neu zu schreiben.

Sie möchten sich auf Code konzentrieren, der entweder ein ungewöhnliches Problem oder ein häufiges Problem auf ungewöhnliche Weise löst. Das macht Ihre Anwendung wertvoll: Der Code, der die Geschäftsregeln implementiert, die nur für Ihre App gelten - die „geheime Sauce“.

Googles Such- und Seitenranking-Algorithmus, Facebooks Timeline-Filterung, Netflixs Abschnitt "Für Sie empfohlen" und Datenkomprimierungsalgorithmen - der Code hinter all diesen Funktionen ist "geheime Sauce".

Mit Code von Drittanbietern - in Form von Bibliotheken - können Sie diese Standardfunktionen Ihrer App schnell implementieren, sodass Sie sich auf Ihre „geheime Sauce“ konzentrieren können.

Warum Code-Abhängigkeiten von Drittanbietern schlecht sind

Werfen Sie einen Blick auf eine nicht triviale Web-App, die in den letzten Jahren erstellt wurde, und Sie werden absolut erstaunt sein, wie viel Code tatsächlich aus einer Bibliothek eines Drittanbieters stammt. Was ist, wenn sich eine oder mehrere dieser Bibliotheken von Drittanbietern drastisch ändern oder verschwinden oder kaputt gehen?

Wenn es Open Source ist, können Sie es vielleicht selbst beheben. Aber wie gut verstehen Sie den gesamten Code in dieser Bibliothek, die Sie nicht besitzen? Ein wichtiger Grund, warum Sie eine Bibliothek überhaupt verwenden, besteht darin, die Vorteile des Codes zu nutzen, ohne sich um alle Details kümmern zu müssen. Aber jetzt steckst du fest. Sie haben Ihr Vermögen vollständig an diese Abhängigkeiten gebunden, die Sie nicht besitzen und nicht kontrollieren.

Keine Sorge, am Ende dieses Artikels finden Sie eine neue Hoffnung.

Vielleicht denkst du, ich übertreibe oder spreche aus rein akademischer Sicht. Ich versichere Ihnen: Ich habe Dutzende Beispiele von Kunden, die sich selbst völlig durchgeknallt haben, indem sie Code von Drittanbietern zu eng in ihre App eingebettet haben. Hier ist nur ein aktuelles Beispiel…

Ein ehemaliger Kunde von mir hat seine App mit einem Backend-as-a-Service-Anbieter von Facebook namens Parse erstellt. Sie verwendeten eine von Parse bereitgestellte JavaScript-Clientbibliothek, um den Parse-Dienst zu nutzen. Dabei haben sie ihren gesamten Code - einschließlich des Codes der „geheimen Soße“ - eng mit dieser Bibliothek verbunden.

Drei Monate nach der ersten Produkteinführung meines Kunden - gerade als er bei echten, zahlenden Kunden eine gute Traktion bekam - gab Parse bekannt, dass das Unternehmen heruntergefahren wird.

Anstatt sich darauf zu konzentrieren, das Produkt zu iterieren und den Kundenstamm zu vergrößern, musste mein Kunde herausfinden, wie er entweder auf eine selbst gehostete Open-Source-Version von Parse migrieren oder Parse vollständig ersetzen kann.

Die Störung, die dies für eine junge, junge Anwendung verursachte, war so groß, dass mein Kunde die App schließlich komplett verschrottete.

Das Gute und das Schlechte in Einklang bringen

Vor einigen Jahren bestand meine Lösung zur Überwindung der Risiken unter Beibehaltung der Vorteile von Bibliotheken von Drittanbietern darin, sie mithilfe des Adaptermusters zu verpacken.

Im Wesentlichen verpacken Sie den Code eines Drittanbieters in eine von Ihnen geschriebene Adapterklasse oder ein Modul. Auf diese Weise werden die Funktionen der Bibliotheken von Drittanbietern auf eine von Ihnen gesteuerte Weise verfügbar gemacht.

Wenn sich nach diesem Muster eine Bibliothek oder ein Framework eines Drittanbieters ändert oder nicht mehr vorhanden ist, müssen Sie nur ein wenig Adaptercode reparieren. Der Rest Ihrer App bleibt erhalten.

Adaptermusterdiagramm von Dofactory.com

Auf dem Papier klingt das gut. Wenn Sie in sich geschlossene Abhängigkeiten haben, die nur wenige Funktionen bereitstellen, reicht dies aus. Aber es kann schnell hässlich werden.

Können Sie sich vorstellen, die gesamte React-Bibliothek (einschließlich JSX) zu verpacken, bevor Sie eine davon verwenden? Wie wäre es mit jQuery, Angular oder dem Spring-Framework in Java? Dies wird schnell zu einem Albtraum.

In diesen Tagen empfehle ich einen differenzierteren Ansatz…

Bewerten Sie für jede Abhängigkeit, die Sie Ihrer Codebasis hinzufügen möchten, das damit verbundene Risiko, indem Sie zwei Faktoren multiplizieren:

  1. Die Wahrscheinlichkeit, dass sich die Abhängigkeit wesentlich ändert.
  2. Die Höhe des Schadens, den eine wesentliche Änderung der Abhängigkeit Ihrer Anwendung zufügen würde.

Es ist weniger wahrscheinlich, dass sich eine Bibliothek oder ein Framework eines Drittanbieters ändert, wenn einige oder alle der folgenden Dinge zutreffen:

  • Es gibt es schon seit mehreren Jahren und es gab mehrere Hauptversionen.
  • Es wird häufig von vielen kommerziellen Anwendungen verwendet.
  • Es wird von einer großen Organisation aktiv unterstützt - vorzugsweise einer bekannten Firma oder Institution.

Eine Bibliothek oder ein Framework eines Drittanbieters fügt Ihrer Anwendung weniger Schaden zu, wenn einige oder alle der folgenden Dinge zutreffen:

  • Es wird nur von einem kleinen Teil Ihrer Anwendung verwendet und nicht durchgehend verwendet.
  • Der Code, der davon abhängt, ist nicht Teil dieser „geheimen Sauce“, über die ich zuvor gesprochen habe.
  • Das Entfernen erfordert nur minimale Änderungen an Ihrer Codebasis.
  • Ihre gesamte Bewerbung ist sehr klein und kann schnell umgeschrieben werden. (Seien Sie vorsichtig mit diesem - es ist selten sehr lange wahr.)

Je riskanter etwas ist, desto wahrscheinlicher ist es, dass Sie es einwickeln oder ganz vermeiden.

Wenn es um den Code geht, der für das Wertversprechen Ihrer Anwendung von zentraler Bedeutung ist - Ihre „geheime Sauce“ -, müssen Sie ihn äußerst schützen. Machen Sie diesen Code so unabhängig wie möglich. Wenn Sie eine Abhängigkeit unbedingt verwenden müssen, sollten Sie sie einfügen, anstatt sie direkt zu referenzieren. Sei auch dann vorsichtig.

Manchmal bedeutet dies, zu einer Bibliothek eines Drittanbieters „Nein“ zu sagen, die Sie für wirklich cool halten oder die Sie aus dem einen oder anderen Grund wirklich verwenden möchten. Sei stark. Vertrauen Sie mir, es wird sich auszahlen. Fragen Sie einfach alle Leute, die stark in die allererste Veröffentlichung von Angular investiert haben, oder meinen ehemaligen Kunden, der Parse überall verwendet hat. Es macht keinen Spaß. Glaube mir.

Apropos Spaß, schauen Sie sich das an ...

Abhängigkeitsdiagramm für TinyTag Explorer

Das obige Bild ist das Abhängigkeitsdiagramm für eine Anwendung namens TinyTag Explorer.

Das Generieren eines Abhängigkeitsdiagramms für Ihre vorhandenen Apps ist eine hervorragende Methode, um das Risiko zu verstehen, das durch Ihre Abhängigkeiten entsteht. Ich habe eine Liste mit kostenlosen Tools zum Generieren von Diagrammen zusammengestellt, die den oben genannten ähnlich sind, und zwar in verschiedenen Sprachen, einschließlich JavaScript, C #, Java, PHP und Python. Sie können es hier bekommen.

Hilf mir, anderen zu helfen

Ich möchte so vielen Entwicklern wie möglich helfen, indem ich mein Wissen und meine Erfahrung mit ihnen teile. Bitte helfen Sie mir, indem Sie unten auf die Schaltfläche ❤ empfehlen (grünes Herz) klicken.

Vergessen Sie nicht, hier Ihre Liste der kostenlosen Generatoren für Abhängigkeitsgraphen abzurufen.