Sikov - stock.adobe.com

Technical Debt durch lose Kopplung von Komponenten vermeiden

Obwohl es viele Faktoren gibt, die technische Schulden verursachen, ist der Grad der Kopplung in der zugrunde liegenden Softwarearchitektur oft der Hauptgrund.

Der Begriff technische Schulden oder Technical Dept ist in der IT und Informatik ein häufig verwendeter Begriff für die Folgen schlechter technischer Umsetzung von Softwareprojekten. Technische Schulden umfassen die Summe der Versäumnisse, Fehler und schlechten Designentscheidungen, die sich in einem Projekt festsetzen. Dies führt zu nachgelagerten Problemen bei Wartungs- und Update-Prozessen und zu einem erhöhten Aufwand, den man für Korrekturen und Erweiterungen im Vergleich zu gut geschriebener Software einplanen muss.

Wie viele Unternehmen und Entwicklungsteams selbst festgestellt haben, hat das Design der zugrunde liegenden Softwarearchitektur – insbesondere der Grad der Kopplung zwischen den Komponenten – einen enormen Einfluss auf das Ausmaß an technischen Schulden, die Anwendungsentwicklungs- und -managementprozesse regelmäßig erzeugen.

In diesem Artikel wird der Zusammenhang zwischen der Koppelung von Softwarekomponenten und technischer Schuld untersucht. Anschließend wird gezeigt, wie die lose Kopplung, die in Microservices-Architekturen (MSA) genutzt wird, die Probleme der technischen Schulden bei monolithischen Anwendungen direkt angeht. Abschließend erläutern wir die Regeln, die beim Refactoring für lose Kopplung beachtet werden sollten und die Entwicklern helfen, starre Abhängigkeiten zu vermeiden.

Monolithische versus Microservices-basierte Anwendungen
Abbildung 1: Monolithische versus Microservices-basierte Anwendungen.

Enge Kopplung versus lose Kopplung

Die Kopplung bezeichnet in der Informatik den Grad der Abhängigkeit von Hardware- und Softwarekomponenten untereinander. Eine enge Kopplung von Komponenten begünstigt bei monolithischen Architekturen oft starre Komponentenabhängigkeiten. Dies macht es unmöglich oder sehr schwierig, Updates und Versionsdienste isoliert zu erstellen. Ein eng gekoppeltes Architekturmodell verursacht damit mehr technische Schulden als entsprechend verteilte Modelle.

Dafür gibt es drei Gründe:

  • Verlust der Wiederverwendbarkeit von Komponenten und Tendenz zu doppeltem Entwicklungsaufwand;
  • Schwierigkeiten beim Erkennen von Abhängigkeiten und beim Vermeiden von Fehlern durch schlecht koordinierte Änderungen; und
  • Verzögerungen bei der Softwareverfügbarkeit aufgrund langer, starrer Entwicklungszyklen.

Viele verbreitete Programmiergewohnheiten begünstigen starre Kopplungen – zum Beispiel das Verknüpfen von Daten zwischen Diensten durch direkte Dateiübertragungen anstatt der Übergabe von Parametern. Unabhängig von der Quelle führen diese Abhängigkeiten zu einer zunehmenden technischen Verschuldung: Ein Update einer Softwarekomponente erfordert mit hoher Wahrscheinlichkeit eine Änderung der meisten – wenn nicht aller – Komponenten und Dienste, mit denen sie verbunden ist. Jede einzelne Änderung löst eine Welle von notwendigen Updates aus, die Zeit und Geld verschlingen und das Risiko von Brüchen und Fehlern erhöhen.

Im Gegensatz dazu begrenzt die lose Kopplung – die typischerweise in Microservices-Designs zu finden ist – die Abhängigkeiten durch eine strikte Trennung der Softwarekomponenten und -dienste. Durch die Umstrukturierung des Architekturmodells werden gute Programmierpraktiken gefördert, wie zum Beispiel die Erleichterung von Datenübertragungen über Parameter anstelle von direkten Übertragungen. Auf diese Weise können Entwicklungsteams die langfristigen negativen Auswirkungen von häufigen Updates und Technologie-Upgrades auf große Softwaresysteme reduzieren.

