Monolith vs. Microservices Part 7
Was sagen die Entwickler:innen?
Bis jetzt haben wir in unserer Artikelserie die Teamaufstellung, die unabhängige Entwicklung von Teams und auch den Einfluss von Microservices auf die Implementierung von Schnittstellenaufrufen behandelt, aber es gibt noch weitere Themen, die aus Sicht von Entwickler:innen eine Rolle spielen.
Zusammenfassung
Ein guter Schnitt der Microservices ist auch für Entwickler:innen von großem Interesse. Nur durch einen guten Schnitt ist sichergestellt, dass Entwickler:innen ohne größere Umstände entwickeln, testen und debuggen können. CI/CD-Pipelines sollten ein ausführbares Image je Microservice bereitstellen, sodass Entwickler nicht alles selbst lokal bauen müssen.
Im Falle einer monolithischen Architektur gilt fast das Gleiche: Der Monolith sollte in saubere Module zerlegt werden. Damit erfordern Anpassungen in einem Modul nicht den Build und Test des gesamten Monolithen, sondern nur des angepassten Moduls. Das Thema bessere Verständlichkeit ist beim Modulith ebenso gegeben wie bei einer Microservice-Architektur, denn kleinere Module sind genau so leicht verständlich wie kleine Microservices – mit dem Unterschied, dass im Modulith auch Aufrufe deutlich erkennbar sind.
Entwickler:innen-Sicht
Moni: „Entwickeln, Testen und Debuggen ist für Entwickler:innen zu Beginn im Monolith leichter.“
Michi: „Bis zu einer gewissen Größe gebe ich dir Recht. Aber je größer die Anwendung wird, desto länger kann der Build-Prozess für den Monolithen dauern. Wenn ich Änderungen an nur einem fachlichen Prozess habe, brauche ich nur diesen Service neu zu bauen statt der kompletten Anwendung.“
Entwickeln, Testen und Debuggen ist für Entwickler:innen Tagesgeschäft. Doch welchen Einfluss hat die Architektur auf diese Tätigkeiten? Moni behauptet, dass sich Entwickler:innen im Monolith leichter damit tun. Und das obwohl von Microservices behauptet wird, dass sie kleiner und deshalb leichter zu verstehen sind.
Für einen einzelnen Microservice ist das auch richtig: Er ist klein, leicht zu verstehen und tut genau eine Sache. Aber wenn es darum geht, über Servicegrenzen hinweg zu entwickeln, zu testen und zu debuggen, wird das bei einer Vielzahl an Microservices schnell schwierig. Zum Beispiel muss man für das Debuggen über Servicegrenzen hinweg die betroffenen Microservices auschecken, lokal starten und mit remote Debugging arbeiten.
Das andere Extrem sind großgewachsene Monolithen, die lange brauchen, zu kompilieren und noch länger, bis alle automatisierten Tests lokal durchgelaufen sind. Wenn jeder Build- und Run-Prozess eine Stunde benötigt, können Entwickler:innen diesen Prozess genau achtmal am Tag ausführen.
Im Kontext der Vielzahl an Microservices wäre eine Herangehensweise, dass jede CI/CD-Pipeline ein ausführbares Image zum Download bereitstellt, sodass Entwickler:innen sich zumindest den Build-Prozess aller benötigten Microservices sparen. Allerdings sollte auch hier ein guter Schnitt der Microservices helfen: Im Idealfall wird für einen Anwendungsfall nicht eine Vielzahl an Microservices benötigt, sondern vielleicht einer oder zwei.
Beim übergroßen Monolith hilft eine saubere Zerlegung in einzelne Module. Wenn der Modulith sauber strukturiert ist und Änderungen in einem Modul vorgenommen werden, muss genau dieses eine Modul neu getestet und gebaut werden. Alle anderen Module des Modulithen müssen nicht angefasst werden. Dadurch kann auch der Build-Prozess beschleunigt werden. Zum Debuggen ist der Modulith natürlich auch angenehmer – man kann den Modulith im besten Fall in der IDE starten und mit dem Debugger in der IDE arbeiten.
Zum Testen einer Anwendung werden auch immer akkurate Testdaten benötigt. Für den Test eines einzelnen Microservices ist die Bereitstellung von passenden Testdaten im Vergleich zu einem großen Monolith ziemlich einfach, da ein Microservice nur einen Teil der fachlichen Gesamtkomplexität umsetzt und deshalb auch nur eine Teilmenge an Daten benötigt. Wird für einen Testfall aber mehr als ein Microservice benötigt, so wird die Bereitstellung von Testdaten und die Sicherstellung der Integrität der Daten über Servicegrenzen hinweg zu einer Herausforderung, die schwieriger werden kann, als Testdaten für einen Monolith bereitzustellen.