Extraktion von Microservices aus einem Monolithen
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 |
| |
Title of Series | ||
Number of Parts | 95 | |
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/32291 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
| |
Keywords |
FrOSCon 201756 / 95
4
8
9
15
20
22
23
24
25
27
29
32
36
37
38
39
40
45
46
47
48
49
50
51
53
54
59
63
64
65
74
75
76
79
83
84
86
87
88
89
91
92
93
94
95
00:00
HTTPWeb applicationFactory (trading post)WEBLanding pageSoftwareXMLUMLComputer animationLecture/Conference
00:49
Web applicationWeb applicationLöschen <Datenverarbeitung>Plane (geometry)SoftwareWeb browserSymfony <Framework, Informatik>FRAMEWORK <Programm>Service (economics)Atomic nucleusStack (abstract data type)Web-AnwendungWindows Registry
04:54
Computer animation
05:41
Lecture/ConferenceComputer animation
06:24
LoginCodeLoginComputer fileZusammenhang <Mathematik>Moment (mathematics)Unit testingSoftware testingBackupMusical ensembleService (economics)Computer animation
09:08
Table (information)Direction (geometry)Mach's principleRow (database)TransmitterSound effectPhysical lawComputer fileComputer animation
11:07
MetadataCode refactoringPHPMobile appSet (mathematics)Musical ensembleConstraint (mathematics)Direction (geometry)Computer fileOpen sourceSoftware testingDefault (computer science)MetadataComputer data loggingCodeCode refactoringFunktionalitätMobile appEnergy levelProcess (computing)Mach's principleProxy serverWEBSummationTable (information)Liste <Informatik>TrailSequenceJavaScriptVideo game consoleBlack boxLecture/ConferenceComputer animation
17:42
PHPSymfony <Framework, Informatik>Computer fileQuery languageSet (mathematics)Cross-site scriptingGraphical user interfaceJavaScriptAsset <Informatik>Computer fileWeb browserLogarithmDownloadHIT <Programm>Selenium <Software>Firefox <Programm>Anbindung <Informatik>Moment (mathematics)Computer data loggingTable (information)Software testingMySQLACCESS <Programm>HTMLSource codeChannel <Internet>Concurrency (computer science)Propositional formulaDevice driverParsingComputer animation
24:08
Cross-site scriptingGraphical user interfaceGraphical user interfaceFirefox <Programm>Particle detectorUniform resource locatorLecture/ConferenceComputer animation
25:52
HTTPMoment (mathematics)Process (computing)Server (computing)JavaScriptPHPLecture/ConferenceComputer animation
26:52
Software testingCode refactoringGrand Unified TheoryTotal S.A.Sound effectSchaleLecture/Conference
28:14
Mainframe computerData modelCodeGrand Unified TheoryDomain nameSpeciesMicrosoftData modelParameter (computer programming)Mainframe computerSingle-precision floating-point formatWeb serviceComputer animation
30:18
Data modelCodeMainframe computerDomain nameData modelObject (grammar)Enterprise architectureSocial classService (economics)DatabaseMainframe computerLecture/ConferenceComputer animation
32:08
Table (information)Configuration spaceCodeService (economics)Encapsulation (object-oriented programming)Table (information)State of matterCodeService (economics)Overhead (computing)Data managementAPISystems <München>Lecture/ConferenceComputer animation
34:52
Service (economics)Encapsulation (object-oriented programming)CodeTable (information)Configuration spaceVariable (mathematics)Encapsulation (object-oriented programming)Atomic nucleusTable (information)Service (economics)Constraint (mathematics)DatabaseLecture/ConferenceComputer animation
35:44
Variable (mathematics)Service (economics)Version <Informatik>Variable (mathematics)Content (media)Division (mathematics)Highlight <Programm>Parameter (computer programming)CodejQueryAsset <Informatik>File viewerAPIEigenvalues and eigenvectorsComputer animation
38:40
Computer fileCache (computing)Moment (mathematics)EmailAsset <Informatik>Query languageClient (computing)Sample (statistics)JavaScriptInstallable File SystemSTYLE <Programmierumgebung>Nichtlineares GleichungssystemCalculationElectronic visual displayGrand Unified TheoryComputer animationLecture/Conference
44:01
Service (economics)DatabaseDatabaseCode refactoringDebuggerDirection (geometry)Mobile appMoment (mathematics)Sound effectTable (information)Directory (computing)Grand Unified TheoryInternetStaff (military)Beam (structure)Lecture/Conference
49:13
Jenkins CIProxy serverMoment (mathematics)Wiener filter
49:53
UpdateService (economics)Queue (abstract data type)SIMPL <Programmiersprache>PAUSScientific modellingPlane (geometry)Process (computing)Exchange Server 2007 Service Pack 1Lecture/Conference
52:24
World Wide WebopenSUSEComputer animation
Transcript: German(auto-generated)
00:07
Hallo zusammen, ich bin Malte, ich bin Entwickler bei der Web Factory. Wir sind eine Web Agentur in Bonn, aber wir sind nicht eine von diesen Agenturen, die immer nur Bam, Bam, Bam neue Landing Pages am Fließband raushaut,
00:22
sondern wir haben durchaus antrufsvolle Projekte und betreuen ja auch langfristig. Und wenn man Software langfristig betreut, dann kommt man früh oder später an den Punkt, dass sich ja irgendwie auch ein Haufen alter Software angehäuft hat. Und heute geht es darum, wie wir den irgendwie Schritt für Schritt so einen Haufen Software
00:40
in die Moderne ziehen können, indem wir Microservices eben extrahieren. Wer ganz genau hinschaut, der sieht, der Titel hat sich ein kleines bisschen geändert, im Vergleich zum Programm, da steht noch Extration von Microservices aus einem Monolithen. Tatsächlich habe ich aber gemerkt, alle meine Beispiele beziehen sich auf eine monolithische Web-Anwendung.
01:03
Ist mir leider zu spät aufgefallen, aber ich wollte jetzt nicht schon im Titel falsche Erwartungen heben. Ich glaube aber, dass die Konzepte, die dahinterstecken, dass sie sich auch übertragen lassen, oder? Ich hoffe, sagen wir mal so. Mal gucken, vielleicht kann ja jemand was dazu sagen. Gut, die meisten hier, die in so einem Vortrag sitzen, die werden wahrscheinlich
01:22
ihren eigenen Monolithen kennen und wahrscheinlich ihre eigene Lions-Geschichte damit haben. Unsere sieht so aus. Vor mittlerweile 17 Jahren kam ein Kunde auf uns zu und wollte ein Projekt haben und haben wir gedacht, ja super machen wir und haben dann so einen schönen kleinen PAP-Elefanten auf eine grüne Wiese gepflanzt und alles war gut, der Kunde war zufrieden.
01:40
Der Kunde war so zufrieden, dass er mehr davon haben wollte. Das war ein Erfolg, es kamen irgendwie mehr Wünsche, wir haben mehr umgesetzt, die Anwendung wurde irgendwie erwachsen und der PAP-Elefant wurde erwachsen. Und je mehr Features der Kunde haben wollte, desto mehr haben wir irgendwie ein gemeinsames Muster festgestellt. Das war nämlich eigentlich alles irgendwie eine Form von Crud-Anwendung, die er haben wollte.
02:03
Also sprich, das Erstellen, das Ansehen, das Bearbeiten und das Löschen von irgendwelchen Entitäten. Und was machen wir, wenn wir irgendwie ein gemeinsames Muster feststellen? Wir schmeißen ein bisschen Abstationen drauf, haben noch ein bisschen Magie dazu gepackt und das alles eben implementiert, damit wir diese Art von Features schneller
02:21
umsetzen können. Und das war auch erfolgreich und so erfolgreich, dass der Kunde auch immer mehr haben wollte und dann kamen immer mehr Features drauf. Und irgendwann ist das dann aus technischer Sicht gekippt und wir hatten so das Gefühl, dieses Projekt ist irgendwie so ein bisschen Opfer des eigenen Erfolgs, da wurde einfach immer noch weiter draufgeschmissen. Und dann haben wir uns das Anfang des Jahres nochmal angeschaut und festgestellt,
02:44
dass es irgendwie so ein bisschen entartet, das Ganze. Wir haben draufgeschaut und haben gesehen, die Service Registry ist mittlerweile zweieinhalbtausend Zeilen lang. Wir haben über 100 Pakete eingebunden, teilweise über Pair, teilweise über Composer.
03:00
Das damalige, vor 17 Jahren, hauseigene Framework ist irgendwie eine unheilige Allianz mit dem Zen Framework 1 eingegangen und überall steckt irgendwie Magie und versteckte Abhängigkeit und man sieht das gar nicht alles mehr so, wenn man irgendwie von oben drauf guckt. Die ursprünglichen Entwickler sind natürlich nicht mehr da und was fehlt? Logischerweise jegliche Form von Dokumentation.
03:21
Aus technischer Sicht also irgendwie ein bisschen düster. Das Schlimme daran ist, das Ding läuft und läuft und läuft und läuft und das schafft laufend Wert für den Kunden und deshalb will er das behalten und will das noch weiter ausbauen. Das heißt, wir mussten das irgendwie technisch wieder einfangen.
03:41
Und was haben wir da gemacht? Wir haben noch ein Framework draufgeschmissen und jetzt könnte man sagen, UUU ist das wahrscheinlich nur so eine mittelmäßig kluge Idee, auf den Haufen alter Software jetzt noch eins draufschmeißen. Haben wir aber gemacht und zwar mit einem eigentlich ganz guten Plan, den wir Legacy Integration nennen. Das ist ein Weg, wie wir diesen fiesen Legacy Kern behalten, aber drumherum
04:04
Symfony als Framework schnallen und das so ein bisschen verstecken. Wir haben Symfony so geschrieben, dass alle Requests an die Alteranwendung irgendwie da reingehen und interessiert uns nicht, müssen wir nicht gucken. Das passiert alles unter der Haube, aber alles Neue, was wir entwickeln, das
04:20
können wir schön in einem modernen Stack auf dieser Symfony Hülle tun. Das hat schon mal das ein bisschen wieder aufgeklärt, aber wir wissen natürlich, hier drunter sieht es irgendwie immer noch fies aus. Was machen wir mit diesem Legacy Kern? Gerade, wenn wir irgendwas in diesem alten Teil modernisieren wollen.
04:41
Die Antwort, die man heute gibt, ist, naja, wir teilen das irgendwie in shiny neue Microservices auf. Und wie wir dabei vorgehen, davon handeln die nächsten 40 Minuten. Ich habe meinen Talk in drei Bereiche aufgeteilt. Das erste sind die Vorüberlegungen, da geht es um die allgemeine Rangehensweise und ein paar Tipps zur Entwicklungsumgebung.
05:03
Dann der Teil zu unbenutzten Ressourcen, dreht sich darum, falls wir uns entschieden haben, dass wir unseren Microservice als Klon des Monolithen aufsetzen und alles wegschneiden, was nicht zu der Microservice gehört, damit nur der übrig bleibt, dann haben wir das Problem, wie erkennen wir denn das Zeug, was wir wegschneiden sollen? Das sind genau diese unbenutzten Ressourcen.
05:23
Und der dritte Teil behandelt gemeinsam genutzte Ressourcen, die also sowohl der extraerierte Microservice als auch der Monolith benutzen. Ist das gut, dass wir das zusammen nutzen? Sollen wir das aufteilen? Und wenn ja, wie? Das ist der dritte Teil. Ich bleibe in meinem Talk relativ abstrakt, weil ich glaube,
05:42
dass die grundlegende Idee total einfach ist, aber die ist nicht die schmierigen technischen Details. Wer sich für technische Details für Microservices interessiert, dem würde ich das Buch Building Microservices von Sam Newman empfehlen. Und wer hier aus der Region kommt, ich höre auch
06:00
immer sehr gutes über das Bonner Microservices Meetup. Zu diesen Vorüberlegungen. Mir persönlich sind Kurzentwicklungszyklen total wichtig. Und das, weil wir hier zwei Probleme haben. Erstens, dieser Monolith ist total unübersichtlich. Wir haben irgendwie immer Angst, wenn wir den anfassen, wenn wir
06:21
irgendwie hier in dem Rüssel ziehen, dass da irgendwie ein Auge abfällt oder sowas. Das sind diese versteckten Abhängigkeiten, diese Seiteneffekte, wo wir einfach keinen Überblick mehr haben, weil das Ding so groß geworden ist. Das zweite sind Rattenschwänze. Wenn wir diesen alten Code sehen, dann juckt es wahrscheinlich total in den Fingern, dass wir den jetzt auch refektern wollen. Wir wollen das gerade ziehen und machen die Datei
06:40
auf und sehen, heute sind wir ja viel klüger, würden wir total anders lösen. Und da begeht man sich dann mal eben schnell in das Rabbit Hole rein und versucht, das gerade zu ziehen, hat aber vielleicht die Komplexität unterschätzt, denn so ein Monolith hat einfach irgendwie viele Abhängigkeiten. Und irgendwann denkt man vielleicht, oh, das breche ich jetzt lieber ab und möchte eigentlich wieder zurück.
07:03
Deshalb möchte ich eigentlich eine Strategie haben, wo ich ganz, ganz viele Reißlein habe, also ganz viele Sicherheitsnetze, wo ich immer sagen kann, nach fünf Minuten, oh, jetzt habe ich mich irgendwie verrannt. Das wird irgendwie nichts. Ich will zurück auf meinen letzten Commit und dann ist alles wieder gut. Dann kann ich irgendwie neu anfangen.
07:21
Eigentlich ist das ein Standard-Problem. Das will ich eigentlich bei jeder Software-Reklinge so haben. Gibt es auch eine Standard-Lösung für? Ja, automatisierte Software-Tests. Und in dem Zusammenhang finde ich Blackbox-Tests wichtig. Klar, Unit-Tests haben auch ihre Rechtfertigung und Daseinsberechtigung und sind total gut.
07:42
Nur in diesem Kontext finde ich sie nicht so wichtig, denn in der Regel haben wir im Moment nicht dieses Verständnis von den Modulierten, dass wir wirklich zu jeder Unit sagen könnten, das ist der Kontext, in dem arbeitet sie und vor allen Dingen die ist für uns relevant. Deshalb spreche ich mich dafür aus, hier Blackbox-Tests zu schreiben und mit denen alle Features dieses
08:00
Microservices, den wir extrahieren wollen, abzutesten. Und so lernen wir auch nach und nach kennen, was dieser Microservice eigentlich tun soll. Denn wahrscheinlich ist die Aufgabenbeschreibung am Anfang nur so gewesen, naja, die App, die unter Slash eins läuft, die soll eben irgendwie raus. Aber was sie so genau macht, das weiß wahrscheinlich keiner mehr nach 17 Jahren.
08:24
Was sind das für Sachen, diese Features, die wir abtesten wollen? Als Beispiel könnten wir sagen, die Startseite eines Bereiches wollen wir mal abgucken. Wir gucken, dass dann 200er da rückkommt, dass irgendwie Messages ausgegeben werden, wie auch immer. Wir können den Login prüfen, wir können so ein Crud-Zyklus gucken, also wir erstellen eine
08:41
Identität, wir schauen sie an, wir löschen sie und bearbeiten sie vorher. Wir können die Suchmaske ausfüllen und die Ergebnisliste angucken. Interessant sind auch zukunftsgeschützte Requests, was passiert, wenn ich eine bestimmte Funktion aufrufe, als Gast, als eingelogter Benutzer oder eben als Admin zum Beispiel. Oder was auch immer sonst in eurem jeweiligen
09:01
Kontext gerade interessant ist. Kommen wir zu zwei Tipps zur Entwicklungsumgebung. Erstens, ihr habt ja wahrscheinlich schon irgendwie Kämpfe mit Dämonoliten gefochten und habt deshalb irgendwie einen lokalen Checkout. Ich glaube, ihr tut euch einen großen Gefallen, wenn ihr den behaltet. Denn bei den ganzen versteckten Abhängigkeiten
09:21
und so weiter, wird es glaube ich einfach passieren, dass man irgendwann zu weit läuft. Man hat zu viel gelöscht oder irgendwas Refakt hat oder sowas und lernt erst Tage später, dass das irgendwie doch relevant war. Dann ist es total wichtig, dass man noch mal schnell zurückspinzen kann. Wie sollte das denn eigentlich laufen? Zweiter Tipp, Slim Dump. Zumindest für die MySQL-Benutzer unter uns.
09:43
Slim Dump ist open source und ist ein Tool für schnelle anonymisierte MySQL-Dumps. Das Schöne daran ist, dass Benutzkonfigurationsdateien. Da kann ich zum Beispiel sagen, aus der Tabelle möchte ich nur einen Testdatensatz sagen, weil nur 10 Prozent aller Datensätze. Aus der nächsten Tabelle möchte ich keine
10:01
Blobs runterladen. Und die Usertabelle, die will ich nur anonymisiert haben. Also ersetzen wir die E-Mail-Adressen und die Benutzernamen und so weiter. Und ich kann auch konfigurieren, welche Dateien, welche Tabellen ich überhaupt dampfen möchte. Und das ist ganz spannend, weil der Microservice, den ich extrahiere,
10:22
der wird ja wahrscheinlich nicht alle Tabellen benutzen, die er monolith benutzt hat. Und wenn ich nach und nach feststelle, die Tabelle brauchst du nicht, x, y, dann kann ich das in der Konfiguration festhalten. Und ich finde das eine schöne Art, dieses Wissen zu persistieren und den Fortschritt damit zu dokumentieren. Und wenn ich diese Config-Datei versioniere, dann haben auch gleich alle meine
10:40
Kollegen was davon. Dann die Frage, wenn ich jetzt mit dem Microservice starte, wie mache ich das konkret? Mache ich das auf der grünen Wiese? Oder mache ich einen Klon von meinem Monolithen und schneide da eben ganz viel weg, bis nur noch das Relevante übrig bleibt? Das sind ja beides legitime
11:01
Herangehensweisen und es gibt viele Gründe, die für die eine oder andere Richtung sprechen. Für mich kocht das alles auf drei Kriterien zusammen. Und zwar erstens die Menge der Einschränkungen, die ich mitnehme. Wenn ich auf der grünen Wiese starte, klar, dann habe ich maximale Freiheit und minimale Einschränkungen. Wenn ich dagegen mit dem Klon starte,
11:21
dann übernehme ich zum Beispiel die ganze technische Welt des Monolithen und bin auch erst mal daran gebunden. Zumindest so lange, bis ich da in meinem Microservice irgendwie ausbrechen kann. Das spricht also für die grüne Wiese. Zweites Kriterium, Nutzung alter Metadaten. Damit meine ich insbesondere die Commit-Message-History. Das ist oftmals unsere einzige Chance,
11:43
zumindest in meiner Erfahrung, eine Stelle von besonders verrücktem Code irgendwie überhaupt noch verstehen zu können. In meiner Erfahrung ist das eine wahre Goldgrube an verstecktem Wissen. Vielleicht fände ich eine Ticketnummer und kriege den ganzen Kontext der Änderungen raus. Ich finde, das kann man gar nicht schwer genug gewichten, dieses Argument.
12:02
Sprich also für den Klon. Und drittens, wie fließend kann ich den Übergang gestalten von Stand zu Stand der Microservice ist in Produktion. Diesen Fluss habe ich nicht, wenn ich auf der grünen Wiese starte. Denn da habe ich erst mal eine ganz große Latenz. Da muss ich von null aufbauen. Das dauert Tage, Wochen,
12:21
Monate, bis ich irgendwie die Funktionalität wiederhergestellt habe. Auf der anderen Seite, wenn ich einen Klon danebenstelle, dann kann ich jetzt mal ganz einfach gesprochen um meinen originalen Monolithen eine Proxy drum schnallen und sagen, alle Request, die den Microservice betreffen, die reichste bitte an den Microservice-Klon weiter.
12:41
Unter aller anderen behandelst du selbst. Und damit, also theoretisch läuft es schon. Mache ich dir in einer Stunde. Vielleicht nicht in einer Stunde, aber es ist irgendwie klar, dass das erheblich weniger Aufwand ist, als jetzt alles neu zu programmieren. Mein Fazit, es gibt gute
13:01
Gründe für beide Richtungen. Für mich überwiegen die beiden. Also bis ich da irgendwie mal eine Situation kennenlerne, werde ich per Default immer den monolithen Klonen. Und dann stellt sich die Frage, wie schneide ich denn die Dinge weg, die da nicht hingehören, sodass nur noch mein schöner, kleiner Microservice übrig bleibt. Und damit willkommen zu zwei Teilen, den unbenutzten
13:21
Ressourcen. Ihr seht meinen Tech Stack. Ich habe das beispielhaft an PHP-Dateien, die eben den Code machen. Hier, das ist Composer, ist ein Paketmanager für PHP. Ich schaue mir MySQL-Tabellen an, und Jan steht hier stellvertretend für die ganzen Frontend Assets, also
13:42
JavaScript, CSS, aber auch Bilder und so ein Kram. Wie erkenne ich die? Und wie erkenne ich die in kurzen Interaktionen? Ich bin also an dem Stand, ich habe meine Blackbox-Tests geschrieben, und die laufen, alles gut. Dann versuche ich doch einfach mal eine von diesen unbenutzten Ressourcen zu löschen.
14:02
Lass meine Tests durchlaufen, stell fest, wahrscheinlich ist was kaputt gegangen, ich muss es irgendwie fixen. Vielleicht hatte ich auch Glück und kann direkt comitten, und dann geht es weiter. Dann lösche ich die nächsten unbenutzten Ressourcen für die Tests aus, fixen, comitten und so weiter. Und da drehe ich mich ein paar Mal drin. Irgendwann finde ich nichts mehr, was ich löschen kann,
14:21
habe aber das Gefühl, ich will jetzt ein bisschen Refactoring machen, dann mache ich das, Test ausführen, fixen, comitten und so weiter. Dann durch das Refactoring ermögliche ich vielleicht, dass wieder andere Ressourcen unbenutzt sind, kann ich löschen und so weiter. Bis ich irgendwann denke, jetzt ist aber mal genug, jetzt geht es weiter zum Beispiel mit Teil 3 mit den geteilten Ressourcen.
14:42
Eigentlich ganz einfach. Und das ist auch kein Wunder, denn wenn man weit genug rauszoomt, dann sieht alles einfach aus. Die Frage, also der Teufel steckt natürlich im Detail, und die Frage hier ist, diese unbenutzten Ressourcen, wie erkennen wir die? Allgemein ist das leicht zu beantworten,
15:00
denn unbenutzten Ressourcen sind alle Ressourcen minus die, die benutzt werden. Und die benutzten Ressourcen, die können wir jetzt rauskriegen. Im ersten Schritt gucken wir irgendwie, dass wir irgendwie eine Form von Coverage Logging aktivieren. Dann lassen wir unsere Tests durchführen und dann können wir aus der Coverage irgendwie die benutzten Ressourcen ermitteln.
15:22
Wenn wir das haben, alle Ressourcen zu listen, ist in der Regel trivial, das ist irgendwie ein Showtables oder ein LS oder was auch immer, das kriegen wir ganz leicht hin. Und wenn wir die beiden haben, dann können wir auch simpel die Differenz bilden. Weil das jetzt aber im Detail durchaus ziemlich nicklig sein kann, und vor allen Dingen aufwendig,
15:41
habe ich ein Zauberlehrling geschrieben. Das ist ein Open Source Tool, das einerseits uns hilft, hier ein paar Schritte zu automatisieren und andererseits eine relativ umfangreiche Readme hat, in der nochmal diese Vorüberlegungen und so ein paar Tipps und Tricks konkret macht, ist, der sagt uns,
16:01
wie wir das Coverage-Logging aktivieren können, der kann die benutzten Ressourcen ermitteln und alle Ressourcen listen und sein eigentliches Ergebnis ist dann eben, die Differenz zu bilden und zu sagen, naja, diese Tabelle, die kannst du mal löschen und gucken, was passiert. Das heißt, die Tests haben hier eine Doppelrolle. Und wenn ihr nur einen Satz aus diesem
16:22
Vortrag mitnehmt, dann die Doppelrolle der Tests, denn die sind erstens dafür da, die Korrektheit sicherzustellen während des ganzen Prozesses und zweitens eben über diese Coverage zu ermitteln, was sind die benutzten Viecher, die wir weiterhin brauchen. Wie sieht das konkret aus, zum Beispiel bei PHP-Dateien? Allgemein,
16:41
unbenutzte PHP-Dateien sind alle PHP-Dateien minus die benutzten. Wie sieht das hier mit der Coverage aus? Die meisten PHP-Frameworks haben irgendeine Form von Front-Controller, also eine Datei, wo alle Web-Requests irgendwie durchgerutet werden. Und meistens sind die irgendwie nicht aufgebaut, die werden irgendwie eine Form von Application
17:01
bauen und damit dann den Request handeln, ob der hier aus einem Web kommt oder aus der Konsole, was auch immer. Wenn wir so einen Front-Controller haben, dann können wir uns ganz leicht einhaken. Keine Angst vor dem PHP-Code. Hier steht einfach nur Starte, das Coverage-Logging und hier unten steht einfach nur
17:21
Speicher, all die benutzten Dateien in einem Output-File. Das heißt, dann habe ich irgendwie schon mal die Liste der Dateien, die irgendwie benutzt wurden während meines Runs. Und dann kann ich so einen Zauberlehrling hingehen und sache ihm bin-Konsole show unused PHP-Files, gebe ihm diese Liste der benutzten
17:42
Dateien und dann versuche zu ermitteln, wo muss ich denn hingucken, wo sind die restlichen Dateien. Ich kann ihm das auch explizit sagen mit diesem pass to inspect. Ich kann ihm sagen, wo er sein Output hinschreiben soll und ich kann ihm noch so eine Blacklist mitgeben, zum Beispiel um, also damit ich einfach mein Ergebnis sauber halte, dass da zum Beispiel temporäre Verzeichnisse ausgeschlossen sind oder unit-Tests, die vielleicht
18:02
nicht durchlaufen oder was auch immer, irgendwelche Dinge, die ich vielleicht behalten will, aber die eben nicht während meiner Test-Runs berührt werden. Und dann sagt er mir, die PHP-Dateien, die übrig bleiben, die ich wahrscheinlich löschen kann. Wie sieht es bei Composer-Paketen aus? Ist wieder die gleiche Idee.
18:20
Nur die Details sind ein bisschen anders. Unbenutzte Pakete sind alle Pakete minus die benutzten Pakete. Dann gehe ich zum Zauberlehrling hin und sage, ey, show unused Composer-Packages. Das ist wieder diese Liste von Files, die wir vorhin hatten. Dann sage ich, wo liegt die Composer-JSON? Das ist die Datei, in der ich meine direkten Abhängigkeiten angebe. Und
18:42
dann sucht er sich wahrscheinlich schon automatisch, wie heißt das Verzeichnis, in dem Composer sein Zeug installiert hat. Was der Zauberlehrling jetzt hier macht, ist, der fragt Composer, also der fragt den Package Manager, das müsste nicht Composer sein, nach allen installierten Paketen. Es gibt ja nicht nur die direkten, die ich angegeben habe, sondern es gibt auch die indirekten.
19:01
Und aus diesen Paketen guckt er dann, welche sind denn wohl in Benutzung. Und das macht dafür folgt, er guckt, in der used-Files ist da irgendwie eine PHP-Datei drin, die in einem dieser Pakete liegt. Wenn ja, dann ist es wahrscheinlich benutzt. Und dann kann er noch so ein bisschen fancy-schmancy-Dinge hier tun, zum Beispiel Symphony-Bundle-Dateien ignorieren. Das ist so ein Sonderfall,
19:22
wenn nur diese Datei in ein Paket angefordert wird, und nichts anderes, dann ist wahrscheinlich dieses Paket irgendwie unnütz. Das ist einfach irgendwie eine Komfortgeschichte, die einfach praktisch ist, wenn man die mit automatisiert, finde ich. Was er tut, ist alles andere als perfekt. Denn der guckt sich tatsächlich im Moment nur PHP-Dateien an. Das heißt,
19:41
wenn ich ein Paket habe, was nur Convigental zum Beispiel oder nur Assets oder sowas, dann wird das hier auch als unbenutzt vorgesehen und wird zur Löschung vorgeschlagen. Also der Zauberlehrling macht natürlich nicht alles, sondern der macht eben Vorschläge und es nimmt einem nicht ab. Think before the lead, oder lasst zumindest die Tests laufen, nachdem du was gelöscht hast,
20:02
und dann siehst du wahrscheinlich, dass irgendwas kaputt geht. Unbenutzte MySQL-Tabellen. Auch wieder die gleiche Idee. Unbenutzte Tabellen sind alle Tabellen, minus die benutzten Tabellen. Hier läuft das, die Coverage darüber, dass wir das Query-Logging einschalten können. Bei MySQL geht das ganz einfach.
20:20
Hier ist es beispielsweise so, dass wir ihm sagen, schreibt das alles in so eine System-Log-Tabelle rein. Und dann gehen wir schon zu einem Zauberlehrling hin und sagen ihm show unused MySQL-Tabels. Was er dann macht, ist, er geht zu der Log-Tabelle hin und holt sich alle Statements raus, die eben sich während unserer Test-Runs gesammelt
20:41
haben. Also klar, zwischen Coverage einschalten und dem muss man natürlich die Tests durchlaufen lassen. Und guckt sich dann an, was haben wir denn da gesammelt. Und daraus wird er dann die benutzten Tabellennamen rausfinden. Und das ist nicht so total trivial, weil die können im From-Teil stehen, die können da
21:02
comma-separiert drin stehen, die können in der Join-Clause stehen. Da können sich Views einmischen und so weiter. Das will man nicht mehr mit der Hand machen, wenn man irgendwie hunderte oder tausende Queries da gelockt hat. Deshalb ist es ganz praktisch, dass der Zauberlehrling das automatisiert und der Benutzer führt einen SQL-Parser, um eben wirklich nur die
21:20
Tabellennamen rauszufinden. Und dann, mit ShowTables holt er sich alle Tabellen, findet die Differenz und sagt uns die Tabellen, die wir wahrscheinlich löschen können. Unbenutzte Frontend Assets. Auch hier wieder die gleiche Idee. Unbenutzte Assets sind alle Assets, minus die benutzten Assets. Hier läuft die Coverage über
21:41
Webserver Access Logs. Dann gehen wir zum Zauberlehrling hin und sagen Show Unused Public Assets. Hier ist das Webserver Log File. Hier ist dein Public Verzeichnis. Wenn das irgendwie ein komisches Log File ist, mit einem komischen Format, dann sagen wir eben so, wie findest du denn darin die Dateinamen?
22:01
Wo sollst du dein Output hinschreiben? Und vielleicht wird es wieder ein paar Sachen ignorieren. Und das funktioniert so meh. Denn wir haben hier vor allen Dingen drei Probleme. Erstens, Assets Download. Wenn wir zum Beispiel Standard Behead-Tests machen, dann macht er das standardmäßig mit Good
22:21
als Browser. Das ist ein Headless Browser, der wird nicht das JavaScript herunterladen und ausführen. Der wird nicht das CSS herunterladen. Der wird nicht Bilder herunterladen. Das heißt, diese ganzen Hits finden wir gar nicht mehr im Log File. Zweites Problem, Kompilate. Wenn wir so eine wunderschöne Deployment-Pipeline aufgebaut haben, wo alle JavaScript-Dateien
22:42
in eine große Form kandidiert werden, dann hilft uns so eine Aussage, wie diese Datei wird benutzt, relativ wenig. Und das dritte Problem ist die automatisierte Coverage in JavaScript- und CSS- Dateien zu erkennen. Ich habe da Ansätze, aber das ist alles noch nicht ganz
23:01
rund. Zum Assets Download. Naja, wir sind hier nicht auf Good festgelegt. Wir können zum Beispiel Selenium als Browsertreiber anbinden. Und mit dem können wir Chrome, Firefox usw. fernsteuern. Wir können sogar Browserstack anbinden und dann eine beliebige Anzahl von Browsern auf unser Problem draufjagen.
23:21
Kompilate. Naja, vielleicht kriegen wir die verhindert. Vielleicht müssen wir da in unsere Deployment-Pipeline ein bisschen eingreifen und sagen, konkreten wir das nicht, sondern schreibe eben all die einzelnen Dateien so in das HTML rein, dass ich die nochmal zuordnen kann. Eine andere Idee wäre irgendwie über Source Maps zu gehen, aber das ist auch komplizierter, also so weit bin ich definitiv noch nicht.
23:42
Aber dann wird es nochmal richtig schwierig, wenn es nämlich darum geht, die Coverage innerhalb dieser Dateien zu finden. Bei JavaScript gibt es so einen Haufen an Tools, zum Beispiel Istanbul JS Cover, Blanket JS, für eben die JavaScript Code Coverage. Ich habe die Folien gestern Abend das letzte
24:01
Mal aktualisiert, ich schätze seitdem gibt es drei neue oder so. Und die kannst du anbinden an JavaScript-Testrunner, wie zum Beispiel Karma oder Jasmine, muss dann aber eben auch deine JavaScript-Test natürlich dafür schreiben. Und da bin ich auch noch nicht so weit, dass das irgendwie in einem Rutsch irgendwie durchgehen würde. Noch schwieriger wird die Sache bei CSS-Dateien.
24:23
Aber da ist gerade immerhin viel Bewegung. Zum Beispiel hat der Chrome seit 59 ein extra Panel für CSS-Coverage und das funktioniert etwa so, der guckt sich alle CSS-Dateien an, die in der Seite geladen wurden, guckt sich daran alle Detektoren an und guckt, treffen die
24:40
irgendwie in dem Dokument, was ich gerade geladen habe. Wenn sie treffen, dann hat das wahrscheinlich eine Relevanz, wahrscheinlich, ist auch nur Neuristik. Wenn sie nicht treffen, dann hat es wahrscheinlich keine Relevanz. Das Problem ist, das habe ich noch nicht automatisiert gekriegt. Also weder kann ich dem Chrome sagen, hier liest mal diese zehn URLs nacheinander ein,
25:00
noch kann ich den Output strukturiert irgendwie abgreifen. Ein bisschen besser läuft es gerade bei dem Firefox-Dusty-Selector, das ist ein Firefox-Backend. Dem kann ich immerhin das Sitemap zu fressen geben. Der läuft alle URLs ab und kann mir am Ende das in einem JSON-Format rausgeben.
25:21
Ist aber, glaube ich, auch noch nicht irgendwie das Ende der Straße, also das muss irgendwie noch besser werden. Die Blackbox-Sets,
25:44
von denen ich gesprochen habe, sind vor allen Dingen Behead-Tests gewesen. Die Frage war, wie führen wir eigentlich diese Blackbox-Tests aus, von denen ich gesprochen habe? Da wurden ein paar Beispiele genannt, Konzepten und so weiter. Im Moment habe ich vor allen Dingen PHP-Tests und das heißt, ich habe vor allen Dingen Behead benutzt. Und dann wird eben
26:02
Behead in einem PHP-Prozess gestartet, der einen Web-Request macht auf meinen Server über HTTP und so weiter. Das sind getrennte Prozesse und so weiter. In JavaScript soweit bin ich noch nicht, dass ich da irgendwie etwas wirklich empfehlen könnte. Das war der Teil zu
26:24
den unbenutzten Ressourcen, wie wir die erkennen können. Der dritte Teil geht über die gemeinsam benutzten Ressourcen.
26:57
Also, wenn ich die Frage kurz
27:05
wiederhole, so wie ich sie verstanden habe, wie finde ich Totencode heraus, der vielleicht gar nicht benutzt wird? Vielleicht ist es irgendeine Abstraktion, vielleicht ist es irgendein Pfad, der gar nicht benutzt wird und meine Tests laufen einfach durch. Richtig? Genau.
27:25
Die Antwort finde ich nicht raus. Also, ich verlasse mich ein bisschen darauf. Ich benutze PHPStorm. Der hat eine relativ gute Statische Code, also relativ gute. Für mich die beste Statische Code-Analyse, die ich kenne, von einer IDE. Und der sagt mir zum Beispiel,
27:41
dieser Branch ist irgendwie tot, weil die Bedingung nie ein und ein treffen kann oder sowas. Aber schwierige Sachen wie unnütze Abstraktion oder sowas findet auch der nicht. Also, da ist man weiterhin gefordert und ich denke auch, es ist eine Frage, wie ich mich während des Refactorings eben daran nähere. Und das ist eigentlich eine ganz wichtige Frage, denn wenn ich so unnütze Abstraktion zum Beispiel wegschneide,
28:01
dann fällt häufig auch ein ganzes Paket weg oder ein ganzer Zweig oder was auch immer. Also, gerade das sind die spannenden Punkte, wo ich eben nochmal gehirnisch investiere, um den eben nochmal deutlich kleiner schneiden zu können. Dritter Teil, die gemeinsam benutzten Ressourcen. Da stellt sich dann eben die Frage, will ich die weiterhin gemeinsam benutzen? Ist das eine gute Idee? Will ich das aufteilen?
28:21
Wenn ja, wie? Und das ist meistens eine Abwägung zwischen der Ersparnis, die ich habe, wenn ich es einfach weiterhin teile, und der Entkopplung auf der anderen Seite. Und dieses Entkopplungsargument ist eigentlich total wichtig, denn darum geht es ja eigentlich bei Microservices. Das ist eins der zentralen Argumente, dass sie eben autonom sind. Wenn ich zu sehr die Ersparnis abgreifen
28:41
möchte und zu sehr mich darauf verlasse, dann laufe ich Gefahr, in das Microservices ending up as distributed monoliths zu laufen. Das heißt, ich hatte am Anfang einen Monolithen, der war ganz furchtbar, habe ihn in viele Teile gehackt. Die haben aber die gleichen Abhängigkeiten wie bisher nur jetzt auf X-Systeme verstreut, und ich finde sie noch viel schlechter als vorher.
29:00
Das will ich natürlich nicht. Das heißt, hier neige ich so ein bisschen zu Entkopplung, aber nicht in jedem Fall. Deshalb habe ich jetzt hier mal so ein paar Ressourcenarten aufgezählt, die wir teilen können, die typischerweise geteilt werden, zumindest am Anfang, und dann total subjektiv, wie kritisch ich das finde, wenn man die weiterhin teilt.
29:22
Erstens shared host, also tatsächlich die physikalische Maschine. Wenn mein Monolith und der extra Microservice, den ich gerade extrahiert habe, die auf der gleichen Maschine laufen. Ich finde das okay, neutral. Klar, man kann sagen, das ist ein Single Point of Failure, und da hat man dann auch total recht.
29:41
In meiner Erfahrung ist es einfach noch nicht vorgekommen, dass wenn der eine Host kaputt gegangen ist, dass der andere Standalone Host mich gerettet hätte. Das mag bei anderen Anforderungen total anders sein. Wie gesagt, your mileage might vary. Anderes Thema, shared code. Da habe ich mal so zwei Pole angeschaut. Einerseits basale Infrastruktur
30:00
und andererseits das Domain Model. Mit basaler Infrastruktur meine ich so echt ganz low level Dinge. Zum Beispiel das Framework, Symphony Framework, würde ich auch in jedem Microservice benutzen. Wenn ich Amazon Web Services benutze, dann würde ich immer deren SDK reinholen. Also so Dinge, die ich so typischerweise in Third Party Libraries einordnen würde,
30:22
das ist die basale Infrastruktur, und das finde ich gut, wenn man die weiterhin benutzt, denn dann kann ich in jedes Projekt mit einem ähnlichen Mindset reingehen. Ganz anders sieht es beim Domain Model aus, wenn das geteilt wird. Denn ich glaube, dass die verschiedenen Microservices eine total unterschiedliche Sicht auf diese Domainobjekte haben.
30:41
Zum Beispiel wird eine Buchhaltung sich was völlig anderes unter einem User vorstellen als ein Freundschaftsservice. Was interessiert mich im Freundschaftsservice ist die Kontonummer des Users. Das ist einfach nur ein Spam in meiner Klasse, der mich irgendwie nur irritieren kann. Und das würde ja bedeuten, wenn ich das alles zusammenhalten will, dass dieses
31:00
Enterprise Domain Modell von einem User, dass das die Obermenge von allen Microservices sein müsste, in allen Anforderungen, die irgendwie haben, in einer großen Riesenklasse zusammen. Und ich glaube, das funktioniert nicht. Allein schon wegen der Namenskonflikte wird das nicht funktionieren. Und wenn sich dann irgendwie ständig Apis ändern und ich müsste alle aktualisieren, ich glaube, das ist eine ganz schlechte Idee.
31:20
Jeder sollte seine eigene Sicht darauf haben. Spannendes Thema auch, Shared Database. Und da habe ich mir mal angeschaut, die Server-Ebene und die Schema-Ebene. Server, also wenn ich jetzt einen MySQL- Datenbank-Server habe und da laufen verschiedene Datenbanken drin, dann finde ich das ähnlich wie beim Shared Host okay. Solange die sauber voneinander getrennt sind,
31:42
stört es mich nicht, wenn die zusammenlaufen. Ich habe vielleicht weniger Administrationsaufwand, vielleicht hat das buchhalterische Gründe oder sowas. Finde ich okay. Vor allen Dingen, weil man das auch total leicht später wieder trennen kann, wenn man möchte. Ganz anders sieht es aus, wenn innerhalb eines Schemas Dinge geteilt werden. Und weil das aber
32:00
die typischerweise die Ausgangssituation ist, wenn ich einen Microservice extrahiere, will ich da nochmal kurz reinschauen. Und das einzige, was uns daran interessiert, sind geteilte Tabellen. Denn ungeteilte Tabellen, also welche, die nur vom Microservice benutzt werden oder nur von Monolithen, die schlage ich dem einfach zu. Interessiert sich sonst keiner dafür. Die kann ich einfach aufteilen. Also Thema geteilte
32:22
Tabellen. Was kann in diesen Tabellen drinstehen? Erstens, es könnten statische Daten sein. Zum Beispiel eine Länderliste. Wenn das statische Daten sind, dann habe ich erstmal gar kein Synchronisationsproblem und kann die einfach rüberkopieren in meinem Microservice. Im einfachsten Fall mache ich das mit einer Tabelle und alles läuft wie bisher. Wenn
32:44
ich überlege, das sind statische Daten, sind die überhaupt gut aufgehoben in einem Datenmanagement System, was ja eher für veränderliche Daten toll ist, vielleicht komme ich dann auf die Idee, ich könnte sie an Code oder Konfiguration verschieben. Und wenn ich schon da habe, könnte ich mir auch überlegen, will ich vielleicht ein Paket daraus schnüren? Zum Beispiel ein Composer-Paket,
33:01
was ich dann eben zwischen Anwendung teile. Und das wird man im Einzelfall sehen müssen. Ich werde ein bisschen vorsichtig, weil das hat ja auch alles seinen Overhead. Ja, muss man eben im Einzelfall sehen. Spannender ist es bei veränderlichen Daten. Wenn also sowohl der Microservice als auch der Monolith beide in eine Tabelle reinschreiben wollen. Zum Beispiel
33:22
wenn die Buchhaltung in eine Notification-Tabelle reinschreiben möchte, deine Premium-Mitgliedschaft läuft in einem Monat aus. Und auf der anderen Seite haben wir diesen Freundschaftsservice, der in die Notifications reinschreiben möchte, du hast eine neue Freundschaftsanfrage erhalten.
33:40
Das sollten wir nicht so lassen, denn wenn wir das in Microservices aufteilen, in getrennte Systeme, dann wird es total schwierig, das zu verwalten. Dann wird es schwierig nachzuhalten, wer darf denn überhaupt hier reinschreiben in diese Tabelle, wer macht das, wer hat das Recht an diesem Datensatz, wer darf ihn bearbeiten, wer darf ihn löschen. Was müssen wir tun, wenn wir ihn löschen?
34:01
Müssen wir andere Leute benachrichtigen? Wenn wir eine Schemaänderung machen, wen müssen wir dann aktualisieren? Ich glaube, das ist eine Hölle, in die man eigentlich nicht will. Deshalb würde ich sagen, vielleicht checkt da ein neues Konzept drin. Vielleicht sollten wir auch hier einen Service bauen, der das Problem irgendwie kapselt. Und in dem Fall liegt da nah am nahe, lass uns einen Notificationservice machen. Das heißt,
34:20
dein Notificationservice kriegt die Tabelle, hier wird den anderen weggenommen, und die müssen dann über eine API eben damit kommunizieren. Und dann gibt es noch so ein paar ein bisschen besser versteckte Abhängigkeiten, nämlich bei Fremdschlüsseln und Views. Wenn wir zum Beispiel diesen Notificationservice jetzt rausgezogen haben, mit dieser Messages-Tabelle, dann hat
34:42
wahrscheinlich der Empfänger irgendwie einen Fremdschlüssel auf die User-Tabelle gehabt. Wenn wir jetzt aber die Messages-Tabelle in einen Service packen und die User-Tabelle erstmal mononiteln lassen, dann können wir ja nicht zwischen den beiden getrennten Datenbanken den Fremdschlüssel spannen. Das heißt, hier muss ich vielleicht auch wieder an so einen Service
35:02
decken, der das irgendwie kapselt. Und dann kann ich die User-Tabelle im ersten Schritt wieder hinter einem Service verstecken, mit einer API, die Leute greifen auf zu. Und ich werde mich dann allerdings um Constraints und Kaskaden selbst kürben müssen, in dem Clienten, also in dem Microservice. Sprich, dass es dürfen nur Freundschaftsanträge
35:22
an existierende User gemacht werden oder bei diesen Kaskaden, wenn dann ein User gelöscht wird, dann soll auch dessen Freundschaftsantrag gelöscht werden und so weiter. Das heißt, da muss ich auch nochmal nachdenken, muss vielleicht auch nochmal mit den Business-Leuten reden, was da jetzt wirklich alles mit gemeint war und da nochmal drum herum programmieren. Gut, wir
35:42
kommen zum Ende. Das ist jetzt die letzte geteilte Ressource und die auch schon in einem sehr weiten Sinne war das Rahmenlayout. Das erwähne ich vor allen Dingen deshalb, weil ich schon ganz oft von Leuten gehört habe, die einen Layout-Service bauen und wo das irgendwie total explodiert ist auffangsmäßig, weil irgendwie immer mehr Anforderungen gleich reinkamen und
36:00
man hat das irgendwie immer sehr spät zu einer Version eins geschafft. Und da möchte ich zumindest eine Idee geben, wie man damit billig starten kann. Das ist nicht das Ende der Straße, aber es ist ein schneller billiger Start. Und das ist ein Mini-Layout-Service im bisherigen Monolithen. Der nutzt aus, dass der Monolith wahrscheinlich ja schon
36:21
so ein Konzept von einem Rahmenlayout hat. Der wäre ja kein Monolith, wenn der nicht schon viele Sachen in einer beinhalten würde, viele Teilanwendungen oder so was. Und wie wird der ja? Da wird er ja nicht jedes Mal ein neues Layout geschrieben haben, sondern auch da wollte man schon den Code weiterverwenden und hat wahrscheinlich eben irgendwie so einen Rahmen drum herum gehabt und irgendwie dass diese Teilanwendungen dann eben nur noch so ihren
36:42
Content dann hier rein platzieren. Und das können wir uns zu Nutze machen. Wir können in den Monolithen irgendwie so eine leere Anwendung hinsetzen, die irgendwie so ein leeres View hat, wo nur so ein Plapazhal da drin steht, wie Place Content hier oder so was.
37:01
Vielleicht braucht er dann, je nachdem wie gut wir das eingebaut kriegen, braucht die Api dann noch so ein Parameter, was ist der aktive Menüpunkt, damit man den irgendwie highlighten kann und so weiter, denn der steckt ja, der würde ja hier zum Beispiel drin stecken. Aber dann bin ich im Grunde auch schon fertig. Dann kann mein Microservice das hier abfragen, cache dieses Ergebnis und ersetzt die Platzhalter eben mit seinem eigenen Content.
37:23
Und das ist was, was man tatsächlich ohne große Kenntnis des Monolithen an einem Nachmittag schaffen kann. Ist, wie gesagt, nicht die perfekte Lösung für alle Zeiten. Hat zum Beispiel das Problem oder kann das Problem haben mit zentralen Assets. Wenn jetzt das Menü hier aus irgendeinem Grund
37:41
jQuery benutzt, um das zu verarbeiten oder so was, oder rauszufahren oder so und ärgerlicherweise benutzt du noch jQuery 1.6 oder so was, dann ist das ein Problem, denn erstmal liefert der Rahmenlayout Service ja alle Assets mit aus, die er eben benötigt, sprich auch dieses jQuery 1.6 und knallt das dann an unseren Microservices vor die Nase.
38:02
Aber die sollen ja eigentlich autonom sein und ihre eigene jQuery Version benutzen können. Speziell jQuery hat dafür so einen No-Conflict-Mode, der erlaubt das irgendwie die parallel verschiedene Versionen einzusetzen. Das funktioniert auch ganz gut. Hört auch irgendwann auf Spaß zu machen, wenn man irgendwie einen Service hat, der eine Seite hat und da werden dann jetzt x Microservices
38:21
rein integriert und jeder bringt seine eigene Version mit, erstmal irgendwie in Megabyte verschiedene jQuery Versionen herunterladen will wahrscheinlich auch keiner tun. Also es ist nicht perfekt, aber es ist definitiv mal eine Idee, um damit billig anzufangen. Das war's auch schon. Ich danke für eure Aufmerksamkeit. Hier nochmal die URL zum Zauberlehrling.
38:40
Und ich sehe, es gibt schon Fragen. Erstmal glaube ich, wie verhindere ich im Rahmenlayout CSS-Konflikte? Das ist tatsächlich eine gute Frage und betrifft die Aufteilung davon, also es betrifft jetzt
39:02
eigentlich eine Frage, wie gestalte ich einen Layout-Service? Im engeren Sinne. Habe ich jetzt Erfahrung mit genau einem Layout-Service? Das heißt Stichprobe von eins ist wahrscheinlich nie so perfekt. Wir hatten das Glück, dass wir noch jemanden an Bord hatten, der einigermaßen aus den Dateienamen ablesen konnte, was wohin gehört. Und wir
39:22
haben das dann so gemacht, also es ist eigentlich schon Schritt zwei. Im Schritt eins, so wie ich es dargestellt habe, würde man sagen, der Layout-Service behält erstmal alles und der Client braucht nichts, weil der kriegt ja alle Assets schon von oben eingeladen. Schwieriger wird es, wenn der pro Seite unterschiedliche Assets hat. Also wenn du nicht einmal eine große CSS-Datei zum Beispiel kompliziert hast, sondern wenn jede Seite unterschiedlich
39:41
hattest. Aber dann kannst du auch sagen, dann gucke ich mir eben an, was gab es allgemein, zum Beispiel auf der Startseite oder so was und welche Datei hat zusätzlich der Microservice eingebunden. Dann würde ich eben sagen, diese zusätzlichen Dateien kommen in den Microservice rüber, der Layout-Service macht nur das, was zum Beispiel eben auf der Startseite war. Und wenn man Glück hat,
40:01
kann man da eben ein bisschen anhand der Dateienamen auslesen und so weiter. Generell würde ich sagen, das war nur der erste Schritt, ich würde versuchen, schnell zu überarbeiten und dann würde ich sagen, sollte der Layout-Service so minimal CSS und JavaScript und so weiter mitliefern wie möglich. Ein paar Sachen sind speziell in der Anwendung, die wir extrahieren. Und ein paar Sachen sind optional, weiß ich nicht, zum Beispiel Jack Query oder so was. Na, Jack Query ist ein
40:22
großes Beispiel, aber also Dinge, die ich eben zwischen verschiedenen Microservices teilen möchte. Jack Query, klar, weil es eine Third-Party-Library ist, wird die schon irgendwie mit MPM oder so was dann eben rübergeholt, aber vielleicht habe ich auch irgendwelche Shared Styles oder so was, die außerhalb des Rahmenlayouts noch für drei von vier Microservices benutzt werden oder so was, die kann ich dann eben
40:40
rauslagern und dann eben auch nur teilweise anfordern, wenn ich feststelle, das war doch irgendwie zu groß geschnitten oder so. Hat das die Frage beantwortet? Okay, die Antwort war ja. Aber vielleicht klären wir das gleich nochmal, wenn
41:00
Interesse besteht, im kleinen Kreis. Bitte, wenn ich kurz
41:32
unterbrechen darf, sonst vergesse ich den Teil wieder. Es wurden zwei, also zwei Ideen vorgeschlagen. Die erste ist
41:40
das, dass ich die CRPs da, was, wenn ich das richtig verstanden habe, statische Code-Analyse, aber irgendwie über die Kommando-Zeile machen kann, dass ich die Ausgabe strukturiert abgreifen könnte und mit dem Zauberlehrlingen vereinen, denn in der IDE das zu haben, das ist ja eine völlig andere Dimension. Und die zweite Idee? Die zweite Idee
42:11
ist, statt die Web-Server-Exist-Logs zu benutzen, um die Capacities bei den Assets rauszufinden, könnte ich ja vielleicht auch das Dateisystem monitoren und gucken, welche Dateien da
42:22
geöffnet wurden. Bin ich tatsächlich noch nicht drauf gekommen. Klingt ziemlich gut im ersten Moment. Compilat ist trotzdem ein Problem, aber zum Beispiel Images oder sowas wäre schon toll, wenn das darüber dann besser lief. Dann könnte man irgendwie einen Demon schreiben. Es ist eine sehr gute Idee. Caching
42:44
kann mir so oder so Probleme machen, das stimmt. Also das ist auch das Schöne an diesen Test-Runs, die ich mache. Der benutzt einfach keinen Cache. Der ruft alles ab, also völlig richtig könnte ein Problem sein.
43:27
Also ich habe schon versucht, die Anwendung komplett abzudecken. Sowohl Fehlerfälle, als irgendwie jeden Use-Case. Ich habe einen Freund angelegt, die Freundschaftsanfrage abgelehnt, angenommen und so weiter, E-Mails verschickt, alles Mögliche.
43:41
Weil ich auch erstmal lernen musste, was hat das Ding überhaupt gemacht, wo kann ich überall klicken, was sind das für Details, die mir in der Anführung verborgen blieben. Sodass ich das überhaupt erstmal alles sehen konnte und dann wird im besten Fall eben auch alles berührt. Aber das ersetzt natürlich nicht, dass da irgendwie ein Business-Mensch nochmal draufschaut. Aber ich habe die Frage nicht wiederholt.
44:05
Kannst du das nochmal kurz wiederholen? Dann wiederhole ich es ja auch nochmal. Genau. Das Test, gerade in Legacy-Anwendungen,
44:21
eben nur den Heavy Path abdecken und wir dann vielleicht gar nicht alle Festlungen sehen und dann gar nicht finden, welche Sachen wurden denn tatsächlich benutzt oder nicht. Und meine Antwort ist eben, ich versuche das eben hier möglichst vollständig abzudecken, denn wenn nicht, habe ich relativ wenig Chancen, das zu erkennen. Aber trotzdem, ich bin nur ein relativ dober Techniker, der nur so einen Ansatz
44:41
von der Domäne versteht. Es ersetzt natürlich nicht, dass irgendwie jemand mit Mehrfach bis am Ende nochmal draufguckt und sagt da, das war aber ein Feature, das war kein Bug irgendwie, weil ich es eigentlich falsch interpretiert habe. Bitte.
45:15
In so einem System, wo dann tatsächlich eine Formel 3x5 zu Brut brauchen kann, kann man das einfach nur gut abbilden
45:22
und darunter stelle ich mir auch sehr, sehr furchtbar vor, weil es alles als möglicher geht. Hier wurde nochmal auf die Datenbanken eingegangen, das habe ich relativ kurz behandelt. Wie läuft das konkret, habe ich da Erfahrung damit, wenn da wirklich so eine große
45:41
Datenbank ist, die ich aufteilen muss in X-Service und so weiter. Bisher war ich da auch relativ glücklich, dass ich relativ klar sagen konnte, die waren schon genamespaced, vor allem die Tabellen, die wesentlichen. Das heißt, da wusste ich schon, die kann ich rausziehen und gucken, was passiert, und da ist alles gut gelaufen. Tatsächlich hatten die aber sowohl zum Beispiel Fremdschlüssel auf die User-Tabelle.
46:02
Jetzt hatte ich an der Stelle aber auch schon User-Service, der werde genau das eben gekapselt hat. Wobei so ein User-Service auch, das war nur ein Mini-Ding, was irgendwie auch in einem Nachmittag geschrieben war, weil der Zugriffsgeschütz einfach irgendwie für eine ID Bundesdaten rausgibt. Dann steckt da so ein Serializer dahinter, der es in JSON umwandelt und fertig war die Laube.
46:21
Das kann noch viel komplizierter werden, und ich habe da schon mal irgendwie Fragen in diese Richtung bekommen, wenn es da Trigger gibt, zum Beispiel. Wäre auch noch so ein Thema von versteckten Abhängigkeiten. Das kann total komplex werden. Und ich hatte wie gesagt bisher relativ viel Glück. Das, was ich da vorgestellt habe,
46:42
ist also so ein bisschen auch nur Bücherwissen. Das ist nur bei einfachen Fällen erprobt. Details würde ich dann auch in diesem, ich glaube, das war auch Refactoring Building Microservices von Sam Newman nachlesen. Kann aber sein, dass das auch in diesen Refactoring-Databases dran stand, wie ich das tatsächlich, wie ich das schrittweise hinkriege,
47:02
Daten migriere und so weiter. Also da würde ich auf die Literatur verweisen, weil ich es auch nicht viel besser weiß.
47:44
Also du hast dich nochmal dafür ausgesprochen, dass man eben Refactor as you read in dem Moment, wo man es liest und vor allen Dingen in dem Moment, wo man es gerade verstanden hat, dass man es da ein bisschen schöner formuliert, Refactored, wie auch immer. Das finde ich auch eine gute Regel, ist so ein bisschen dieses Fahrtfinder. Ich mache es nicht immer. Ich mache es meistens dann, wenn ich irgendwie
48:01
zum zweiten Mal an der Stelle vorbeikomme oder sowas, weil es kann einfach überwältigend viel sein und ich versuche das so ein bisschen zu filtern, was sind denn die wichtigsten Dinge. Aber, ja, das ist, du machst die Welt besser jedes Mal.
48:23
Schmerzhaft. Wie schmerzhaft ist das ein Microservice übergreifende Debuggen. Ich finde, du musst deinen Microservice erstmal total isoliert testen können. Das heißt, ich habe in dieser extrahierten App habe ich zum Beispiel einen Stub für den Layout Service programmiert,
48:41
der einmal sich das Layout genommen hat, einen statischen Abzug und das raushaut. Genauso habe ich einen User Service als Stub dahin gelegt. Das heißt, ich tausche einfach irgendwie die URL auf auf, keine Ahnung, closed API User Service 1 und dann gibt er mir immer den statischen Test-User zurück. Also, ich finde es total wichtig, dass du die isoliert testen kannst.
49:01
Denn, und das funktioniert auch, glaube ich, ziemlich gut. Schwierig wird es dann, wenn du die Integration testen möchtest. Wir haben das zum Beispiel so gemacht, dass eben in dieser großen Anwendung hier werden Request auf diese Teilanwendungen, also das war dann slash tools slash Atlas in dem
49:21
Beispiel, dass die eben mit einem Reverse-Proxy durchgereicht werden an den anderen. Und diese Reverse-Proxy-Konfiguration, die haben wir zwar auch getestet, aber das Setup ist schon so kompliziert, dass das irgendwie nicht mehr dass das irgendwie ein bisschen Handarbeit erfordert. Das läuft nicht mehr automatisch auch im Jenkins und so weiter. Also, das einzurichten, das ist irgendwie eine lange Readme geworden, ist aber glücklicherweise auch der kleinste Teil
49:41
davon. Also, alles, was du so in der laufenden Anwendung hast, kannst du, glaube ich, ganz gut wegmocken. Gibt es schon, also ich,
50:01
gibt es Tools, zum Beispiel, um zwei XDBug-Prozessor miteinander zu verheiraten. Gibt es, XDBug kann mehrere Connections machen und im PHP-Storm ist zum Beispiel die Default-Einstellung, dass er nur eine erlaubt. Du kannst aber eine zweite zusätzlich erlauben, kannst dann zwei ID's aufhaben. Das Problem ist einfach nur, dass hier explodiert relativ der Kopf, weil
50:21
das wird zumindest für mich irgendwie zu kompliziert. Also, das versuche ich tunlichst zu vermeiden und die Dinge möglichst isoliert zu testen. Klingt für dich gegen Microservices. Lass dich mal so stehen. Bitte.
50:58
Hier wurde vorgeschlagen, dafür einen Message-Broker einzusetzen und die Nachrichten, die durch ihn durchgehen,
51:02
eben zu kontrollieren. Tatsächlich machen wir das auch auf einer anderen Ebene. Also zum Beispiel dieser User-Service, der verschickt Updates am User über eine Amazon SQS, das Simple Queue Service. Und da schickt er in Production eben in eine Production-Line und in Development eben in eine
51:20
separate Development Queue. Und da kann ich eben mitlesen. Und wenn ich sie gelesen habe, kann ich den konsumierenden Microservice anschmeißen, der sie eben nimmt. Ich kann dann auch mit der Hand neue Nachrichten reinfingieren und gucken, was passiert. Also, wenn ich tatsächlich diese Integration auf der Message-Ebene testen möchte, dann funktioniert das sehr gut. Und ich wüsste auch gar nicht, wie man das allein, damit du die autonom halten kannst. Die sollen ja nicht, es soll ja nicht dein
51:42
System kaputtgehen, wenn ein Service gerade nicht antwortet oder so was. Deshalb, finde ich, ist es fast schon Pflicht, irgendwie eine Queue zu benutzen. Und dann landet man eben schnell bei diesen Modellen. Und da kann man, glaube ich, auch ganz gut reingucken. Zentrales Logging, sagst du, lässt sich da auch gut machen.
52:01
Da gibt es, glaube ich, so viele Logging-Lösungen. Eine von vielen, ja. Ich sehe keine weiteren Fragen mehr. Dann würde ich mich nochmal bedanken. Wem später noch was einfällt, der findet mich in den Pausen wahrscheinlich am Kaffee stand. Und für Leute mit
52:21
ähnlichen sozialen Phobien wie ich, die können mich ja auch im Twitter-Händel hier anschreiben. Dann wünsche ich euch noch viel Spaß auf der Frostcom. Und auf zur Kantine!