Refaktorisierung für lose Kopplung

Unternehmen, die auf schnelle Entwicklungszyklen setzen, sollten sich nicht fragen, ob sie technische Schulden durch lose Kopplung signifikant reduzieren können – sie sollten dies als gegeben betrachten. Wenn jemand im IT-Team Erfahrung mit Microservices hat und Software bereits unter Verwendung von loser Kopplung und Microservices implementiert ist, steigt die Chance, dass sich eine Refaktorisierung für lose Kopplung auszahlt.

Natürlich ist es einfacher, eine lose Kopplung in Greenfield-Projekten einzuführen, als bereits bestehende Anwendungen für eine stärkere Trennung umzugestalten. Angesichts der Schwierigkeit, Code umzugestalten, gibt es einige Richtlinien, anhand derer Sie feststellen können, ob ein Refactoring erforderlich ist:

  • Wenn es schnell gehen soll bei der Entwicklung und Updates häufig durchgeführt werden, wird sich eine lose Kopplung auszahlen – selbst wenn ein Refactoring erforderlich ist.
  • Möglicherweise kann eine Abkehr von einer eng gekoppelten Architektur schrittweise vollzogen werden. Dies ist zum Beispiel dann der Fall, wenn Aktualisierungen von Komponenten als Reaktion auf sich ändernde Anforderungen geplant werden, anstatt eine große, singuläre Erneuerung der gesamten Codebasis in Angriff zu nehmen.
  • Wenn die Software noch relativ neu und so strukturiert ist, dass aktive Komponenten leicht identifiziert und isoliert werden können, ist ein Refactoring wahrscheinlich nicht notwendig.
  • Wenn das Unternehmen Probleme hat, Softwareexperten zu beschäftigen, wird ein effektives Refactoring wahrscheinlich schwierig sein – es ist teuer (und risikoreich), die Entwicklung auszulagern. Das macht die finanziellen Vorteile, die Sie sich von Anfang an erhofft haben, wahrscheinlich zunichte.

Angenommen, eine Refaktorisierung ist gerechtfertigt: wie sollten Unternehmen dabei vorgehen? Hier besteht das Risiko, dass die Kopplung zu eng bleibt, wenn versucht wird, an allen Ecken und Enden zu sparen, wodurch die potenziellen Vorteile, die ein Refactoring-Projekt rechtfertigten, zunichte gemacht werden.

Um dies zu vermeiden, kehren Sie zu den Prinzipien eines sauberen Anwendungsdesigns zurück. Identifizieren Sie die kritischsten Funktionen der bestehenden Anwendung in diesem Modell, notieren Sie sich sorgfältig die einzelnen Code-Beiträge für jede Funktion und ermitteln Sie, wer sie programmiert hat. Wenn die Entwickler Code hinzufügen, um neue Funktionen zu implementieren, sollten die Teams gleichzeitig die Blöcke des vorhandenen Codes retten, die inkrementell modifiziert werden können, um sie an ein Microservices-Modell anzupassen.

Der häufigste Übeltäter bei Problemen mit einer eng gekoppelten Architektur ist die Verwendung von persistentem Speicher, um Daten zwischen Komponenten zu übergeben. Wenn mehrere Anwendungskomponenten Zugriff auf einen einzelnen Datensatz benötigen, sollte der Datensatz als Parameter übergeben werden und nicht im Anwendungscode oder in der Datenbank gespeichert werden. Achten Sie auf Szenarien, in denen diese Datenarten in den Code eingebettet sind, und eliminieren Sie sie beim Refactoring. Diese Best Practice der Code-Hygiene trägt wesentlich dazu bei, versehentliche enge Kopplungen zu verhindern und erleichtert die Reduzierung der technischen Schulden.

Erfahren Sie mehr über Softwareentwicklung