Codeabhä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 dies jedoch zu einem zentralen, untrennbaren Bestandteil unserer Apps.

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

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

  1. Externe Abhängigkeiten stellen eine große Gefahr für die Langzeitstabilität und Lebensfähigkeit einer Anwendung dar.
  2. Es wird immer schwieriger, wenn nicht sogar 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 uns all die Dinge überlegen, 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
  • Server Hardware (CPU, Festplatte, Ram,…)
  • Kühlung
  • Virtualisierungsplattform
  • Containerplattform
  • Betriebssystem
  • Webserver-Plattform
  • App Server Platform
  • Webbrowser

Als Entwickler ist es gut, sich dieser Dinge bewusst zu sein, aber wir können oft nicht viel dagegen tun. Ignorieren wir sie jetzt 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 uns gehört.

2. Abhängigkeiten, die wir nicht kontrollieren

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

3. Einmal entfernte Abhängigkeiten

Dies sind die Codeabhängigkeiten, von denen unsere Codeabhä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 einmal entfernte Abhängigkeiten können immer noch Kopfschmerzen verursachen, aber im Fall von Abhängigkeiten, die wir kontrollieren, sollten wir in der Lage sein, direkt einzugreifen und Probleme zu mindern.

Wenn Abhängigkeiten einmal entfernt wurden, können wir uns in der Regel darauf verlassen, dass ein Dritter sie für uns erledigt, da sie auch von diesen abhängig sind.

Warum Codeabhä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, Anzeige einer Elementliste, Validierung von Formulareingaben usw.

Unabhängig davon, welchen Technologie-Stack Sie verwenden, gibt es gute Chancen, dass für diese Probleme gemeinsame Lösungen 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äufig auftretendes 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 Soße".

Der Such- und Seitenranking-Algorithmus von Google, die Timeline-Filterung von Facebook, der für Sie empfohlene Netflix-Bereich und Datenkomprimierungsalgorithmen - der Code hinter all diesen Funktionen lautet "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 Soße“ konzentrieren können.

Warum Codeabhä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, 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 der Bibliothek, die Sie nicht besitzen? Ein wichtiger Grund, warum Sie eine Bibliothek 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 denken Sie, ich übertreibe oder spreche aus rein akademischer Sicht. Lassen Sie sich versichern - ich habe Dutzende von Beispielen von Kunden, die sich völlig selbst erschlichen haben, indem sie den Code von Drittanbietern zu eng in ihre App eingebettet haben. Hier ist nur ein aktuelles Beispiel…

Ein ehemaliger Kunde von mir hat seine App mithilfe eines Backend-as-a-Service-Anbieters 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 für die „geheime Soße“ - eng mit dieser Bibliothek verknüpft.

Drei Monate nach der ersten Produkteinführung meines Kunden - gerade als sie anfingen, bei echten, zahlenden Kunden eine gute Traktion zu erzielen - kündigte Parse an, dass der Betrieb eingestellt wird.

Anstatt sich auf das Produkt zu konzentrieren 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, noch junge Anwendung verursachte, war so groß, dass mein Kunde die App schließlich komplett verschrottete.

Gutes und Böses in Einklang bringen

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

Im Wesentlichen binden Sie den Code eines Drittanbieters in eine Adapterklasse oder ein Modul ein, die bzw. das Sie geschrieben haben. Auf diese Weise werden die Funktionen der Bibliotheken von Drittanbietern auf eine Weise verfügbar gemacht, die Sie steuern können.

Wenn Sie dieses Muster verwenden, müssen Sie nur ein bisschen Adaptercode korrigieren, wenn sich eine Bibliothek oder ein Framework eines Drittanbieters ändert oder verschwindet. Der Rest Ihrer App bleibt erhalten.

Adapterdiagramm von Dofactory.com

Das klingt auf dem Papier 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…

Berechnen Sie für jede Abhängigkeit, die Sie zu Ihrer Codebasis hinzufügen möchten, das Risiko, das durch sie entsteht, indem Sie zwei Faktoren multiplizieren:

  1. Die Wahrscheinlichkeit, dass sich die Abhängigkeit wesentlich ändert.
  2. Das Ausmaß 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 von einem bekannten Unternehmen oder einer 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.
  • Der Code, der davon abhängt, ist nicht Teil der „geheimen Soße“, über die ich zuvor gesprochen habe.
  • Das Entfernen erfordert minimale Änderungen an Ihrer Codebasis.
  • Ihre gesamte Anwendung ist sehr klein und kann schnell umgeschrieben werden. (Seien Sie vorsichtig mit diesem - es ist selten sehr lange wahr.)

Je riskanter etwas ist, desto eher sollten Sie es einwickeln oder ganz vermeiden.

Wenn es um den Code geht, der für das Wertversprechen Ihrer Anwendung - Ihre „geheime Soße“ - wirklich von zentraler Bedeutung ist, müssen Sie diesen ä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 einschleusen, anstatt sie direkt zu referenzieren. Sei auch dann vorsichtig.

Manchmal bedeutet dies, einer Drittanbieter-Bibliothek, die Sie für richtig cool halten oder die Sie aus dem einen oder anderen Grund wirklich verwenden möchten, „Nein“ zu sagen. Sei stark. Vertrauen Sie mir, es wird sich auszahlen. Fragen Sie einfach alle, die viel in die erste Version von Angular investiert haben, oder meinen früheren Kunden, der Parse überall verwendet hat. Es macht keinen Spaß. Das können Sie mir glauben.

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

Abhängigkeitsdiagramm für TinyTag Explorer

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

Das Generieren eines Abhängigkeitsdiagramms für Ihre vorhandenen Apps bietet eine hervorragende Möglichkeit, das Risiko zu verstehen, das durch Ihre Abhängigkeiten entsteht. Ich habe eine Liste kostenloser Tools zum Generieren ähnlicher Grafiken in verschiedenen Sprachen zusammengestellt, darunter 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 eine Liste der kostenlosen Generatoren für Abhängigkeitsgraphen abzurufen.