Hexagonale Architektur in Microservices
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Subtitle |
| |
Title of Series | ||
Number of Parts | 94 | |
Author | ||
License | CC Attribution 4.0 International: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/45614 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
FrOSCon 201963 / 94
7
10
12
14
15
16
17
20
22
23
26
27
28
29
30
31
32
33
36
37
38
39
41
44
45
48
52
53
55
56
57
58
60
61
62
64
66
67
74
76
77
78
79
81
83
84
93
00:00
HTTPDevice driverEnterprise architectureJavaScriptInternetSoftwarePoint cloudXMLUMLLecture/Conference
01:28
Internet service providerClient (computing)HTTPSoftware repositorySpring (hydrology)String (computer science)HexagonModemPriority queueWeb serviceMobile appProduct (category theory)SoftwareFlow separationFRAMEWORK <Programm>DatabaseCodeSoftware repositoryMUDHTTPSocial classHexagonModel View ControllerObject (grammar)Ecke
10:35
CountingMEGAMIKE <Programm>ValidationEckeQuantum stateCodeInterface (computing)SIMPL <Programmiersprache>Invariant (mathematics)Interface (computing)XMLProgram flowchart
14:20
User interfacePRINCE2Open sourceMobile appSQLYouTubeMobile appDirection (geometry)CodeDataflowDevice driverGenerating functionSoftware repositoryCASComputer fileConstructor (object-oriented programming)Invariant (mathematics)String (computer science)Service-oriented architecturePlane (geometry)Program flowchart
21:45
SQLHTTPInformationHTTPEckeMobile appValidationSoftware repositoryMach's principleWeb serviceDatabaseSoftwareDevice driverProduct (category theory)Queue (abstract data type)Event horizonDirection (geometry)RoutingSQLClient (computing)Template (C++)Atomic nucleusInvariant (mathematics)Software testingPlane (geometry)Soap <Programm>CodeXMLProgram flowchart
29:10
World of WarcraftOpen sourceAPILeadSoftware repositoryMobile appProduct (category theory)CodeDefault (computer science)Web serviceMAPPERObject (grammar)Pyramid (geometry)Grand Unified TheoryInterface (computing)Direction (geometry)StatistikerLink (knot theory)Liste <Informatik>Canonical ensembleSQLSystems <München>Business IntelligenceSoftware testingEvent horizonAtomic nucleusBoom (sailing)Großes SystemDurchschnitt <Mengenlehre>Invariant (mathematics)Overhead (computing)FRAMEWORK <Programm>InformationAbbildung <Physik>World of WarcraftMach's principleXML
36:34
ARCHIVE <Programm>IndexHexagonWEBXMLUMLProgram flowchart
37:25
Internet service providerARCHIVE <Programm>HexagonIndexCodeDevice driverWEBLink (knot theory)Program flowchart
39:16
Constraint (mathematics)DatabaseComputer animation
40:21
CountingANNA <Programmiersprache>Constraint (mathematics)ValidationConstraint (mathematics)MicrosoftService-oriented architectureDatabaseExecution unitWeb serviceDomain nameSoftwareMUDE-commercePlane (geometry)HTTPStructural loadBus (computing)Computer animationLecture/Conference
48:54
openSUSEWorld Wide WebXMLComputer animation
Transcript: German(auto-generated)
00:07
Ja, schön, dass ich heute da sein darf. Ich hatte letztes Jahr tatsächlich das erste Mal hier auf der Froska meinen allerersten Talk of my Conference und daher freut es mich, dass ich auch dieses Jahr hier wieder reden darf. Ich habe ein Thema mitgebracht, die hexagonale Architektur.
00:22
Ich erzähle euch gleich, was das alles ist, kurz mal zu mir. Wer bin ich? Mein Name war Christian Ivancik, ich habe vor drei Wochen geheiratet, ich heiße jetzt Schmidt. Das ist ganz spannend, gerade auch im Zuge der wachsenden Überwachung im Internet, und mich findet man nicht mehr. Andere Satz Herausforderung, versucht man, euren Namen im Internet zu ändern, das ist
00:43
nicht so trivial. Wo komme ich her? Ich bin seit 2010 angestellt bei der Terrain Solutions in Bonn, uns findet man auch als Stand da vorne, irgendwo direkt am Eingang. Was sind so meine Steckenpferde, im Endeffekt auch berufsbedingt ein bisschen
01:01
reingerutscht, alles, was so in der JVM unterwegs ist, vor allen Dingen mittlerweile auch Skala, hin und wieder mal Java, auch viel Domain Driven Design, viel mit Microservice Architekturen, neuerdings was ganz was anderes, so ein bisschen Cloud Zeugs mit Node.js und JavaScript und wir beweisen gerade, dass man auch mit JavaScript
01:23
Enterprise Software schreiben kann, auch spannend. Genau, ich möchte euch heute ein bisschen auf eine Reise mitnehmen. Stellt euch vor, wir sind ein Team in einem Softwareentwicklungunternehmen und wir haben
01:42
so ein Business Case, wir wollen einen Warenkorps-Service bauen, also Retail Contacts, irgendwie Online-Shops etc. Wir sind in so einer kleinen Microservice Architektur, alles fancy, alles schön. Wir haben hier vorne so einen bestehenden Product Service, da können wir uns anhand von der SKU, das sind Produkt-IDs, Stock Keeping Unit nennt sich das, können
02:02
wir uns Produktinformationen abholen und wir möchten gerne so einen Warenkorps-Service hier bauen, wo Kunden quasi neue Produkte hinzufügen können, Warenkörper anlegen können, Produkte wieder rausnehmen etc. Zusätzlich haben wir hier unten noch so eine kleine Datenbank, wo wir das ganze Ding persistieren können. Unser Team legt los und denkt sich, klar, kleiner Microservice, wir bauen eine ganz
02:24
klassische 3T-Architektur, oben haben wir den Controller, unten in der Mitte ein Service Layer, unten das DB Repository und da stellt sich schon die erste Frage, diese HTTP Client, was ist das eigentlich, ist das mehr so ein Service oder ist das ein Repository, wo baue ich das rein, keine Ahnung, aber das ist alles wunderbar.
02:44
Wir machen Separation of Concerns, wir betreiben De-Coupling, wenn wir mal eine Datenbank austauschen, kein Problem, wir haben eine Abstraktionslayer unten reingezogen, wir betreiben Dependency Inversion, also alles so nach wunderbar, eine gute Software.
03:01
Und dann kam halt die Fachlogik. Die maximale Produktanzahl im Warenkorb soll 50 nicht übersteigen, damit die Leute nicht zu viel einkaufen, warum auch immer. Der maximale Warenkorbwert soll 120 Euro, damit wir nicht so viele Ausstände haben gegebenenfalls und die maximale Anzahl pro Produkt soll 10 sein, damit
03:22
jetzt kein Mensch nicht irgendwie 40 Kästen Bier kauft, die ich dann transportieren muss. Genau, und wir haben noch so ein bisschen Datenvalidierung, diese SKO, die soll halt zwischen 50 und 20 Zeichen lang sein. Alles klar, denken wir, wunderbar. Wir bauen ein kleines Domain-Modell. Haben wir ein Shopping-Card, Shopping-Card hat n Produkte und überlegen
03:44
uns dann, ja, wo baue ich das denn jetzt ein, denken wir, klar, hier in den Service, da steckt die Logik drin, da implementiere ich meine ganzen Business Rules, die Datenvalidierung, alles wunderbar.
04:01
Und dann kommt Bob ins Team und Bob fragt, was bauen wir hier eigentlich? Und das Team antwortet ihn natürlich, wir machen ein Microservice in Spring Boot, aber mit Kotlin, das ist voll fancy neu, cool. Einer antwortet, ja, so ist so ein Warenkorbservice, ah ja, und wir machen hier mit JPA, also Abstraktionslevel High Five, cool.
04:23
Aber Bob fragt, ja, es ist ja alles schön, aber nochmal, was macht denn der Service jetzt eigentlich? Kein Problem, Bob, ich nehme dich mal mit, wir gucken mal den Code ran. Ich habe jetzt alles in Kotlin gemacht, ich hoffe, es ist einigermaßen verständlich, Leute, die so von der Java-Ecke kommen, erster variablen Name, dann der Typ, nicht andersrum, wie es
04:45
irgendwie so moderne fancy Sprachen machen, einfach andersrum machen. Wir gucken uns mal den Controller an. Daten kommen rein und wir machen hier mit so einer Regex eine kleine Datenvalidierung. Wenn die nicht matcht, schmeißen wir ein Badrequest zurück, alles
05:02
wunderbar. Dann kommen wir in den Service Layer, ah, da ist Fleisch dran. Hier haben wir einen Product Service Client, das ist unser HTTP Client, da holen wir uns ein Produkt ab mit der SKO. Und hier holen wir uns dann von unserem Shopping Card, den wir
05:21
irgendwo da oben geholt haben, nehmen wir dann die Produkte Liste und adden dann ein neues Shopping Card Item mit diesem Produkt. Und danach rufen wir das Repository auf und sagen Save. Ah, guck an, Bob findet irgendwelche Nomenklaturen, der findet, ah, was ist das, Shopping Card, Shopping Card Item,
05:42
Product, was ist das denn eigentlich? Das Team sagt, ja, das sind unsere Entity Klassen. Für den OR-Mapper, wir haben hier so one to many Annotations dran, damit unser OR-Mapper da irgendwie was in der Datenbank mangeln kann. Wunderbar, wunderbar.
06:02
Okay, sieht relativ einfach aus. Und dann fragt er auch noch, ich habe mal gerade in eure Dokumentation geguckt und da steht so ein Shopping Card hat Endprodukte. Was ist denn jetzt dieses Shopping Card Item da, das kommt da drin gar nicht vor. Ach so, ja, das brauchen wir aber für den, für den OR-Mapper, weil wir haben hier noch so eine Quantity dran und die können
06:22
wir nicht anders darstellen. Deshalb müssen wir noch so eine Zwischentabelle reinziehen. Und dann fragt Bob, okay, gut, wir haben also Kontrolle. Da ist Zeug drin, Service layer. Ich habe da noch gelesen, von einem Produkt darf man doch nur maximal zehn haben. Wo wird das denn geprüft?
06:42
Anna, sag mal, wo war nochmal dieser Comstrain? Ach, kein Problem hier in der Datenbank. Was haben wir jetzt? Wir haben ein schönes Architektur Modell gebaut.
07:00
Wir haben wirklich schöne lose Schichten. Wir haben Separation of Concerns, aber wir haben unheimlich viel verteilte Fachlogik. Wir haben da oben in Kontrolle haben wir Formatvalidierung. Wir haben im Service layer haben wir Objektkomposition. Das heißt, wir schieben Objekte ineinander und ziehen sie wieder auseinander. Und so allem Überfluss haben wir unten in der Persistenz
07:21
Layer noch eine Überprüfung von In-Varianten. Ein paar Monate vergehen und irgendwann kommt so was dabei raus. Das habe ich mir jetzt nicht ausgedacht. Sowas haben wir tatsächlich mal gebaut. Und wir waren irgendwo an einem Punkt, wo dann unser Injection Frame irgendwann die Geräte gemacht hat, weil es irgendwelche
07:42
zirkulären Abhängigkeiten hatte. Und ich hatte mir mal die Mühe gemacht, mir wirklich mal alles aufzumalen, farblich getrennt, dass es irgendwelche Packages sind, die da rumgeflogen sind. Ja, und da stellt man sich halt irgendwann die Frage, wo wird denn noch mal dieser Warenkorb berechnet? Keine Ahnung. Wir haben was, ein Big Ball of Mud.
08:01
Keiner versteht ihn mehr. Es ist unheimlich schwer zu warten. Wenn man in einem Microservice ist, hat man vielleicht noch so Glück, dass man argumentieren kann, wegschmeißen, neu bauen. Wenn man in einem größeren Umfeld unterwegs ist, wird es dann echt schwer, das Ding wieder zu entflechten, zu ordentlich zu refactorn. Aber Bob hat eine Idee. Ich habe mal was von hexagonaler Architektur gehört.
08:22
Wow, erzähl mal. Das ist ein hexagon. Warum das ein, ja gut, bei der Auflösung jetzt ist es ein gestauchtes hexagon. Das sollte normalerweise ein bisschen, egal. Warum das Ding ein hexagon ist, erzähl ich ganz am Ende.
08:42
Und dieses hexagon unterteilen wir erst einmal in Schichten. Und wir definieren, ganz innen haben wir eine Domäne. In der Mitte haben wir Application. Und ganz außen haben wir Ports. Das ganze Ding nennt sich auch Ports in Adapters Architektur, man findet es auch als Onion Architektur.
09:03
Es gibt verschiedene Namen, verschiedene Ausprägen davon. Aber im Endeffekt, diese Schichten Architektur ist meistens immer gleich. Was machen wir in der Mitte? Wer sich mit dem Domain Driven Designer beschäftigt hat, ein schönes Buch von Eric Evans.
09:21
Kann ich auch nur empfehlen, generell, dass das Ganze, diese ganze Art zu entwickeln. Haben wir in der Mitte eigentlich unsere, ja, Eric Evans nennt es so das Herz der Software, worum ich eigentlich diese Software baue. Eigentlich meine ganze Fachlogik. Hier baue ich meine Modelle.
09:41
Vor allen Dingen habe ich in der Mitte keine Technik, also Technik in dem Sinne, dass ich hier keine Frameworks oder irgendwelche anderen Sachen mache. Wenn es richtig cool läuft, habe ich sogar noch nicht mal irgendwelche Annotations dran. Ich habe wirklich puren Code, der da läuft und Daten Komposition macht, Datenvalidierung macht, etc.
10:00
In der Applikation, hier modelliere ich dann meine Use Cases, also das, was quasi Objektkomposition ausmacht. Das heißt, ich lade mir vielleicht neue Daten rein, muggel die ein bisschen rum, speicher sie wieder rein. Was genau das ist, komme ich gleich noch zu. Und in den Ports, hier habe ich tatsächlich da
10:21
meine technischen Anhängsel. Also sowas, was eigentlich im Zweifel meine Frameworks leisten. Hier habe ich irgendwelche MVC Frameworks, hier habe ich Persistenz Frameworks, etc. Irgendwelche Queuing Publisher, whatever. Dino-Main, gucken wir uns die mal ein bisschen genauer an. Hier habe ich wirklich reine Fachklassen.
10:45
Und was hier ganz wichtig ist, und das macht man relativ gerne falsch, das mache ich auch immer meistens gerne falsch. Man darf hier nicht datenbankzentriert denken. Wenn man so eine Domäne aufzieht, erst mal komplett alles, was man irgendwie an Technik im Hinterkopf hat,
11:03
wie baue ich meine R-Model, wie baue ich mein Jason, das irgendwo persistiert oder mein XML oder was auch immer. Alles vergessen, erst einmal reine Fachklassen bauen. Meine Domäne, so gut es geht, abbilden, verstehen, was die Anforderungen sind und diese eins zu eins in den Code gießen. Am besten sogar mit den Begriffen,
11:21
die irgendwie in der Fachdomäne halt Bezug haben. Ganz einfach, wenn du mit so einem Fachmenschen redest und mit dem über SKU statt über ID redest, dann versteht er dich auch besser. Hopp, genau. Ich habe zum Beispiel hier sowas jetzt als Beispiel simple Fachtypen. Diese Fachtypen haben aber eine
11:41
syntaktische und semantische Validierung drin. Ich zeige gleich mal ein Beispiel, wie man sowas machen kann. Vorteil ist, wenn ich so einen SKU-Typ habe, da kann ich sicher sein, dass da drin auch ein Value ist, der eine SKU repräsentiert. Das Ding ist dann validiert. Das Ding ist irgendwie semantisch geprüft, etc. Dieses Objekt darf nicht generiert werden können,
12:01
wenn ich irgendwie ein invalides Datum drinne habe. Darüber hinaus habe ich zusammengesetzte Werte, sowas wie Product. Und ganz wichtig, ich habe einen einzelnen Typen, der man sagt in diesem Kontext, der mein Aggregate oder mein Aggregate-Root darstellt.
12:26
Der baut quasi mit diesen Unterobjekten ein Objekt-Graf auf, hat vielleicht noch irgendwelche Überprüfungsinvarianten als benahmte Elemente mit dabei. Was aber wichtig ist, nur dieses Teil definiert eine Schnittstelle nach außen.
12:41
Das heißt, wir haben hier unsere interne Domäne und nur dieses Teil definiert Schnittstellen in die Außenwelt. Keine anderen Elemente sonst. Warum mache ich das so? Ich habe zum Beispiel so eine Methode
13:01
putProductInto, die bekommt ein Produkt. Ich gebe das in die Domäne rein und meine Domäne kann nun Folgendes machen. Es kann prüfen, ob dieses Produkt, das ich hinzufüge, meine innere Fachlogik verletzt oder nicht. Das kann diese ganzen Pre-Conditions, Post-Conditions, Invarianten alles wunderschön abprüfen.
13:21
Wenn es diese Invarianten verletzt, schmeißt es zum Beispiel einen Fehler. Wichtig ist aber, wenn ich den Fehler geschmissen habe, dass meine Domäne als Zustand genau denselben hat, den es vor der Operation hatte. Das heißt, ich mache hier oder kann hier, indem ich wohl definierte Interfaces
13:40
habe, die nach außen gehen, kann ich tatsächlich valide und überprüfte Zustandsübergänge meiner Domäne haben. Wichtig dabei ist noch, wenn ich sowas habe wie, gib mir mal die Quantity von einem Produkt und ich gebe so
14:01
ein Objekt hier raus. Das ist natürlich dann wichtig, wenn ich solch einen Konstrukt mache, dass ich niemals eine Referenz rausgebe, wo mich dann wieder den inneren State verletzen könnte. Das ist hier an der Stelle ganz wichtig. Die Domäne muss immer einen validen Zustand haben, sonst macht dieses ganze Architekturbild keinen Sinn.
14:21
Wie mache ich sowas? Das ist zum Beispiel ein ein bisschen Kotlin-Code. In Kotlin gibt es sogenannte Data Classes. Wenn man aus der Java-Welt kommt, kennt man diese Pogels mit diesen Gettern und Settern, die sonst nichts tun. Habe ich in Kotlin einfach komplett geschenkt. Ich habe hier so einen Inlet-Block. Das ist eine Art Konstruktor.
14:40
Und hier kann ich tatsächlich prüfen. Ich bekomme einen String rein, matche den auf eine Regex und mein komplettes SKO-Objekt erzeugt sich jetzt dann, wenn ich einen gültigen Wert habe. Genauso ein Produkt, das benutzt hier nicht irgendwelche Strings, sondern benutzt dann tatsächlich diese simplen Fachtypen.
15:00
Vorteil hier in diesem Produkt muss ich nichts mehr tun. Das ist eine reine Komposition. Ich habe einen SKO-Typ und wenn ich einen SKO-Typ habe oder ein Objekt eines SKO-Typs, kann ich mir an dieser Stelle sicher sein, dass es auch wirklich eine SKO ist. Die ist validiert, die ist semantisch überprüft. Alles wunderbar. Genauso mit dem Price. Wenn ich definiere, dass ein Price niemals negativ sein darf,
15:21
dann kann ich hier von ausgehen, dass dieser Price niemals negativ ist, weil sonst würde dieses Objekt nicht existieren. Das heißt, hier in so einem Produkt muss ich nichts mehr weiter machen als ein bisschen Objektkomposition. Das ist in Kotlin ein Zeiler. Praktisch hier auch noch, wenn ich so ein Objekt erzeuge, gerade in Kotlin ist das ziemlich cool, weil er keinen New-Operator hat.
15:40
Ich kann hier relativ sprechend mir ein neues Objekt erzeugen. Das kann man im Code wie einen Satz lesen. Genau, so ein Accurate Route, das hat dann solche Methoden wie putProductInto, bekommt ein Product, bekommt eine Quantity. Auch hier kann ich mir wieder sicher sein. Diese Objekte,
16:00
die ich erzeugt habe, sind semantisch sicher. Hier sind einfach da. Am besten halt auch noch immutable gebaut, damit ich sie ja nicht mehr verändern kann, sondern höchstens kopieren. Und hier beginnt dann eigentlich die eigentliche Fachlogik. Hier habe ich meine Invarianten, da habe ich vielleicht keine Helferklassen, die einzelne Präconditions abprüfen,
16:22
die vielleicht mir auch noch irgendwelche anderen Daten heranziehen und dafür halt validieren. Code technisch sieht das ganze Ding aus. Das ist jetzt ein Beispiel von mir. Das kann man auch ein bisschen anders gestalten. Ich mache es gerne so, dass ich mir hier so ein Domain Package habe und da habe ich dann einfach
16:41
alle Dateien drin, die zu meinen Domänen gehören. Und ich habe dann einen Teil, wie hier so ein Shopping Card. Nur das hat ein Interface nach außen außerhalb dieses Packages, sodass ich auch hier nur darauf zugreifen kann. Kommen wir mal zur Application. Wenn wir jetzt gesagt haben, dass in der Domäne
17:00
mal gucken, in der Domäne die reine Fachlogik drin ist, das heißt, hier passieren meine Präconditions, Postconditions, Invarianten etc. Was macht da noch die Application? Die Application definiert Use Cases. Ein Use Case kann sein, dass ich mir
17:22
mein Domain Objekt ziehe, Daten von außen bekomme, mir diese kleinen Fachklassen erzeuge, die dir meine Domäne gebe, irgendwas machen lasse und das ganze Ding vielleicht wieder irgendwo wegspeichere. Kann aber auch sein, dass ich ein, zwei oder drei Fachmethoden der Domäne aufrufe.
17:42
Das geht auch. Hier haben wir jetzt auch wieder unsere Services. Das heißt das oder zum Beispiel so ein Command oder Report Service, wie auch immer man das jetzt nennen würde. Das sind wirklich dann nur noch relativ kleine
18:01
Codeschnipsel, die eigentlich nur noch ein bisschen Komposition betreiben. Die machen nicht mehr viel. Die machen keine Fachvalidierung. Das steckt alles in der Domäne drin. Ja, wichtig, keine Fachlogik. Nach außen.
18:21
Definiere ich dann auf der einen Seite Use Case Interfaces und auf der anderen Seite Infrastruktur Interfaces. Komme ich gleich noch zu, wo dann der kleine Unterschied ist. Generell, hier kommen wir wieder. Ich hatte eben mal eingangs erläutert. Das ganze Ding nennt sich auch
18:41
Ports in Adapters Architektur. Das sind Ports, die quasi aus der Applikation die Applikation bereitstellt, aber auch von der Applikation benutzt wird. Wie sieht das Ganze dann so ein bisschen auf Code Ebene aus,
19:02
beziehungsweise hier so ein klassen Diagramm? Ich habe hier rechts mein Domain Objekt. Da rufe ich meine Domain Methoden auf. Ich habe hier zum Beispiel einen App Shopping Card Service, der definiert ein Interface. Das ist mein Port nach außen, benutzt aber auch ein Interface,
19:20
zum Beispiel hier ein Shopping Card Repository Port. Das sind die Ports, die ich benutzen möchte. Wie sieht so was aus? Ich habe zum Beispiel einen Port nach außen. Das heißt, hier habe ich meinen Repository Port von dem.
19:43
Aus diesem Repository lade ich mir mein Domain Objekt. Ich bekomme ein Shopping Card Objekt mit dem kompletten Objekt, kraft darunter. Ich bekomme hier eine Shopping Card UUID zum holen, vielleicht noch ein paar andere Sachen wie hier die Produktinformation.
20:02
Ich lade mir das aus der Datenbank, gebe meinem Domain Objekt das Objekt, das ich vielleicht hinzufügen will, in dem Fall das Produkt. Die Domäne sagt, klappt oder klappt nicht. Wenn es nicht klappt, schmeiße ich den Fehler weiter. Wenn es klappt, hat die Domäne ihren Zustand verändert und ich speichere diesen neuen Zustand
20:21
über das Repository wieder in meine Persistenz Schicht. Die Ports, genau andersrum, Adapter. Ports hat man ja schon. Wir haben eine Application Schicht
20:40
und darüber haben wir eine Port Schicht beziehungsweise die Port Schicht an seher Stelle ist ein bisschen von der Nomenklatur ein bisschen falsch, weil im Endeffekt die Ports werden von der Application definiert. Meine Port Schicht definiert aber nur die kleinen Adapter. Was sind Adapter? Adapter sind nun diese kleinen technischen Anhängsel, die meine Use Case Interfaces
21:02
quasi bedienen. Man unterscheidet hier. Man sieht, ich habe das Bild mal so ein bisschen zweigeteilt auf der einen Seite zwischen sogenannten Driver Adapters und auf der anderen Seite zu Driven Adapters. Wo ist hier der Unterschied?
21:21
Man sieht schon so ein bisschen die Pfeile, die einen gehen raus, die anderen gehen rein, die anderen gehen raus. Das hat nichts mit dem Datenfluss zu tun, sondern mit der Richtung des Aufrufers. Mein Driver Adapter mit dem wird meine Applikation von außen gesteuert. Mit dem Driven Adapter steuert meine Applikation
21:41
andere Applikation nach außen. Das ist so ein bisschen quasi die Command Strecke, die dann läuft. Was sind das zum Beispiel? Ich habe hier ein Port nach außen und ich habe hier einen Adapter. Das kann meine UI sein. Hier habe ich meine Template Engine. Hier habe ich mein UI zusammengedengelt.
22:01
Da unten habe ich vielleicht einen Rest Controller hängen, der bedient mein Port, meine Applikation. Ich habe nach hier außen habe ich zum Beispiel meinen HTTP Client. Wie funktioniert das jetzt? Meine Applikation definiert sich ein Interface. Ich möchte gerne ein Produkt holen anhand einer SKU.
22:21
Dieser Rest Client implementiert das Interface und sagt alles klar, mache ich dir. Wichtig dabei ist jetzt aber bis zu dieser Grenze hier rede ich nur mit meinen Fachobjekten. Das heißt, auch meine Applikation bedient dieses Interface nur. Gib mir mal bitte ein Produkt anhand dieses SKU Typs.
22:42
Dieser Adapter übersetzt dann diesen SKU Typ wieder in irgendeinen String, den er über die HTTP Leitung bekommt, bekommt vielleicht von meinem Produkt irgendeinen JSON, hat dann die Aufgabe, das ganze Ding aber in einen Produkt Typ umzuwandeln, das Applikation wiederzugeben und die Applikation sagt an der Domäne Hier hast du mal
23:00
das gefundene Produkt. Füge es bitte einem Warenkorb hinzu. Mach was damit, überprüfe, sag mir, ob es klappt oder nicht. Hier unten haben wir so einen kleinen Sonderfall. Das ist halt in dem Fall hier Richtung SQL meine Persistenz Schicht. Das sind dann diese sogenannten Repositories.
23:20
Gerade so im Domain Driven Design haben die so ein bisschen eine Sonderrolle. Auch hier definiere ich mir ein Interface nach außen, wo meine Applikation sagt, ich habe hier eine Shopping Card UUID als Typ. Gib mir bitte meine Shopping Card Domäne oder ich habe meine Shopping Card Domäne angewiesen, etwas ihren State zu ändern. Das hat funktioniert.
23:41
Bitte speicher diese Shopping Card Domäne jetzt bitte zurück in meine Persistenz. Wie das ganze Ding persistiert wird, das muss dieser Adapter hier entscheiden. Das ist nicht Aufgabe der Domäne. Das ist nicht Aufgabe der Applikation. Das ist allein Aufgabe dieses Adapters.
24:01
Genau, das könnte so technisch aussehen. HTTP client, OR Mapper, REST Controller. Auch hier. Wie sieht das Ganze wieder technisch aus? Ich habe hier wieder meine Domäne rechts. Ich habe in der Mitte meinen Service Layer in blau.
24:20
Mein Service Layer definiert Interfaces nach außen. Also meine meine Driven Adapter, meine Driver Adapter, Entschuldigung. Die werden zum Beispiel von einem Shopping Card Control implementiert. Jetzt habe ich da unten drunter so ein Spring Boot, MVC Framework. Das kümmert sich um die ganze HTTP Strecke,
24:42
das ganze Routing etc. Ruft dann nur noch das Interface auf. Mein Service Layer definiert aber auch ein ein Driver Interface oder ein Driver Port. Das ist hier zum Beispiel ein Repository. Hier habe ich meinen JPA Repository, das dann meine Domäne irgendwie aus der Datenbank
25:01
laden kann, aber auch zurückschreiben kann. Wenn wir uns das ganze Ding mal so angucken, das hatten wir doch schon mal. Haben wir einen Controller da links, haben wir da oben, haben wir einen Service in der Mitte,
25:21
haben wir auch in der Mitte. Wir haben da unten ein Repository, haben wir auch. Gut, den HTTP Client habe ich jetzt nicht aufgeschrieben und wir haben sogar hier so ein Shopping Card. Das haben wir da auch. Wo ist der Unterschied? Im Endeffekt, auf Code Ebene gibt es keinen großen, außer dass ich meine Domänenlogik da reingezogen habe.
25:42
Aber in unseren Köpfen da passiert Folgendes, denn ich baue meine relativ eindimensionale Architektur top down in eine zweidimensionale Architektur out in oder in out. Indem ich einfach meine komplette Denkweise meiner Applikation
26:00
auf so eine Schichten Architektur einfach ummünze, obwohl das vielleicht code technisch nicht ganz der große Unterschied dabei ist, habe ich aber ein viel, viel einfacheres Denken, wie meine Applikation ausbauen oder aufgebaut werden kann. Wenn jetzt mein Teamleiter Product Owner mit einer neuen Anforderung um die Ecke kommt.
26:21
Hör mal, wir haben hier noch eine zusätzliche Validierung. Wo baue ich dir denn ein? Keine Ahnung. Domäne. Wir haben noch ein Use Case, dass wir irgendwie wir brauchen noch ein Reporting, wie die Durchschnitt, keine Ahnung, wie viele Produkte gerade in einem Warenkorb da sind.
26:41
Kein Problem. Baue ich dir einen neuen Use Case in die Applikation rein. Vielleicht noch eine neue Methode hier in die Domäne, die genau diese Informationen liefert. Ich habe etwas. Mein Problem. Ein anderer Service hat irgendeine Message Queue, wo mit mir Informationen gibt, die ich benötige.
27:02
Wo baue ich diese Message Queue ein? Kein Problem. Auf diese Seite. Driver Adapter oder Sorry. Driver Adapter Message kommt rein, steuert meine Software. Ich soll irgendeine Message Queue bedienen. Die geänderte Information
27:21
oder Business Events meiner Applikation irgendwie der Welt oder meiner kompletten Microservice Welt irgendwie zu bereitstellt. Kein Problem. Baue ich hier einfach hier ein Driver Port rein. Wenn hier irgendwas passiert, geht es in der Message Queue raus. Ich muss mir hier keine Gedanken mehr machen, wo ich irgendwelche technischen Anhängsel einbaue. Ich habe neben den Rest
27:40
jetzt muss ich noch irgendwie im Legacy System irgendwie eine Soption Stelle bereitstellen, weil das nur Soap kann. Kein Problem. Baue ich noch einen Adapter daneben, der genau den selben Port bedient, aber einfach hier an der Stelle Soap macht. Klaus kommt ins Team
28:01
und er fragt, was bauen wir denn hier? Und das Team sagt, kein Problem. Hier ist der Domain Kern. Hier hast du die. Das ist noch ein Punkt. Sehr valide. Klaus hat mich drauf gebracht. Testing. Brauche ich Unit Test
28:20
oder muss ich meine Fachtests machen? Kein Problem. Ich nehme diese Schicht und diese Schicht einfach weg und ich kann meine Domäne komplett einständig testen. Ich muss hier nichts mocken. Ich habe keine Frameworks, die ich irgendwie ersetzen muss. Ich habe komplett reine Fachklassen. Ich kann meine Invarianten eins zu eins testen. Das heißt, ich habe hier die meisten Tests. Die Application Schicht,
28:41
wenn ich irgendwie eine Art Component Test habe. Ich möchte jetzt kein HTTP haben. Ich möchte meine Datenbank irgendwie wegmocken. Das heißt, meine technischen Anhängsel brauche ich nicht. Nehme ich allein die Ports weg. Ich kann die Applikation mit den Use Case Interfaces wunderbar testen. Hier bekommst du irgendwie eine Shopping Card UUID rein oder ein Produkt und guck mal, was passiert.
29:02
Ich kann hier unten diesen Port hier unten auch wegmocken. Ich implementiere hier einfach einen Test Adapter und sage, okay, für diese Shopping Card UUID bekommst du irgendein ein Mockobjekt. Und auch für voll integrative Systeme oder Systemtests kein Problem. Habe ich einfach den kompletten Service mit allen drei Schichten
29:21
kann ich wunderbar testen. Das heißt, ich habe irgendwelche Umsysteme, die vielleicht dann auch technisch gemockt sind, die aber die Schnittstelle irgendwie bedienen. Kann ich auch machen. Das heißt, ich habe hier das, was wir so als Test Pyramide kennen, also Unit Test, Component Test, Integration Test. Dann kann ich eins zu eins auf diese drei Schichten abbilden.
29:41
Genau. Was bauen wir hier? Kein Problem. Domain Kern. Hier sind die Tests. Da findest du alles, was wir eigentlich machen. Und Klaus denkt, wow, das ist echt sauber und verständlich. Umsysteme findest du unter Ports. Da findest du alle
30:00
Informationen auch für Serialisierung, Deserialisierung wunderbar. Und so weiter. Wie geht es weiter? Die hexagonale Architektur hat hier noch so ein paar Sachen, die man da noch einbauen kann. Da gibt es so. Das ist aber schon so ein bisschen advanced. Das kann man gucken. Ein Teil ist zum Beispiel ich habe solche Sachen wie.
30:22
Ich habe ein Shopping Card Service, aber ich soll bitte einen Report machen. Die durchschnittliche Anzahl Milch über alle Shopping Cards. Jetzt fange ich mit der Architektur ja nicht an und lade mir erst mal alle Shopping Cards aus dem Repository raus, iteriere dann über alle,
30:41
ziehe mir die Milch raus und breche mir dann irgendwas. Hier gibt es dann so Sachen wie zum Beispiel man kann einen Component reinziehen, wo man dann sagt, OK, für diesen Fall über alle hat das zwar immer noch was mit meiner Domäne zu tun, aber nicht mehr mit einem einzelnen Objekt, sondern mit einem ganzheitlichen darüber.
31:00
Also kann ich so eine einzelne Component reinziehen, die sich dann über alle drei Schichten ausbreitet, auch alle drei Schichten sauber trennt. Das heißt, sie bringt ihre eigene Subdomäne so ein bisschen mit. Das heißt, sie basiert zwar auf Shopping Card, arbeitet in der Domäne jetzt aber eher mit Listen von Shopping Cards oder sowas in die Richtung oder oder Listen von Produkten
31:21
oder Product Items. Das hat immer noch was mit der Domäne zu tun, steht aber immer so ein bisschen daneben, definiert dann aber saubere Ports in die Application Schicht. Was kann man auch machen? Auch ganz spannendes Thema. Wenn ich ein etwas größeres System habe, sind das interne Message Busse.
31:41
Das heißt, meine Domäne, wenn die irgendein State geändert hat, sagt die nicht einfach der Application Hallo, hier ist was passiert. Nein, sie postuliert vielleicht auch auf einem internen Message Bus, ein Business Event, dass es passiert. Und Adapter, die sich dafür interessieren, die dann irgendwas anderes machen, konsumieren diese Events und können das Ganze machen.
32:01
Muss nicht asynchron sein, kann auch synchron sein. Klappt auch wunderbar. Mit dem System kann man zum Beispiel tatsächlich auch mit dieser Hexagonal Architektur sehr, sehr schnell so ein CQRS System machen, so ein Command, Query, Responsibility Dingens. Generell aber, wann sollte man
32:20
das ganze Ding einsetzen? Man hat eine nicht triviale Fachlogik. Das ist meistens der Fall. Außer ich mache vielleicht wirklich einen generischen Proxy, der irgendwas von A nach B schaufelt und es ist ihm egal, was es ist. Generell eine Domäne, die Invarianten hat, die ich abprüfen muss,
32:40
die irgendwelche, die nicht immer einen gültigen State hat. Ich habe viele Umsysteme und APIs. Da macht mir einfach dieses Bild das Leben einfacher, von der denke ich, ich weiß, wo ich es einfach positionieren kann. Ich habe verschiedene fachliche Sichten. Das heißt, mein Kunde möchte Produkte reinladen,
33:01
aber irgendein, weiß ich nicht, Business Intelligence Menschen interessiert sich über irgendwelche Statistiken über das System. Kann ich auch machen. Man setzt sich es nicht an, gerade schon gesagt, wenn ich einfach kein Fachmodell habe. Aktuelles Beispiel bei mir, das ist einfach ein System, da kommt ein Jason rein,
33:20
wird ein bisschen gemagelt, kommt hinten Jason wieder raus. Da habe ich keine fachlichen Invarianten, deshalb setze ich das da nicht ein. Brauche ich nicht, weil das ist dann einfach mit Kanonen auf Spatzen geschossen. Wenn ich so was habe wie so ein simples Krutt, brauche ich das auch nicht. Hier aber Vorsicht, also aus meiner eigenen Erfahrung, gerade wenn ich ein Krutt mit dem Krutzsystem anfange,
33:41
die Dinger bleiben, da ist es nicht Krutt. Die haben dann irgendwann kommen nämlich diese fiesen Dinger da rein und dann wird es haarig. Nachteile oder Vor- und Nachteile. Großer Vorteil, meine Domain Komplexität wird wesentlich handhabbar, allein weil ich das Ding zentriere,
34:00
mich darauf konzentrieren kann. Ich kann gute Unit Tests schreiben und bin damit safe. Einführungen von Umsystemen sind einfacher. Ich brauche mir da keine großen Gedanken machen. Ich habe irgendwelche Use Case Ports. Für die Dinger brauche ich einfach neue Adapter. Kein Problem. Neue Kollegen sehen sich den Kern und wissen, was passiert.
34:21
Diesmal steht die Wahrheit wirklich im Code. Nachteile sind Overhead. Den habe ich definitiv. Warum? Die Domäne ist kein Overhead, weil die Domäne wird im Zweifel die Komplexität oder die technische Komplexität abbilden, die auch eine fachliche Komplexität hat.
34:41
Eine fachliche Komplexität bekomme ich meistens eher weniger wenig minimiert. Aber viele, viele Frameworks und das ist leider der Fall, machen einem das Leben schwer. Beispiel so ein bisschen aus der Java Welt. Ich möchte das ganze Ding bitte mit oder möchte das Ganze mit dem OR Mapper persistieren. Der OR Mapper möchte jetzt aber
35:01
auf die interne Struktur meiner Domäne zugreifen, damit er weiß, was er persistieren soll. Zu allem im Überfluss, wenn er es deserialisieren möchte, möchte er gerne Default Konstrukte haben und so weiter. Die möchte ich aber nicht in der Domäne haben, weil die mir den internen State versauen. Das ist dann immer so eine Sache. Da muss man wirklich gucken,
35:21
wie man es machen kann, wie es geht. Ich habe steht gleich noch ein Link drauf ein Beispiel gemacht, wo ich dann wirklich mein Domain Modell erst mal in ein OR Modell umwandeln und das persistiere. Ob das jetzt so sinnvoll ist, weiß ich selber auch nicht. Es fühlt sich schlecht an. Ob ich mir dann mein Domain Objekt direkt durch meinen Adapter
35:42
direkt per Hand in SQL umwandeln und das persistiere für kleine Domains, vielleicht handhabbarer. Mal gucken. Weiß ich selber noch nicht. Also den Heiligen Gral habe ich da auch noch nicht so gefunden. Genauso wie auf der anderen Seite. Wenn ich so eine Restion Stelle habe, wobei man da ja auch mittlerweile
36:01
viel mehr wieder mit Data Transfer Objects baut. Das heißt, ich wandle mein Domain Objekt erst mal in ein DTO um. Gebe das als Jason Serialisierung raus, weil ich vielleicht auch noch in meiner Hate Ors Rest Huyui Schnittstelle dann noch irgendwelche Links Bäume aufbauen möchte,
36:21
damit das Ganze super automatisiert aufgebaut wird. Diese Links Objekte möchte ich natürlich nicht in meiner Domäne haben, genauso wie ich in meinem Jason vielleicht interne Daten aus meiner Domäne nicht habe. Deshalb muss ich da so ein bisschen Modellumwandlung machen. Ja, eine Sache, die habe ich noch offen. Warum heißt das ganze Ding
36:40
Hexagon oder hexagonale Architektur? Alistair Cockburn, der das ganze Ding damals mal postuliert hat, Datum weiß ich jetzt nicht mehr, war irgendwann in den 90ern, glaube ich. Der wollte das ganze Ding gerne als Ports in adapters Architektur halt rausgeben. Der interne Arbeitstitel war bei hexagonale Architektur. Warum ein Hexagon? Weil Alistair Cockburn
37:00
in seinem ersten Beispiel zufällig sechs Ports hatte. Also das ist tatsächlich sucht man nach hexagonale Architektur, findet man mehr Artikel als über Ports in adapters Artikel, über Ports in adapters, wobei Ports in adapters der eigentliche Namen dieser Architektur sein sollte.
37:22
Hat sich nun nie durchgesetzt, weil Hexagon irgendwie cooler klingt. Also Foto noch? Oder? Sorry. Generell so ein bisschen Literatur dafür. GDS ist ein ganz cooler Blogartikel, den kann ich
37:41
tatsächlich nur empfehlen, beziehungsweise der zweite, den kann ich echt empfehlen. Der bringt das Ganze so ein bisschen auch ein bisschen die Theorie dahinter noch mal ein bisschen raus. Ist echt cool gemacht. Das Ding in der Hoffnung, dass er noch funktioniert, ist Web Archive, ist der Originalartikel von Alistair Cockburn. Der existiert leider
38:00
nicht mehr so. Was ich tatsächlich empfehlen kann, das ist jetzt Domain Driven Implementing Domain Driven Design von Warren Werner, nicht weil ich mit dem Menschen irgendwie einen Vertrag habe, nein, weil ich das bookgeil finde, weil er da tatsächlich dieses ganze Thema Domain Driven Design, wie baue ich meine Fachdomäne auf, sehr, sehr gut erklärt und auch erklärt,
38:20
wie ich dieses System auch in die verschiedensten Architekturen reinbekomme, unter anderem auch diese Three Tire Architektur vom Anfang erklärt er auch darin, wie das da geht. Generell, auch wenn ich jetzt Schmidt heiße, der Link bleibt idantik, das ist halt unveränderlich. Das ist ein Beispiel hexagonalen Service,
38:40
den ich gebaut habe, quasi die ganzen Code Beispiel, die ich gerade gezeigt habe, findet man da, das Ding funktioniert und läuft, ist getestet. Und ich habe mal die anderen Code Beispiele von so, wie es Bob irgendwie doof fand, habe ich auch mal gebastelt, ist tatsächlich, also es macht Spaß, aber es ist auch echt eine Herausforderung, einfach mal ein Code Scheiße zu schreiben.
39:01
Das ist also willentlich und willentlich passiert ist ja öfters, aber willentlich ja, dann bleibt mir noch zu sagen, vielen Dank. Dreiviertel Stunde.
39:21
Wunderbar. Fragen, Antworten. Ich glaube, ich habe hier ein Mikro, dass ich dann rumreichen kann. Ich hoffe, das ist an.
39:54
Okay, jetzt besser.
40:09
Gut, also meine Frage war nach dem wunderschönen Constraint, wo halt eben die Anzahl der maximal erlaubten Items in der Datenbank abgefragt wurde.
40:22
Das ist ja ein Designfehler, der, egal welches Konzept man dahinter steckt, nicht passieren sollte. Also ist das jetzt eine Disziplinfrage oder wo ist der Constraint gelandet? Der Constraint bringt mich gerade mal auf den Punkt. Das war der von ganz am Anfang der
40:42
bo bo bo bo bo. Wo ist der PO da? Sorry, ich habe nicht richtig mitbekommen. Welchen meintest du jetzt? Den, der in der Datenbank gelandet ist, wo dann halt eben das als Constraint in der Datenbank gelöst wurde.
41:02
Dass das nicht passieren soll? Ja, das soll nicht passieren. Und das liegt ja, denke ich mal, jetzt nicht am hexagonalen Design an sich, sondern grundsätzlich dann an der Disziplin im Design.
41:21
Ja, natürlich. Also das ist jetzt natürlich ein negativ Beispiel, das ein bisschen populistisch gestrickt ist. Das habe ich schon gesehen. Generell sage ich, wenn man in der Datenbank so einen Constraint hat, so als Last Line of Defense,
41:42
kein Problem. Aber man soll das natürlich schon vorher mal abgeprüft haben, damit man einfach irgendwo eine fachliche Validierung hat. Natürlich. Ja, ich habe auch schon mal so was gesehen. Dann diskutiert man drüber, da macht man es anders. Dann hast du vielleicht einen etwas juniorigeren Entwickler dabei. Ihr lernt was dabei und dann ist das alles wieder fein.
42:03
Sollte man nicht tun. Passiert normalerweise auch in diesen Dinger nicht. Aus der Praxis, das hatten wir tatsächlich, dass die Datenbank einen Bug gefixt hat, weil der Bug noch nicht gefunden war. Ja. Hat die Datenbank
42:21
selber noch mal geprüft. Stimmt denn das, was ich bekommen habe? Wenn nicht, fixe ich das, bis der Bug gefunden ist. Man kann jetzt natürlich philosophieren, ich muss mein System ganzheitlich denken. Okay.
42:46
Dann ja. Vielleicht mögt ihr das einfach rumreichen oder? So vielleicht wenn in der Microservice Architektur dann viele Services zusammenkommen
43:02
und beim E-Commerce Fall jetzt so, ich glaube der Worst Case vielleicht irgendwie eine Gutscheine Engine, die halt irgendwie 3000 Regeln abbilden können muss von maximalen Produktpreis und irgendwie Mitternachtsgutscheine mit einer Shopping und Geburtstagsgutscheine. Die Modelle aus anderen Services wie also,
43:21
so wie ich das ja verstanden habe, würde ja jeder Service eine hexagonale Architektur abbilden und die durch die Ports verbunden werden, wenn man dann mehrere Services hat. Wie werden da so die Kommunikationen, die Modelle von anderen Services könnte man die einbinden? Also generell würde ich das nicht so spielen, dass jeder Service in der Architektur
43:40
hexagonal sein muss. Das ist ja auch nur ein Werkzeug in meinem Werkzeugkasten, wie ich Software bauen kann. Das ist ja auch nicht der Weisheit letzter Schluss. Generell, wenn ich gerade so was habe wie Gutscheinberechnung. Gut, das ist jetzt eine Fachfrage. Muss ich das tatsächlich schon in meinem gerade aktuell Mutable Shopping Card haben?
44:00
Ist das mehr so eine Sache für den Checkout? Wenn ich hinterher tatsächlich die eigentliche Bestellung abschicke, werden dann Gutscheine verrechtet. Das muss man auch noch ein bisschen gucken. Generell, wenn ich so eine Architektur habe. Ich habe jetzt so ein Gutschein Service, der sich irgendwie Gutscheine verwaltet. Die möchte ich ja vielleicht an einem gearteten Checkout Service weitergeben,
44:20
der die dann gebrauchen kann. Da würde ich dann wahrscheinlich über eine Messagebus oder so was arbeiten und die Daten dann einfach duplizieren. Das heißt, der Gutschein Service hat die Datenrohrheit. Da steckt die Wahrheit über Gutscheine drin. Der Rest wird dann in den Checkout gegeben. Im Endeffekt, das ist eine Fachentscheidung, ob das jetzt synchron sein muss,
44:41
alsynchron, ob ich da jetzt so ein bisschen mit eventual Consistency arbeiten kann, weil im Endeffekt kann ich mir auch vorstellen, ich definiere mir für nächste Wochen Gutschein, wenn das Ding jetzt am Montag 250 Millisekunden später beim Checkout Service ankommt und die ersten 10 Minuten nicht davon profitieren, die wissen ja nichts davon. Ist vielleicht auch egal.
45:01
Also ich würde es dann im ersten Niveau für dich empfehlen, asynchron zu arbeiten, einfach so ein Kafka-Bus oder so was kann man da eigentlich ziemlich schön verwenden für einfach einen asynchronen Bus dazu unterzuhaben. Der eine Microservice bekommt halt einen Message Producer rein. Das heißt, ich habe dann so einen Driver-Port, der nach außen geht. Wenn ich irgendwas
45:21
einen neuen Gutschein bekomme, postuliere ich einen Message nach außen. Hier Welt, kümmer dich drum. Und mein Checkout Service würde dann kommt jetzt vielleicht ein neuer Gutschein. Ja, kommt rein. Ich muss dann vielleicht das ganze Ding irgendwie als Datenbasis vorhalten oder gerade aktuelle Checkouts irgendwie umrechnen. Aber das ist eine Fachfrage, wie ich das dann machen muss und kann.
45:45
Die Frage ist auch, inwieweit du deine Domäne überhaupt in Microservices abbilden kannst, weil wenn du ein Domänenmodell hast, was sowieso sehr, sehr verwoben ist, dann ist es sehr, sehr schwierig,
46:01
das überhaupt sinnvoll in Services oder in kleinere Einheiten zu zerschneiden. Das funktioniert. Aber da hat man je nach Größe des Unternehmens hat man halt nicht irgendwie eine Abteilung, die nur für Gutscheine zuständig ist, sondern die machen dann Gutscheine
46:22
und gleichzeitig noch den Checkout-Prozess oder sowas. Also das ist meistens sowieso meiner Erfahrung nach sehr, sehr stark auch beieinander, dass man gar nicht so klein schneiden kann, dass man meiner Ansicht nach von Microservices spricht.
46:40
Dazu vielleicht ganz interessant, wenn man sich so ein bisschen aus dem Domain- driven Design kommt, da gibt es halt dieses Konzept des bounded Context. Technisch gibt es dann mittlerweile so self-contained systems, die dann diese ganze Microservice-Thema ein bisschen relativieren. Innerhalb dieses self-contained systems ist im Endeffekt eine fachliche vertikale Säule,
47:02
die ich habe. Da drin kann ich so wild Microservisieren, wie ich will. Das geht dann. Nach außen habe ich dann irgendwie, gut, das ist dann quasi Business-Schnittstellen, die ich dann in andere vertikalen Säulen habe. Die Krux an der ganzen Sache ist, dass das sagst du ja schon, viele Domänen sind halt auch einfach sehr stark verwoben.
47:21
Da kann man mit Sicherheit ordentliche Schnitte machen. Man muss sie nur finden. Und das ist das Schwierige an der ganzen Sache. Wenn man einmal den Schnitt hat und einmal die Domänen definiert hat, das ganze Ding in so eine Architektur gießen. Das ist Pille-Palle. Aber tatsächlich dann diese einerseits wirklich diese diese Säulen rauszufinden, diese diese Domänen rauszufinden, das ist eigentlich das Schwierige daran.
47:45
Unter Umständen hat man dann ja auch noch ein übergeordnetes Domänen-Modell, was die kleineren Domänen-Modelle wiederum koordiniert. Und dann hat man den Big Ball of Mud auf eine andere Ebene gezogen.
48:01
Generell ist das ja so auch der ganze Thema Microservices. Ich kann halt auch ein Big Ball of Mud mit Microservices machen. Ob ich da jetzt wie Monolithen die Methoden direkt aufrufe oder das ganze Ding HTTP nenne. Habe ich auch schon gesehen, wo du dann innerhalb der Microservice-Architektur
48:21
wiederum zirkuläre Abhängigkeiten hast. Geile Sache.
48:41
Okay. Dann würde ich sagen noch einmal vielen, vielen Dank, dass ihr alle da wart. Ich hoffe, ihr konntet mitnehmen.
Recommendations
Series of 9 media