# Layered vs Hexagonal Architecture Strategy

**Podcast:** Software Architektur im Stream
**Published:** 2026-11-13

## Transcript

So, dann herzlich willkommen zu einer weiteren Episode von Software-Hertig-Turm-Stream.
Diesmal so ein bisschen so eine eher traditionelle Folge, wo es also um ein Thema geht und ich sozusagen meine Gedanken zu diesem Thema zum Besten gebe.
Ich würde einmal kurz noch einen Werbeblock sozusagen machen.
Es gibt von mir das Domain Driven Design Saniert Legacy Training.
Das ist ein halbtägiges Training, findet am 1.12.
um 13 Uhr bis 17 Uhr statt, sind also vier Stunden.
Und da geht es, wie der Titel schon sagt, darum, wie man halt mit DDD Legacy saniert.
Das ist sehr interaktiv, das heißt, es gibt keine Folien.
Wir erarbeiten uns die Inhalte tatsächlich gemeinsam.
Und ihr könnt halt auch gerne alle eure Fragen stellen.
Und das ist halt ein Training, wo es noch Plätze gibt.
Also wenn ihr da kommt und euch mit mir sozusagen gemeinsam um dieses Thema kümmern wollt, dann seid ihr mehr als willkommen.
Das ist der Werbeblock.
Kommen wir jetzt zum eigentlichen Thema.
Also es geht um Schichtenarchitekturen.
Und die erste Frage, die man dann natürlich stellen muss, ist, was sind denn eigentlich Schichten?
Und Schichten sind eben so, dass ich sage, ich habe Teile meines Systems und ich definiere, dass es dort eben bestimmter Teile in diesem System gibt.
Es gibt nur Abhängigkeiten von oben nach unten.
Es gibt also keine Abhängigkeiten von unten nach oben.
Und es gibt dann noch diese strenge Schichtenarchitektur, die sagt, dass jede Schicht nur die Schicht direkt darunter benutzen darf, wo man nicht eine Schicht überspringen darf.
Das impliziert wiederum, dass es eben eine nicht strenge Schichtenarchitektur gibt, wo man also alles von allen Schichten darunter nutzen kann.
Man kann die Frage stellen, was vielleicht die einfachstmögliche Architektur ist, in dem Sinne, dass ich typischerweise bei so einer Struktur des Systems, wenn ich von so einer Architektur spreche, ja Abhängigkeiten einschränke.
Und in diesem Fall habe ich sozusagen das Minimum an Abhängigkeiten, an Abhängigkeitseinschränkungen, nämlich, dass ich nur in eine Richtung darf und nicht zurück.
Und das ist sozusagen vielleicht das Einfachste, was man sich vorstellen kann.
Vielleicht fällt dazu jemand noch was Einfacheres ein.
Und für mich ist so, dass Prototypische zu den Schichten, also natürlich reden wir hier über Softwarearchitektur, natürlich reden wir hier in erster Linie in dem Stream über Softwarearchitektur für Geschäftssysteme, aber wenn es um Schichtenarchitektur geht, fällt mir als erstes diese Geschichte mit den Netzwerken ein.
die physische Schicht haben.
Also dieser Rechner, mit dem ich hier jetzt gerade streame, ist zum Beispiel bei Ethernet verbunden mit dem Internet.
Könnte ich aber jetzt auch zum Beispiel bei Wi-Fi machen.
Oder es gab früher, ich glaube, das ist mittlerweile, also das gibt es noch, dieses PPP-Protokoll, was halt genutzt wird, um Modems zu verwenden und heutzutage noch genutzt wird, um beispielsweise einen DSL-Zugang.
dann tatsächlich an den Internet Service Provider anzuschließen.
PPP oder Ethernet ist das mal an sich nach.
Und diese Protokolle sind halt in der unteren physischen Schicht.
Und darauf setzt dann sowas auf wie IP, also das Internet Protocol, was halt insbesondere dafür sorgt, dass ich jetzt routen kann.
was eben so ein bisschen die geniale Idee dieses Internets war, deswegen auch der Name.
Ich habe also unterschiedliche physische Netzwerke, die ich alle miteinander verbinden kann.
Und durch diese IP-Sachen kann ich jetzt eben sagen, wo ein Paket hin soll.
Ich habe eine IP-Adresse und diese IP-Adresse kann jetzt an einem Ethernet hängen, an einem Modem oder woran auch immer.
Da kriege ich jetzt das halt irgendwie hingeliefert, unabhängig von dem, was halt physisch hinter steckt.
Dann gibt es darauf aufbauend sowas wie TCP als ein verbindungsorientiertes Protokoll, UDP als ein verbindungsloses Protokoll und ICMP für sowas wie ein Ping zum Beispiel, also wo ich halt nachschaue, ob eine andere Seite überhaupt existiert.
Und sowas wie TCP beispielsweise sorgt dafür, dass ich eine Verbindung habe, was halt bedeutet, dass ich jetzt schauen kann, ob irgendein Paket tatsächlich Also wenn ein Paket nicht übertragen wird, kann ich halt durch eine Verbindung dafür sorgen, dass ich das merke, weil ich kann die Pakete innerhalb der Verbindung durchnummerieren und kann dann halt sagen, dieses Paket habe ich nicht bekommen, kann es nochmal übersetzen und habe dadurch übertragen und habe dadurch eine höhere Zuverlässigkeit.
So und darauf baut dann irgendwie sowas, also in groben Zügen sowas wie HTTP auf.
HTTP 2 ist dann ein bisschen anders, weil es in meinem Sinne nach UDP benutzt.
Dieses Protokoll hat dann solche Sachen wie ein Get-Pfil, wo ich sage, ich möchte halt gerne diese Webseite bekommen und basiert dann eben darunter auf sowas wie TCP oder UDP und dadurch habe ich dann letztendlich einen Netzwerk-Stack.
Jetzt ist halt die Frage, warum tue ich das?
Also warum habe ich jetzt irgendwie diese verschiedenen Schichten?
Ein wesentlicher Aspekt ist diese Austauschbarkeit auf der physischen Ebene.
Das heißt, egal was ich da jetzt irgendwie mache, Ich habe halt durch diese untere Schicht davon abstrahiert und ich muss mich jetzt als Entwickler nicht mehr darum kümmern, ob ich eben ein Modem oder sonst was habe, sondern ich kann halt irgendwie einfach schauen, dass ich irgendwie mit IP arbeite und halt IP-Adressen habe.
Das ist, glaube ich, ein wesentlicher Grund dafür.
Der andere Grund ist Transparenz, dass eben Details verborgen sind.
Das heißt, wenn ich halt irgendwie auf IP-Ebene arbeite, muss ich nicht mehr verstehen, wie hat ein Ethernet konkret funktioniert, weil das wird halt von mir verborgen.
Und tatsächlich ist es halt so, dass, würde ich behaupten, beim Netzwerkstack im Wesentlichen die Information der Schichten darunter oder die Kenntnis über die Schichten darunter relativ egal ist.
Also spätestens auf HTTP-Ebene muss ich jetzt nicht mehr wissen, ob ich halt mit einem Modem arbeite oder mit einer Ethernet-Verbindung.
Das ist dann wirklich, wirklich...
transparent.
Und das ist halt dieses Konzept von Information Hiding, was uns ja schon an verschiedenen Stellen so ein bisschen verfolgt hat.
Also ich muss eben nicht wissen, was da unten ist.
Dadurch wird mein Entwurf einfach und ich bin da irgendwie einen Schritt weiter.
Jetzt hat der Urs gerade geschrieben, muss ich mal sehen, was er geschrieben hat, beim ISO-OSI-Schichtmodell bietet, aber jede Schicht eine klare Abstraktion.
Das ist bei Schichten in Softwarearchitekturen kaum der Fall.
Das ist so ein bisschen Das, weswegen ich mit dieser Motivation anfangen wollte und auch so ein bisschen für mich ein Fazit, also genau, ich sollte vielleicht noch dazu sagen, das ist nicht nur im Netzwerk so, sondern ein anderes Beispiel, was mir einfällt, ist halt sowas wie Dateisysteme.
Auf Programmierebene sage ich halt, ich möchte halt diese Datei öffnen.
Da drunter ist ein Dateisystem.
Das Dateisystem ist damit beschäftigt, diese Dateien eben zu organisieren.
Die haben dann halt irgendwie Namen, da gibt es Verzeichnungen, solche Geschichten.
Und da drunter ist dann irgendwie so ein physisches Ding, also eine SSD oder eine Festplatte.
Und auch da ist es jetzt wieder so, wenn ich halt sage, ich möchte gerne eine Datei öffnen, dann interessiert mich das nicht, ob das auf einer SSD, auf einer Festplatte, auf irgendeinem Storage-Device ist, was über ein FS oder so angeschlossen ist.
sondern das ist halt für mich transparent und dadurch kriege ich halt die Sachen von den noteren Schichten nicht mit.
Und das ist, glaube ich, etwas, und ich glaube, das ist auch das, was der Urs eigentlich sagen will, was halt bei diesen technischen Systemen super funktioniert.
Also da irgendwie so eine Schichtarchitektur zu bauen und halt zu sagen, okay, ich habe halt eine obere Schicht, die ganzen Details interessieren mich nicht, die sind auch austauschbar, das macht halt extrem viel Sinn und ist dort halt super nützlich.
Und weil Urs es gerade genannt hat, nicht das ISO-USI-7-Schichtmodell, ist irgendwie etwas, was, ich weiß nicht, ob das immer noch so ist, aber zu meiner Zeit zumindest, alle, wir haben es halt in der Informatik gelernt, obwohl damals schon sich irgendwie abzeichnete, dass halt sowas wie TCP-IP sich durchsetzen würde.
Aber ich glaube, dass da halt auch ein wesentlicher Punkt ist, sozusagen war, diese Architektur sozusagen zu diskutieren.
Das ist also die Motivation.
Und wenn wir jetzt über Schichten reden in Bezug auf Softwarearchitektur, ist, glaube ich, das Erste, was einem irgendwie einfällt, eine Dreischichtenarchitektur.
Und die Dreischichtenarchitektur ist so ein bisschen der logische Nachfolger der Zweischichtenarchitektur.
Zweischichtenarchitektur ist eben etwas, wo ich kleinen Server habe, wo ich also im Wesentlichen eine gemeinsame Datenbank irgendwo stehen habe.
Und dann halt eine Client-Anwendung.
Das ist so ein bisschen eine 90er-Jahre-Geschichte.
Ich habe irgendwo eine Oracle-Datenbank.
Die Oracle-Datenbank ist halt im Unternehmen.
Und dann habe ich halt eben verschiedene Rechner, verschiedene Menschen, die halt auf dieses System zugreifen.
Und das machen sie halt über das Netzwerk, sodass ich eben dann irgendwo die zentrale Datenbank habe.
Und dann habe ich halt die Anwendung bei mir.
Und da sieht man halt, dass diese Schichten auch eine Verteilung sind.
Also Client-Server bedeutet halt in dem Fall, dass es eine Verteilung ist über das...
Das heißt, ich werde eben den Client auf einer kleinen Maschine laufen lassen und den Server eben auf einer Datenbank-Server.
Und davon unterscheidet sich dann diese Dreischichten-Architektur, die also sagt, ich habe eine UI, eine Logik und eine Persistenz, die tatsächlich mal früher, nicht im ausgehenden letzten Jahrhundert, dann auch irgendwie in drei unterschiedlichen Rechnern gelebt hat.
Nicht ein Datenbank-Server, ein Server, der eher die Logik hat.
Und ein Web-Server.
Heutzutage ist es durchaus üblich, zumindest das Web und die Logik zusammen auf einem Rechner zu haben oder das sogar zu nutzen, diese Dreischichtenarchitektur, als eine Bezeichnung für etwas, wie ich nur Software strukturiere.
Und ich habe da letzte Woche ein Video veröffentlicht.
Und habe da irgendwie gezeigt, wie meine Schichtenarchitektur umwandeln kann in eine hexagonale Architektur.
Ich finde auch bei Softwarearchitektur im Stream werde ich auch nochmal irgendwie verlinken.
Ich glaube, ich erspare mir das jetzt, das in den Chat zu tun.
Also im Chat könnt ihr mir sozusagen erstmal zuhören und dann später halt schauen.
Ich habe es als Folge bei Softwarearchitektur im Stream auch veröffentlicht.
Das ist halt ein 6-Minuten-Video.
was halt irgendwie sagt, wie ich aus Schichten hexagonal herstelle und wie halt sozusagen der Unterschied ist.
So, und da habe ich auf jeden Fall so etwas, dass ich, da habe ich eine Grafik gehabt und die würde ich jetzt, glaube ich, ganz gerne mal zeigen.
Da habe ich also jetzt so eine Drei-Schichten-Architektur innerhalb einer Java-Anwendung.
Das heißt, ich habe eine Klasse in der UI.
Die benutzt halt irgendeine Klasse in der Logik und die benutzt halt irgendeine Klasse in der Datenbank.
Das heißt, hier habe ich eben tatsächlich diese Schichten ausgeführt zur Strukturierung meines Software-Systems und habe jetzt nicht irgendwie eine Verteilung gemacht.
Ich habe also nicht das über drei verschiedene Netzwerksysteme verteilt, was auch irgendwie, finde ich, nicht wahnsinnig viel Sinn macht.
weil ich dadurch halt diese Systeme oder diese Schichten, die ja sehr stark viel miteinander kommunizieren, habe auch eine Netzwerkkommunikation ein und die ist halt unzuverlässig und langsam.
Das macht also nicht besonders viel Sinn.
Und dadurch setze ich jetzt diese Schichtenarchitektur, über die ich gesprochen habe, am Vorbild von der Netzwerarchitektur sozusagen eben auch hier um, im Rahmen einer Softwarearchitektur.
So, und jetzt ist irgendwie die Frage, ob man hier sozusagen eine vollständige, also Urs hat halt geschrieben, das ist eine vollständige Architektur oder, sorry, eine vollständige oder eine klare Abstraktion.
Ich habe jetzt ja einmal gesagt, wenn ich halt sozusagen das Netzwerk anschaue, dann ist es halt beim Netzwerk so, dass ich dort eben jetzt zum Beispiel die untere Schicht IP austauschen oder dort irgendwie was anderes physisches haben kann.
Das heißt, ich kann halt dieselbe Software nehmen und darunter habe ich jetzt eben im Rahmen von IP nicht mehr ein Ethernet, sondern irgendwas anderes, Modem oder wie auch immer.
Und das ist hier theoretisch auch denkbar, aber in der Realität wird es halt häufig so sein, dass man dann so versteckte Abhängigkeiten hat.
Also wenn ich jetzt in der Datenbank ein relationales Modell habe, dann habe ich eben verschiedene Tabellen.
Diese Tabellen stehen in Beziehung zueinander, das sind eben Relationen.
Ich habe halt typischerweise meine Logik-Schichten objektorientiertes Modell.
Dann muss ich das also irgendwie ineinander übersetzen.
Und da habe ich halt irgendwie Mismatch.
Und ich kann jetzt zum Beispiel auf die Idee kommen und kann halt sagen, damit ich halt dieses Mismatch nicht habe, habe ich auf der Logikschicht ein Modell, das eben tatsächlich inspiriert ist durch die Relationale Datenbank.
Und darüber habe ich vor einiger Zeit Anfang des Jahres eine Episode gemacht, wie Datenbanken die Architektur formen.
Und da geht es genau darum, dass es eben nicht so ist, dass man jetzt einfach sagt, okay, es gibt halt eine Relationale Datenbank und davon abstrahiere ich halt vollständig.
Ich baue jetzt ein objektorientiertes Modell.
Und es ist eben auch so, wenn ich mir zum Beispiel dokumentorientierte Datenbanken angucke, Die haben eben grobgranulare Einheiten.
Das heißt, die haben irgendwie nicht diese Aufteilung in diese verschiedenen Tabellen, sondern eben Dokumente.
Und das, was ich typischerweise in mehreren Tabellen haben würde, also sowas wie ein Kunden oder eine Bestellung, die habe ich halt in einer Dokumentendatenbank in einem Dokument.
Und das kann durchaus etwas sein, was wiederum inspiriert, wie ich halt in der Logik-Geschichte irgendwelche Sachen halt modelliere, sodass das eben nicht so klar ist, dass das tatsächlich austauschbar ist.
Und das ist hier ja auch vielleicht gar nicht so notwendig.
Also dass ich halt ad hoc mal sage, okay, ich will halt die gesamte Persistenzschicht austauschen, eher unwahrscheinlich.
Dass ich es nicht verstehen muss, was da drunter passiert, das ist vielleicht schon eher der Fall.
Also wenn ich halt ein Repository habe und mir das Repository halt anbietet, dass ich jetzt eben dort alle Kunden mit einem bestimmten Namen bekommen kann, dann muss ich nicht verstehen, wie das genau funktioniert.
Das ist halt analog zu dem, was ich halt auch im Netzwerk finden würde.
Und da ist vielleicht der einzige Hinweis, dass ich bestimmte Dinge dann doch nicht verstecken kann.
Also das Laufzeitverhalten von unterschiedlichen Datenbanken ist da unterschiedlich.
Und wenn ich jetzt plötzlich Anfragen mache, die halt oder die Datenbank halt irgendwie Probleme hat, dann ist es vielleicht so, dass ich es länger brauche.
Aber das ist halt auch etwas.
was ich bei Netzwerken hätte.
Das heißt, ich kann aus der Anwendung erraten, was für ein Netzwerk ich da drunter habe, in gewissen Grenzen, weil ich zum Beispiel aus den Antwortzeiten rückschließen kann, ob ich halt ein Wi-Fi habe, wo die Antworten eher langsam sind, eine Mobilfunkverbindung oder halt irgendwie ein Ethernet.
Und darüber, das kann ich halt auch nicht vermeiden.
So, jetzt.
Mal sehen, Urs hat das noch irgendwie erläutert.
Ich meinte Abstraktion mehr im Sinne, wie ein U-Bahn-Plan zur Realität steht, nur die wesentlichen Infos.
Bei TCP ist mir die Art des Kabels egal, nicht im Sinne von Austauschbarkeit, zum Beispiel via Interfaces.
Genau, das ist halt das, was ich halt auch denke.
Es scheint halt zumindest indirekt durch, was halt in den Schichten darunter passiert.
Und genau, das ist auch eine Sache, die ich halt in dem Video gesagt habe.
Wenn ich halt diese Schichtenarchitektur habe, Und jetzt zum Beispiel eine Aufruffarbe gegen die Datenbankschicht, dann werde ich vielleicht Exceptions fangen.
Und diese Exceptions sind dann vielleicht ein Hinweis darauf, was in der Datenbankschicht vor sich geht, weil das eben technische Exceptions sein können.
Es könnte sein, dass ich da eine spezifische Oracle-Fehlermeldung und Oracle-Fehler sozusagen damit umgehe.
Und dann weiß ich eben sogar, dass ich Oracle nutze.
Und das weiß ich eben...
in der Logikschicht, obwohl ich eigentlich davon ja gerade sozusagen abstrahieren wollte.
Genau, das also sozusagen dazu.
Jetzt, also, und ein wichtiger Punkt bei der Austauschbarkeit ist halt irgendwie sowas wie, genau, also das ist halt sozusagen das Problem.
Und ein weiteres Problem, was halt diese Schichtarchitektur an dieser Stelle hat, ist, dass ich, also ich habe jetzt ein Drittsystem.
Ist dieses Drittsystem eher etwas, was sozusagen oberhalb der Logikschicht sein sollte oder ist das etwas, was unterhalb der Logikschicht sein sollte?
Ich finde das schwer zu entscheiden.
Also hier habe ich das jetzt irgendwie nochmal aufgemacht.
Also habe ich das halt eben.
Und wenn ich jetzt, ich kann jetzt entweder argumentieren, dass ich hier ein Drittsystem habe, was halt sozusagen eben so eine eher UI-artige Benutzung hat.
Also eben sagt, okay, ich rufe halt dann etwas auf.
Oder ich kann halt sagen, ist es genau umgekehrt.
Und das ist eigentlich irgendwie weird.
Also ich finde, es kann ja sein, dass dieses System beides tut.
Also dass ich da Daten hinschicken kann und Daten von denen bekomme.
Und dann ist es halt irgendwie überhaupt gar nicht klar, ob es eben oben oder unten sein sollte.
Irgendwie ist das so ein bisschen Beliebigheit in der Abhängigkeit.
Und deswegen ist eine Alternative, über die man sich halt Gedanken machen kann, eben genau so eine hexagonale Architektur.
Wie gesagt, in dem Video, ich verlinke das auch nochmal, erkläre ich halt in sechs Minuten, wie ich halt von der Geschichte in Architektur zu einer Exagonalen komme.
Und da ist jetzt Folgendes passiert.
Ich habe hier also den Logikkern und in dem Logikkern habe ich jetzt sowas definiert wie ein Database-Port.
Und dieser Database-Port sagt jetzt, was ich eigentlich erwarte von sowas wie der Datenbank.
Das heißt, hier ist halt eine Methode, die ich jetzt irgendwie erwarte, die ist halt innerhalb dieser Schnittstelle definiert.
Und jetzt kann ich dort hier sagen, dieser Adapter implementiert diese Methode, baut also genau das, was eben hier erwartet wird von dem Geschäftslogiker.
Und dadurch ist die Abhängigkeit halt in diese Richtung.
Das heißt also, der Adapter hängt ab von dem Port in dem Geschäftslogikkern und dadurch habe ich diesen ursprünglichen Abhängigkeitsfall genau umgedreht.
Den habe ich halt umgedreht, indem ich halt gesagt habe, okay, es ist jetzt eben so, dass in der Logik definiert wird, was die Schnittstelle ist und der Adapter implementiert die Schnittstelle.
Dadurch hängt der Adapter vom Logikkern ab, nicht mehr umgekehrt, wie das bei den Schichten der Fall wäre.
Und ich habe hier dann eben ein anderes, habe hier den UI-Port, der funktioniert ein bisschen anders, der definiert halt eine Schnittstelle, die in diesem Fall implementiert wird von der Geschäftslogik, wo jetzt die UI sagen kann, okay, cool, ich greife darauf zu und da habe ich jetzt wieder genau so einen Abhängigkeitsfall in Richtung Logik.
Und das hat halt zum einen den Vorteil, dass es sozusagen konzeptionell sauberer ist, dass das, wenn ich jetzt ein Drittsystem habe, was halt zum einen so ähnlich wie die Datenbank anbietet, dass ich halt Daten speichern kann, aber zum anderen eben auch so ist, wie die UI und irgendwie Daten liest und verarbeitet, dann kann ich das mit diesem Konzept umsetzen, indem ich eben entweder eine Schnittstelle habe, die angeboten wird von dem Geschäftsführergekern oder eine Schnittstelle habe, die erwartet wird von dem Geschäftsführergekern.
Und das ist halt sozusagen konzeptionell sauberer.
Außerdem ist das Testing einfacher, weil ich jetzt eben den Datenbankadapter beispielsweise Den Datenbankadapter kann ich jetzt irgendwie ersetzen durch Mock und ich kann irgendwie hier drüben den UI-Adapter ersetzen durch irgendeinen Testtreiber, der jetzt irgendwie versucht, die Geschäftslogik aufzurufen.
Und die sind auch prinzipienbedingt machbar, weil ich eben hier genau diese Schnittstellen habe.
Die kann ich ja von irgendwoher benutzen.
Und die Geschäftslogik kann jetzt gar nicht irgendwie aus der Datenbank irgendeine Exception fangen.
weil sie da eigentlich gar keine Sichtbarkeit hat, weil der Abhängigkeitsfall genau umgedreht ist.
Gut, das dazu.
Hauptvorteil davon ist nach meinem Empfinden eigentlich im Wesentlichen Testbarkeit, dass ich also die Sachen austauschen kann gegen eben Mox oder Testtreiber.
Und ich verlinke auch nochmal eine Episode, die ich gemacht hatte vor einiger Zeit mit dem Tom Hombergs und dem Johannes Seitz bei dem Heise Software Architektur Podcast.
Da haben wir irgendwie länglich gesprochen über das Thema Clean Architecture, was letztendlich eben genau synonym ist für hexagonale Architektur oder Portion Adapters.
Und der Tom hat da irgendwie auch Bücher drüber geschrieben.
Das wäre also etwas, wo man da nochmal tiefer sozusagen reingreifen kann.
Also diese Schichtung, diese drei Schichten sind halt eigentlich nicht das, was ich mir wünschen würde.
Ich glaube, dass die hexagonale Architektur so ein bisschen der bessere Ansatz ist.
Und in dem Video argumentiere ich, dass der Unterschied gar nicht so wahnsinnig groß ist.
Eigentlich geht es nur darum, dass ich eben eine Schnittstelle extrahiere, nämlich diese hier.
Und dann irgendwie, also nicht Repository oder die Geschäftslogik, oder die Geschäftslogik-Schnittstelle und dass man dann halt zum anderen den Datenbank-Adapter hat, der das halt implementiert oder den UI-Adapter, der das nutzt.
Dann, genau, also der Pizza für zwei schreibt halt gerade, programmiert man im KI-Zeitalter noch selbst?
Also da ist halt zum einen die Antwort, ja, es gibt Menschen, die noch selbst programmieren.
Natürlich gibt es die.
Zum anderen ist es halt so, für die Konzepte, die wir hier diskutieren, ist es halt so, dass das ja Architekturkonzepte sind.
Ich glaube, es ist halt hilfreich, die zu verstehen und die Implikationen zu verstehen.
Und vielleicht sozusagen der dritte Punkt an der Stelle.
Also ich bin ja nun Softwarearchitekt und tatsächlich Softwarearchitekturberater.
Ich sage ja auch, dass ich PowerPoint-Architekt bin.
Ich glaube, ich könnte meinen Job nicht machen, wenn ich nicht zumindest mal programmiert hätte.
Und wenn man sich anschaut, was halt andere Branchen tun.
Also ich verstehe, dass halt Metall bearbeitende Berufe immer noch Leuten beibringt, wie man halt feilt und nicht irgendwie sagen, hier ist übrigens eine CNC-Maschine, die macht das halt irgendwie alles vollautomatisch.
Und ich bin mir nicht sicher, warum das so ist, also warum das halt beigebracht wird, aber offensichtlich ist es eben so, dass trotz Automatisierung sowas wie Feilen noch etwas ist, was halt lernenswert ist, vermute ich, zu verstehen, was denn da eigentlich in der Automatisierung passiert.
Ich wüsste nicht, warum das bei uns anders sein sollte.
Also kann man natürlich machen, nicht?
Also man kann natürlich AI Code generieren lassen.
Alle, ich wäre sehr überrascht, wenn das halt langfristig zu erfolgreichen Projekten führt, wenn man nur Leute hat, die halt nicht programmieren können und die halt irgendwie Code generieren.
Hat die letzten...
70 Jahre nicht funktioniert dieser Ansatz, dass man halt sagt, wir haben halt Software-Engineer, Leute, die keine Software-Engineers sind und die halt Software entwickeln.
Wüsste ich nicht, warum das jetzt sich ändern sollte.
Gut, das dazu.
Jetzt gibt es, also das ist so ein bisschen der klassische Teil von dem, was man halt über Schichten und hexagonale Architektur beziehungsweise Port-Send-Adapters oder Clean-Architektur sagen kann.
Jetzt kommt irgendwie da ein Teil hinzu.
der so ein bisschen motiviert ist, ich muss gestehen, ich habe nicht geschaut, wo die Frage kam.
In meiner Erinnerung war es, glaube ich, bei Mastodon oder so.
Da hat irgendeine Person gefragt, wie viele Schichten sollte ich denn eigentlich in meinem System haben?
Und diese Frage ist halt insofern nachvollziehbar, als dass ja sozusagen in der Evolution man von zwei zu drei Schichten gekommen ist, was irgendwie die Frage aufwirft, ob man nicht vier Schichten haben möchte.
Die Antwort auf der Ebene ist halt irgendwie eigentlich eher eine hexagonale Architektur, die dann eben nicht mehr Schichten hat, sondern sagt, alles hängt vom Geschäftsrugekern ab.
Und es gibt da in dem Kontext noch ein anderes Thema.
Und das ist halt die Idee, dass sich durch eine Übersetzung, eine Übersetzungsschicht, Dinge voneinander entkoppelt.
Das heißt also, ich habe zum Beispiel, ich spreche ein Drittsystem ab.
an, dieses Drittsystem hat irgendeine Datenrepräsentation, die es halt irgendwie benötigt, ich habe eine interne Datenrepräsentation und es wirkt jetzt so, als wäre es schlau, dass ich eine Licht baue, die das interne Modell in das externe Modell übersetzt.
Und das ist das, was ich eigentlich als nächstes diskutieren wollte.
Ich gucke nochmal, hier ist von Sigrado.
Sie schreibt, die separaten Interfaces sind überflüssig.
Repository wird über Dependency Injection reingereicht.
Die Richtung der Pfeile ist egal, weil es sowieso eine Code-Basis ist.
Jetzt muss ich mal kurz, also schauen wir noch mal kurz auf das Diagramm.
Achso, genau, wir haben es ja noch offen.
Also was sagt er?
Die separaten Interfaces, das müssen also diese hier sein.
Die sind überflüssig.
Repository wird über Dependency Injection reingereicht.
Ja, das ist aber egal.
Also ich sehe hier nicht, wie die Objekte zueinander in Beziehung stehen, sondern ich sehe die Beziehung zwischen sowas wie Cluster und Interfaces.
Das sind ja nicht die konkreten Objekte.
Die Richtung der Pfeile ist egal, weil es sowieso eine Code-Basis ist.
Die Richtung der Pfeile ist eben nicht egal, weil, also ich kann es nochmal sozusagen das davor zeigen.
Hier ist halt das Problem.
dass die Geschäftslogik das Repository kennt.
Das kann ja zum Beispiel sein, dass hier eine Exception zurückfliegt und dann kriege ich halt dort unabsichtlich in der Logik eine Abhängigkeit zu der konkreten Technologie.
Und das ist halt insbesondere für Testing ein Problem.
In der schon zitierten Folge von dem Heise Architektur Podcast haben wir das halt diskutiert anhand von so einer SAP Exception, die halt irgendwie im gesamten System, in der gesamten Logik drin war und halt irgendwie das Testen zur Hölle gemacht hat.
Und das kann ich hier eben vermeiden, weil ich hier ganz sicher nur von der Logik aus definiere, was irgendwie da sein soll.
Und es können sich gar keine solchen technischen Abhängigkeiten einbleichen, weil ich eben genau den Abhängigkeitspfeil umgedreht habe.
Und es geht hier um eine statische Abhängigkeit, also eben wie um die Code-Abhängigkeiten.
Es geht also, Dependency Injection spielt da halt keine Rolle.
Also das ist sozusagen der Punkt.
Gut, danke für die Frage.
Ja, also wir sind bei dieser Frage, wo ich jetzt also sage, ich habe halt ein Modell, zum Beispiel von einem Drittsystem und ich habe mein eigenes Modell und ich führe jetzt eine Schicht ein, um die beiden halt zu entkoppeln.
Was jetzt bedeutet, dass ich meine interne Repräsentation umkopiere in eine externe Repräsentation.
Also ich sage dann halt, okay.
Ich habe halt hier eine interne Repräsentation von dem Kunden, ich habe eine externe Repräsentation von dem Kunden und kopiere das halt ineinander über, weil ich ein Copped sein will.
Und das ist insofern nachvollziehbar, dass halt so eine externe Repräsentation beispielsweise schwerer änderbar ist, weil andere Teams da dranhängen.
Das ist eben eine Schnittstelle, die ich nach außen habe.
Das heißt, es kann sehr gut sein, dass halt andere Teams eben diese Kundenrepräsentation nutzen.
Und die kann ich eben nicht so ohne weiteres ändern.
Das heißt, wenn ich eine interne Änderung haben habe, dann möchte ich die vielleicht nicht nach draußen exponieren, weil ich dann potenziell mit ganz vielen abhängigen Systemen oder sogar abhängigen Menschen reden möchte.
Das heißt, ich hoffe, dass eben diese Änderung sozusagen in der Abstraktionsschicht hängen bleibt und ich dann dafür sorgen kann, dass diese Änderung eben nicht...
durchschlägt zu irgendwelchen Konsumenten einer Schnittstelle.
Und das ist halt insbesondere dann sinnvoll oder vielleicht schlau, wenn ich halt externe Konsumenten habe, mit denen ich halt reden müsste, wenn ich halt eine Änderung mache.
Das heißt, ich versuche halt eher eine Kommunikation mit anderen Leuten zu vermeiden, indem ich halt sage, alles klar, ich mache das halt irgendwie, ich entkoppel das halt.
Und das führt dann eben, also nicht, Meine Datenbank sozusagen, ich habe ein internes Modell, was vielleicht durch die Datenbank inspiriert ist.
Ich habe ein externes Modell, was vielleicht durch die Ansprüche inspiriert ist.
Dann kopiere ich das halt irgendwie ineinander über.
Die wesentliche These dabei ist, dass ich es hinbekomme, dass Änderungen in einer Schicht sozusagen hängen bleiben.
Das heißt, ich habe dann gewonnen, wenn tatsächlich meine interne Repräsentation sich ändert und ich das nicht...
durchreichen muss nach draußen.
Das heißt also, wenn ein anderes Team zum Beispiel kommt und sagt, okay, ich möchte halt folgende zusätzliche Informationen haben, dann werde ich diese Änderung möglicherweise an der externen Schnittstelle machen und auch bei mir intern, weil ich diese zusätzlichen Informationen vielleicht erstmal in der Datenbank überhaupt anlegen muss und dort haben muss.
Dann habe ich halt verloren, weil diese Änderung halt durchgeht durch das externe Team, durch meine Abstraktionsschicht.
und durch meine interne Implementierung.
Wenn ich eine Änderung habe, die das andere Team nicht interessiert, dann bleibt sie da halt irgendwie hängen.
Das ist also der Vorteil und die Kosten dafür sind, dass ich eben diese Schicht habe und die bedeutet eben, wenn ich jetzt mein internes Modell exponieren würde direkt, dann müsste ich nicht umkopieren, ich habe dort also zusätzlichen Code, ich muss zusätzlich umkopieren und habe irgendwie zusätzlichen Aufwand.
Und das ist etwas, was manchmal in anderen Situationen, sagen wir mal, so bedingt gut läuft.
Also ich habe ja jetzt gesprochen über eine externe Schnittstelle, wo also ein anderes Team ist.
Da habe ich eine andere Art von Änderbarkeit.
Und was ich ja jetzt auch machen könnte, wäre, dass ich...
Hier bei meiner Dreischichtenarchitektur, die also innerhalb eines Systems ist, das ist also ein anderer Fall, da habe ich nicht eine externe Schnittstelle, sondern ich habe hier selber geschrieben die UI, die Logik und die Datenbank.
Und da könnte ich jetzt irgendwie auch sagen, okay, hier ist ein Ding, was halt irgendwie umkopiert in ein UI-Modell.
Hier ist ein Ding...
was halt umkopiert in ein Logik-Modell.
Das heißt, ich habe dann hier eben drei Modelle, eins für die UI, eins für die Logik, eins für die Datenbank.
Und da habe ich möglicherweise eine andere Situation, weil es kann gut sein, dass halt eine Entwickler irgendwie vorm Rechner sitzt und sagt, ich mache jetzt mal eine Änderung.
Und dann macht sie das halt alleine.
Ich muss also nicht mit externen Teams sprechen.
Und eine wesentliche These, die ich jetzt in den Raum stellen würde, ist, eine typische Änderung geht durch alle diese Schichten durch.
Das heißt, ich würde erwarten, wenn ich hier in der UI was anderes anzeigen möchte, dann habe ich vielleicht auch eine Änderung in der Logik und vielleicht auch eine Änderung in der Datenbank.
Das heißt also, eine typische Änderung wird halt nicht in einer Schicht sein.
Und dann habe ich halt irgendwie das Problem, dass diese Änderungen halt prinzipiell unbedingt nicht in diesen Schichten hängen bleiben können, weil ich ja durch alle Schichten durch muss.
Also ich sage jetzt, ich möchte das Geburtsdatum von irgendwelchen Kundinnen erfassen.
Das heißt, ich muss das in der UI erfassen.
Ich muss eine Logik haben, die halt sagt, ist das eigentlich ein gültiges Geburtsdatum?
Passt das alles?
Ich werde das für irgendwas verwenden, also herausfinden, ob die Menschen halt volljährig sind oder was auch immer.
Und ich habe es halt in der Datenbank abgespeichert.
Diese Änderung wird halt durch alle Schichten durchgehen.
Und jetzt stehen diese zusätzlichen Daten eigentlich nur noch im Weg.
Das heißt, ich muss sie halt irgendwie umkopieren.
Aber ich gewinne halt nichts, weil eben diese Änderung durch alle Schichten, So, und das ist eigentlich so ein bisschen, wie soll ich sagen, also da wäre jetzt die Aussage, dass diese Umkopierschichten, die jetzt irgendwie sagen, okay, nehmen halt Datenmodelle, umkopieren die halt irgendwie um, dass ich die vielleicht nicht einführen möchte, sondern irgendwie ein Datenmodell haben möchte, was halt in der Datenbank bis zur UI durchgereicht wird.
Und das ist etwas, wo, also letztendlich ist das nicht eine Architekturentscheidung und hier ist halt irgendwie die Idee, dass ich halt oder die Frage, ob ich eben tatsächlich dafür sorgen kann, dass halt Änderungen in irgendwelchen Schichten halt hängen bleiben.
Und das nicht der Fall ist, macht diese Architekturentscheidung keinen Sinn.
Und da kommt jetzt noch eine andere Dimension und das ist etwas, was ich zumindest meiner Erinnerung halt schon erlebt habe und was halt, glaube ich, auch viele Entwickler inhaben.
Ich mache halt eine kleine Änderung.
Ich ändere also einen Attribut hier unten und plötzlich muss ich halt irgendwie an sieben Stellen dieses Attribut ergänzen, das halt irgendwie tun und machen und habe irgendwie wahnsinnig viel Aufwand, obwohl ich eigentlich nur Kleinkram mache.
Und das hängt eben zusammen damit, dass ich dann eben diese verschiedenen Schichten habe und versucht habe, die zu entkoppeln, was halt keinen Sinn macht, wenn die Änderungen sowieso typischerweise durch alle Schichten gehen.
So, jetzt ist da ein Kommentar, was in den Schichten hängen bleibt, sind eher technische Umbauten.
Das UI braucht eine Liste gleich, nicht per Nachladen.
Die DB hat ein Objekt eingebettet in der Masterwelle, nicht als zu 1 Detail.
Ja, aber das impliziert, glaube ich, nicht unbedingt ein zentrales Datenmodell wäre oder eben so ein Umkopieren impliziert das halt nicht.
Der Wolfgang Frisch, 42.
59, 42 gerade geschrieben.
Und dieses Umkopieren und das dadurch versuchte Entkoppeln macht, glaube ich, keinen Sinn, weil die Dinge halt durch die Fachlichkeit aneinander gekoppelt sind.
Das schreibt er jetzt auch nicht.
Das geht eben nicht durch alle Schichten.
Ja, genau nicht.
Also die Schichten machen Sinn, weil es halt bestimmte Dinge gibt, die halt vielleicht nur in der Datenbank relevant sind und die eben nach oben nicht transparent sein müssen.
Für mich ist allerdings das Hauptargument, dass ich nicht wissen will, was da unten passiert, sondern ich kann in der Logikschicht mich halt um die Logik kümmern und muss das in der Datenbank halt nicht wissen, was da passiert.
Das ist mir so ein für mich schneidend Thema für mich.
Aber wie auch immer.
Jetzt ist noch ein Aspekt.
Also, das bedeutet ja jetzt Folgendes.
Will ich so etwas einbauen, damit Daten umkopiert werden?
Und das ist ja eine Architekturentscheidung.
Und eine Frage, die ich jetzt eigentlich stellen würde, ist, ist es dramatisch, wenn ich diese, also wir haben gerade darüber diskutiert, wenn ich die sozusagen auf Vorrat einbaue und ich später feststelle, dass ich sie in Wirklichkeit nicht nutze oder sie mir nichts bringen, weil eben Änderungen nicht in den jeweiligen Schichten hängen bleiben.
Dann bezahle ich halt Aufwand, weil ich halt Änderungen machen muss, die halt irgendwie durch alle Schichten gehen.
Und ich muss irgendwie Daten umkopieren und das ist halt irgendwie nervig.
Jetzt ist ja die Frage, ich mache das umgekehrt.
Also ich habe irgendwie ein Modell, was halt in den verschiedenen Schichten drin ist.
Und ich möchte das halt irgendwann revidieren.
Also ich stelle halt fest, es ist vielleicht doch gut, ein separates UI-Modell zu haben.
Dann...
kann ich meine Behauptung, die Entscheidung zugunsten von, ich habe irgendwie die Daten, die ich überdurchreiche, relativ einfach revidieren, indem ich eben anfange, ein anderes Datenmodell in der UI zu haben, was halt erstmal dem Allgemeinen entspricht, was ich ja davor hatte.
Und dann ändere ich das schrittweise und mache halt Änderungen jeweils nur in einem Teil.
Das heißt also, ich mache, Ich kann das zeigen.
Ich fange halt irgendwie an und sage, okay, ich habe hier dieses eine Datenmodell, was halt über alle geht.
Dann sage ich halt, okay, ich baue mir hier halt ein separates und das ist halt erstmal eins zu eins gegen...
Ups, interessant.
Also das ist erstmal eins zu eins gegenüber dem allgemeinen Modell.
Das wäre ja ein möglicher erster Ansatz.
So, und dann baue ich hier halt irgendwie etwas dazu.
So, und diese Änderung, also dieses Modell sozusagen zu kopieren, hier eine 1 zu 1 Übersetzung zu bauen und dann schrittweise dort Änderungen zu machen, das ist, würde ich behaupten, nicht deutlich schwieriger, wenn ich das später mache, als wenn ich es vorher mache.
Und das bedeutet, ich kann mir diese Entscheidung zu uns in dieses einen Modells und dann sozusagen lazy, wenn ich das benötige, ein zweites Modell einführen.
Das ist vielleicht der bessere Ansatz, weil ich darüber die Entscheidung leicht revidieren kann.
Und wenn es eben stimmt, dass halt die typischen Änderungen in allen Schichten stattfinden, dann habe ich eben an der Stelle gewonnen und habe halt weniger Auffahrt.
Genau, Ralf verabschiedet sich gerade und sagt, dass er halt irgendwie einen Folgetermin will.
Viel Spaß dort.
Bedeutet halt für mich so ein bisschen, dass ich mir nicht sicher bin, ob ich Schichten auf Vorrat einführen würde.
Mein Gefühl ist, das ist ein Gefühl, also es ist jetzt nicht so, dass ich halt harte Fakten dafür präsentieren kann.
Mein Gefühl ist, dass es vielleicht schlauer ist, das dann einzuführen, wenn ich es irgendwie tatsächlich benötige.
So, jetzt schreibt der Pizza für zwei, die UI verlangt ja oft schon nach einer eigenen Datenstruktur, sonst müsste man ja anfangen in der UI mit JavaScript oder was auch immer normalisierte Datenstrukturen umzubauen.
Ja, guter Punkt, also wenn ich da sozusagen einen Technologiebruch habe und jetzt wenn wir sagen, okay, ich habe halt da eine andere Programmiersprache, dann ist das nochmal ein anderes Thema.
Für mich ist die UI, über die wir hier reden, nicht also Java-Server-UI und eben nicht JavaScript, also sprich das Zeug, was irgendwie HTTP beantwortet und vielleicht HTML-Seiten erzeugt.
So, was hat Wolfgang geschrieben?
Wolfgang Frech, 5942, ein Modell hat auch Kosten in der Phase bis zum Umbau, zum Beispiel das Neuanlegen hat, nicht alle Attribute des dargestellten Objekts oder technische Attribute, Modified Add, bitte nicht in Logik.
Verständnisaufwand kostet auch.
Ja, guter Punkt.
Also es kann sein, dass es sinnvoll ist, da irgendwie zu schauen, dass man in bestimmte Informationen, die halt irgendwie eine Schicht nicht verlassen sollte, dass die eben tatsächlich die Schicht nicht verlassen.
Und ja, ich würde auch sagen, dass das mit dem Verständnis halt ein Thema ist.
Man kann da versuchen, was zu machen, indem man halt, also nicht sowas wie ein, So ein, was hattest du geschrieben?
Modified by, add oder by, was ich vielleicht in der Datenbank habe, das könnte ich auch in so ein Hilfsobjekt packen.
Und könnte halt sagen, okay, wenn ich diese Informationen benötige über den Kunden, dann habe ich halt ein Hilfsobjekt, was halt nur diese Informationen enthält.
Und das ist dann irgendwie lokal für die Datenbankgeschichte.
Wäre halt auch eine Idee.
Erzähl mal einem Junior, welcher Attribute er nicht hernehmen kann.
Also, was man auch machen kann, beispielsweise ist eben für, also, eine Schnittstelle definieren.
Also ich könnte jetzt sagen, es gibt in der UI eine Schnittstelle, die halt sagt, also tatsächlich ein Interface, wenn ich halt in Java bin, und diese Schnittstelle sagt, das sind die Sachen, die halt irgendwie sozusagen erlaubt sind.
Und das ist halt nicht in dem UI-Layer definiert.
Also ich habe hier eine Schnittstelle, die halt in dem UI-Layer definiert und sage dann, nicht nur diese Sachen sind halt nutzbar und habe dann in der Logik sozusagen die Implementierung.
Das ist schwierig, weil ich dann tatsächlich Abhängigkeitspfeile umdrehe, aber sowas wäre denkbar.
Wolfgang ist kein Junior.
Ja, das glaube ich auch.
Also sprich, Sichtbarkeit und was erlaubt ist, das würde ich versuchen durch ein Typsystem zu lösen.
Also wenn ich halt im Typsystem sage, das sind die Attribute, die halt erlaubt sind, dann bin ich halt sicher, dass exakt nur diese Attribute verwendet werden.
Das kann man ja versuchen hinzubekommen.
Genau, danke für die Diskussion.
So, was ich jetzt eigentlich noch sagen wollte, achso, und ich hatte ja gedacht, das Thema sei vielleicht gar nicht für eine Stunde, aber offensichtlich ist es das halt irgendwie dann doch.
Man kann über alles mindestens eine Stunde reden.
Ich wollte eigentlich noch eingehen auf ein Domain-Driven-Design-Pattern, das ist das Anti-Corruption-Layer.
Das ist halt ein Pattern aus dem Domain-Driven-Design, aus dem Strategic-Domain-Driven-Design.
Und ich glaube, da ist noch, Das ist für mich deswegen wichtig, weil ich in meinen Trainingssicherheit mache, manchmal die Diskussion bekomme, ja, ich nehme jetzt Anti-Corruption-Layer mit der Begründung, die ich vorhin gebracht habe, also mit einer Entkoppelung.
Was irgendwie sagt, ich baue eine Schicht ein und wenn ich eine Änderung habe, bleibt das vielleicht in dieser Schicht hängen und ich muss diese Änderung halt nicht weiter durchführen.
Das ist nicht das Anti-Corruption-Layer.
Das Anti-Corruption-Layer sagt, ich baue eine Schicht ein.
um Korruption zu vermeiden.
Deswegen heißt es Anti-Corruption-Layer.
Und das bedeutet, ich möchte jetzt dafür sorgen, dass ein irgendwie nicht vernünftig gebautes Modell, also mein Beispiel ist ja immer ein Mainframe-Modell, wo es halt irgendwie so Bit-Främmeleien gab und man dann wie gesagt hat, okay, also wenn das Bit gesetzt hat, hat das halt folgende Semantik.
Wenn das Bit gesetzt ist, ist halt folgende Semantik.
Und das ist eben etwas, was man heutzutage durch irgendwelche Booleans ausdrückt und eben nicht mehr durch irgendwelche Bits.
Und das bedeutet, ich habe jetzt vielleicht ein neueres Modell, wo ich irgendwie sage, nicht, das ist irgendwie gut benutzbar in einer modernen Programmiersprache und ich habe das alte Modell, was halt irgendwie so Bit-Framelei hat und wo man vielleicht auch jetzt gar nicht mehr erkennen kann, weil die Sachen halt irgendwie komisch benannt sind, was tatsächlich dort gemeint ist mit bestimmten Dingen und da sind irgendwie keine entsprechenden Variablen da.
Und das erzeugt begrenzt halt die Korruption.
Das ist was anderes.
Und ein Beispiel, wo ich mir das vorstellen, oder wo das, glaube ich, sehr sinnvoll ist, ist, wenn ich halt so ein Big Ball of Mud habe, also ein großes, unstrukturiertes, altes System, dann ist ja etwas, wir haben auch eine, ich habe eine Folge gemacht zu diesem Big Ball of Mud Paper.
Und eine Sache, die da halt eine Rolle gespielt hat, ist, dass man den Big Ball of Mud zumindest so haben möchte, dass er sich jetzt nicht noch weiterfrisst.
Also wenn ich halt irgendwie so ein großes, unstruggiertes System habe, dann ist eine Strategie damit umzugehen, zu sagen, okay, das ist jetzt das große, unstruggierteste System.
Ich will nicht, dass es weiter wächst, also baue ich eine Schnittstelle ein.
Und diese Schnittstelle könnte dann zum Beispiel ein Anti-Corruption-Layer sein, was eben dafür sorgt, dass die Korruption begrenzt bleibt auf das alte System.
Da ist es dann eben sinnvoll, weil es halt diese Verschmutzung begrenzt.
Und das ist auch wiederum etwas, wo der Eric Evans in seinem Paper, eine von den frühen Episoden war ja auch, war über dieses Paper, ich packe da auch nochmal ein Ding in die Show Notes, eben darüber diskutiert hat, dass es manchmal gar nicht so einfach ist, irgendwie aus diesem alten System Sachen sozusagen rauszuziehen.
Das sind halt typischerweise Anti-Corruption-Layer, das sind auch typischerweise Dinge, die halt in dem modernen System drin sind.
weil ich es da halt leichter habe, solche Adapter oder Übersetzungsschichten zu schreiben.
Und das ist eben etwas, was natürlich total sinnvoll ist.
Was ist denn die Alternative?
Die Alternative wäre, dass ich das Modell aus dem Mainframe, was halt irgendwie unschön ist, in meinem System übernehme.
Und das ist halt...
Dadurch korrumpiere ich tatsächlich das neue System, weil es eben denselben Ansatz wählt wie das alte System für die Datenmodellierung.
Ich habe Schwierigkeiten mir vorzustellen, unter welchen Bedingungen das eine volle Architekturentscheidung ist.
Also wenn ich was neu mache, will ich ein neues Modell haben, ich muss übersetzen, und zwar deswegen, weil ich die Korruption vermeiden möchte.
Und da macht so etwas halt Sinn.
Es ist aber nicht eine Entkopplung für Änderung.
Ich wäre überrascht, wenn sich dieses Modell, nachdem das System ja alt und wahrscheinlich schwer änderbar ist, wenn sich dieses Modell hat, signifikant ändert.
Es macht gar keinen Sinn, sich dagegen Änderungen zu entkoppeln, weil da wahrscheinlich nie welche sind.
Insgesamt mein Gefühl, also es ist halt auch vielleicht alt, Oder andersrum, ich bin in einer Welt groß geworden, ich glaube, so ist es halt richtig, wo halt eigentlich mehr Schichten sozusagen besser sind.
Und das, glaube ich, macht halt irgendwie keinen Sinn.
Und deswegen nicht bis eine Architekturentscheidung, dann ist die Frage, ob das sinnvoll ist.
So, der Wolfgang hat geschrieben, die Struktur des UIs und seines Modells ist aus der strengen Sicht der fachlichen Modellierung auch Korruption, die zu einer denormalisierten DB-Struktur.
Ja, also eine denormalisierte DB-Struktur kann ich halt versuchen durch einen OR-Mapper in ein Objektmodell zu bekommen.
Versuchen, das kann manchmal auch schief gehen.
Das ist ja mir die Frage, ob das halt schlau ist.
Also sprich, ich kann jetzt, sagen wir mal die Grafik, wir reden halt im Prinzip darüber, dass ich hier ein Modell habe.
Und ich kann jetzt versuchen, dass die Sachen aus der Datenbank in dieses Modell reinpassen.
Und das kann ich halt versuchen, indem ich hier in der Datenbankschicht irgendetwas habe, was das übersetzt.
Ein OMAP hat zum Beispiel das Versprechen, dass das einfach funktioniert.
Das ist natürlich nicht so.
Also wenn es so stark demononormalisiertes Modell habe, dann muss ich da vielleicht mir selber Gedanken überlegen.
Wir haben schon darüber gesprochen, wenn ich hier über UI spreche, dann meine ich eben auch ein Backend-UI eigentlich.
Und da ist jetzt die Aussage, die Struktur des UIs und seines Modells ist aus der strengen Sicht der Fachlimitierung auch Korruption.
Naja, also ich würde halt glaube ich, also auf die Gefahr hin, da sozusagen mich unbeliebt zu machen, Das implizieren, also wie soll ich sagen, damit wird halt, andersrum, damit stellst du halt eine These auf.
Also du sagst im Prinzip, gottgegeben dadurch, dass die UI halt andere Dinge tut als die Logik, muss die Logik ein anderes Modell haben.
Ich empfinde die UI eher als eine Fernsteuerung, die halt im Prinzip die Logik fernsteuert.
Und dann wird sie halt auch eher das Modell aus der Logik.
Das ist aber eine abstrakte Diskussion.
Das heißt, eigentlich sind wir jetzt an der Stelle, wo du, Wolfgang, sagst, okay, ich habe halt die UI, die UI hat ein eigenes Modell, das ist halt irgendwie anders als das Logikmodell, ich sollte es sinnvollerweise übersetzen.
Ja, genau.
Also wenn das halt so ist, wenn ich dort zwei verschiedene Modelle habe, dann sollte ich sie übersetzen.
Was ich versuche zu sagen ist, dass ich das Gefühl habe, dass diese Übersetzungen häufig auf Vorrat gemacht werden.
Und ich würde halt versuchen, erstmal mit dem einfachsten Ansatz durch die Tür zu kommen, was eben ist, diese Übersetzung halt nicht zu bauen, weil ich halt behaupten würde, ich kann sie halt im Nachhinein einfacher einbauen.
So, und das müsste, also das wäre für mich ein typisches Beispiel, wo sozusagen nicht so eine abstrakte Diskussion aus dem Stream und irgendwie zwischen Architekturmenschen halt irgendwie ganz nett ist, aber das würde ich jetzt gerne an einem konkreten Beispiel diskutieren.
Und da würde ich jetzt irgendwie auch, also wie soll ich sagen, deine Meinung, Wolfgang, ist nachvollziehbar auf einer abstrakten Ebene.
Ich habe halt irgendwie erstmal eine andere.
Aber das würde ich dann halt am konkreten Beispiel durchdiskutieren.
Und ich würde mich halt auch in einer Consulting-Situation nicht davon abbringen lassen, das an einem konkreten Beispiel durchzudiskutieren, weil mir das, weil sozusagen beide Wege richtig sein können oder vorteilhaft sein können.
Und das können wir erst am konkreten Beispiel entscheiden.
Und deswegen ist vielleicht auch das Feedback halt gut, weil es halt im Prinzip sagt, hey, Also es gibt Situationen, wo das, was du halt gerade sagst, irgendwie nicht stimmt.
Ja.
Was ich allerdings sagen würde, ist, die Architekturentscheidung muss begründet sein.
Wenn du eine Begründung hast, eine konkrete Begründung, ist das halt irgendwie immer gut.
In deinem Video hattest du ja auch einen UI-Port.
Genau, den müsste ich auch zeigen können.
Da ist er.
Was ist konkret der Grund dafür?
Die Dependency geht ja...
bereits in die richtige Richtung.
Guter Punkt.
Also ich habe das in erster Linie, also es geht darum, dass ich die Geschäftslogik habe.
Die Geschäftslogik hat jetzt eine zusätzliche Schnittstelle, die ich UI-Port genannt habe, die eben genutzt werden kann von der UI.
Und was Phyllis Sporos, hört sich für mich nach MR an, gerade sagt, ist, dass das ja eigentlich überflüssig ist.
Das stimmt.
Ich wollte darauf aufmerksam machen, dass dieses Konzept, das ist eher eine didaktische Sache, mit den Ports auch funktioniert, wenn der Abhängigkeitsfile umgekehrt ist.
Und eine von den Sachen, die man da halt einführen oder über die man da diskutieren kann, ist, dass darüber klar ist, welcher Teil von der Geschäftslogik tatsächlich von der UI benutzt wird.
Und da hatten wir vorhin ja auch diese Diskussion, hey, Gibt es halt irgendwelche Dinge, also gibt es halt Objekte, welche Attribute darf ich halt in der UI tatsächlich benutzen oder sehen?
Das könnte ich jetzt auch in dem Port machen.
Ich könnte jetzt in dem Port sagen, okay, es gibt halt eine Schnittstelle, die Schnittstelle definiert halt eine Schnittstelle, die halt von irgendeinem Datenobjekt, wie zum Beispiel ein Produkt, implementiert wird und diese Schnittstelle enthält eben nur die Sachen, die durch die UI...
genutzt werden.
Das heißt, ich habe da die Möglichkeit, die Sichtbarkeit einzuschränken.
Also eben nur die Dinge tatsächlich zu exponieren, die Geschäftslogik, die halt irgendwie in der UI auch genutzt werden darf oder soll.
Ich, also, wie soll ich sagen, es ist ein guter Hinweis darauf, dass man das auch überlegen könnte, lazy einzubauen.
Also ich könnte jetzt irgendwie erstmal sagen, okay, ich lasse halt die UI hier drauf irgendwie zugreifen.
Weil ich sozusagen erstmal alles öffentlich mache, bedeutet dann aber, dass ich, das wäre vielleicht der andere Punkt, dass ich halt Abhängigkeiten einschleichen kann zu Dingen, die halt eigentlich nicht exponiert sind.
Also das hier macht die Schnittstelle eben nochmal explizit, dieser Port macht die Schnittstelle explizit und das ist halt die Existenzberechtigung.
Ob man jetzt den unbedingt braucht, ist eine gute Frage.
Gut, ich...
Schauen nochmal, ob es Fragen gibt oder weitere Kommentare.
Ansonsten wäre es das dann, glaube ich, für heute.
Ich bedanke mich für die Aufmerksamkeit.
Und das Nächste, was jetzt passiert hier im Stream, ist, dass wir am 17., das müsste der, genau, das ist der Dienstag, da haben wir die Fischbue vom Software Texture Gathering zum Thema Friction is a Feature.
Navigating the inevitable tensions of software architecture mit einer ganze Menge Leuten.
Also mein Kollege Lukas moderiert das.
Teilnehmen werden Gitte Kitka, die wir ja vor kurzem Jahr hatten.
Dylan Beatty hatten wir auch vor kurzem Jahr.
Sam Newman hatten wir vor längerer Zeit hier.
Alan Holub, Jackie Reed hatten wir auch letztes Jahr da.
Adele Carpenter und Lisa Maria Schiefer wird auch dabei sein.
Dann würde ich sagen, vielen Dank nochmal.
Also ich gucke nochmal.
Ne, mehr Fragen habe ich nicht.
Und ja genau, hier ist noch ein Hinweis von dem Niklas, dass er bei meinem Flex-Training in Hannover dabei war.
Also nicht Trainings.
Und er schreibt, er war bei einem Flex-Training in Hannover dabei, war super, danke dafür.
Also die nächste Möglichkeit, ein Training mit mir zu genießen, ist hat der 1.12.
das Domain-Driven-Design, der Saniert-Legacy-Training.
Achso, oh, ah.
Guter Punkt noch inhaltlich.
Es gibt auch Callbacks von der Logik zum UI für Aktualisierung.
Wenn kein Callback alles synchron, dann geht es auch später einzubauen.
Wäre auch etwas, was man in dem Port haben könnte, dass man halt irgendwie Callbacks definiert, die hat die UI implementiert, um da irgendwie Informationen zu bekommen.
Und Wolfgang hat sich bedankt.
Ich bedanke mich und wünsche schon mal ein schönes Wochenende und bis dahin.
A note from our team.
Software Architecturum Stream will be streaming live from the ISAQB Software Architecture Gathering in Berlin this November.
Join us online.
You'll find more about the program and special discount code for our community on our website software-architectur.tv
