Auf einen Blick
- Die Entwicklungssicht ist eine der sechs Architektur-Sichten (neben Geschaefts-, Kontext-, Logischer, Daten- und Verteilungs-/Laufzeitsicht) und behandelt Werkzeuge, Entwicklungsrichtlinien, Codeverwaltung, Konfiguration und den Bau der Anwendung.
- Zentrales Ordnungsprinzip: Umgebungen/Landschaften (Entwicklung lokal, Entwicklung/Test/Produktion zentral, Pre-Production) und die vier Werkzeug-Bausteine Versionsmanagement (Release), Versionsmanagement (Konfiguration), Konfigurationsmanagement und Pipeline.
- Kernprinzip: Release und Konfiguration werden strikt getrennt und variieren unabhaengig - Releases sind umgebungsagnostisch, Konfiguration ist umgebungsspezifisch.
- Versionsmanagement ist die einzige Quelle der Wahrheit: ein Release muss vollstaendig aus einem Commit reproduzierbar sein (Code, DB-Schema, versionsabhaengige Daten, Tools, Infrastruktur).
- Die CI/CD-Pipeline (Continuous Integration, Continuous Delivery, Continuous Deployment) automatisiert Build und Deployment mit dem Ziel < 1 Tag vom Commit bis zur Produktion.
- Konfigurationsmanagement schafft vergleichbare Umgebungen (gegen das Snowflake-Antipattern) via Virtualisierung, Container und Infrastructure as Software.
Kernkonzepte
1. Einordnung: Die sechs Architektur-Sichten
Die Architektur wird in sechs Sichten beschrieben. Geschaeftssicht: Geschaeftsprozesse, Geschaeftsobjekte, Akteure, Organisation, fachliche Modelle und Regeln. Kontextsicht: Akteure, andere Systeme, Datenfluesse. Logische Sicht: Kernanwendungsfaelle, Modellierung, Aufteilung in Module, Modulabhaengigkeiten. Entwicklungssicht: Werkzeuge, Entwicklungsrichtlinien, Verwaltung des Codes, Konfiguration, Bau der Anwendung. Datensicht: technisches Datenmodell, Datenaustausch/Integration. Verteilungs- und Laufzeitsicht: Verteilung auf Infrastruktur, Hintergrundverarbeitung, Performanz und Skalierung, Betrieb. Dieses Kapitel behandelt die Entwicklungssicht.
2. Validierung vs. Verifikation
Zwei Leitfragen begleiten den gesamten Entwicklungsprozess. Validierung beantwortet: Baue ich das Richtige? (Bezug zu Zielen und Anforderungen). Verifikation beantwortet: Baue ich es richtig? (Bezug zu Design, Implementierung und Tests). Der Prozess laeuft von Zielen ueber Anforderungen, fachliches Design, technisches Design bis zur Implementierung; auf jeder Stufe finden Validierung und Verifikation statt (bis hin zu Entwicklungstests, funktionalen Tests und Akzeptanztest).
3. Umgebungen (Landschaften)
Man arbeitet mit mehreren Umgebungen. Entwicklung (Lokal): Coding und Entwickler-Tests auf den Endgeraeten der Entwickler, mit haeufigen Deployments, Ausprobieren von Aenderungen und Testen. Entwicklung (Zentral): kontrollierte Deployments und Testen. Test (Zentral): Testen. Produktion (Zentral): Deployments nach Freigabe, Nutzung durch Anwender. Pre-Production (Zentral): Tests von Bugfixes und dringenden Aenderungen sowie Umgebungen konfigurieren/Konfiguration aendern.
4. Was muss organisiert werden - die vier Bausteine
Vier Aufgaben und ihre Loesungswerkzeuge. Releases muessen konsistent, schnell und getestet auf die Produktion gelangen -> Pipeline. Es braucht eine Quelle der Wahrheit fuer Code und Konfiguration bei mehreren gleichzeitig verwendeten Versionen (Release-Code, Umgebungen), mit Wiederholbarkeit und Nachvollziehbarkeit -> Versionsmanagement. Umgebungen muessen vergleichbar, einfach und wiederholbar aufgesetzt und verwaltet werden -> Konfigurationsmanagement. Zusammen ergeben Versionsmanagement (Release), Versionsmanagement (Konfiguration), Konfigurationsmanagement und Pipeline die Elemente der Entwicklungssicht.
5. Bestandteile einer Konfiguration
Zur Konfiguration gehoeren: verwendete Infrastruktur (Server, virtuelle Maschinen/VM, Laufzeitumgebung, Datenbank); Parameter der Infrastruktur (Netzwerk, Speicher und CPU von VMs, Start-/Stopp-Skripte, Logging-Einstellungen); Verbindungsparameter (Ports, URLs, Passwoerter, Zertifikate); Entwicklungsumgebung (Compiler, IDE, Tools); Information ueber die Art der Umgebung (Entwicklung/Test/Produktion); Feature Toggles (Schalter, die Code an-/ausschalten und damit das Verhalten aendern koennen).
6. Bestandteile eines Releases
Zum Release gehoeren: Quellcode; Abhaengigkeiten (Bibliotheken); eingebundene Dateien (Bilder, Texte, releaseabhaengige Daten); Datenbankschema (starke Abhaengigkeit mit dem Code - jedes Datenbankobjekt hat eine Repraesentation im Code); releaseabhaengige Daten (in der Datenbank oder im Dateisystem, z.B. Wertelisten, Entscheidungstabellen); releaseabhaengige Dokumentation. Wichtig fuer die Trennung: Releases sind umgebungsagnostisch, Konfiguration ist umgebungsspezifisch.
7. Trennung von Release und Konfiguration
Die Versionen von Release und Konfiguration variieren unabhaengig voneinander. Die Versionen der Konfiguration sind umgebungsspezifisch (verwalten die Unterschiede zwischen DEV/TEST/PROD). Die Versionen der Releases sind umgebungsagnostisch (ein Release muss auf jeder Umgebung ausfuehrbar sein). Beispiele: Aenderung der Konfiguration (Firewall-Regeln, Speichergroesse, Toggle) bei gleichem Release; Aenderung des Releases bei gleicher Konfiguration. Umgebungsabhaengige Daten haben im Release nichts verloren - sonst kann man einen Produktionsfehler lokal nicht reproduzieren.
8. Qualitative Anforderungen an die Entwicklungssicht
Vollstaendigkeit: eine beliebige Version soll vollstaendig aus einem Repository gebaut werden koennen (eigener Code und Bibliotheken, Datenbankschema, versionsabhaengige Daten, Tools wie Compiler/Build/Testautomatisierung, Infrastruktur/Software/Services/Netzwerkkonfiguration). Reproduzierbarkeit (betrifft Konfiguration und Release). Nachvollziehbarkeit (wichtig fuer die Fehlersuche). Sicherheit (Angriffe auf die Supply Chain sind sehr effektiv).
9. Quantitative Anforderungen an die Entwicklungssicht
Haeufige Lieferungen: mindestens 1 Lieferung pro Arbeitstag moeglich. Schnelle Lieferungen: < 1 Tag vom Commit im Repository bis zum Deployment in der Produktion. Stabile Lieferungen: < 15% Fehlschlagrate (aufgabenabhaengig) und < 1 h fuer Rollback. Keine Downtime: auch im Fall eines Rollbacks.
10. Grundlegende Operationen des Versionsmanagements
Commit: Aenderung mit aussagekraeftigem Kommentar in das Repository schreiben (z.B. [Fix] #3756 - Discount for Iceland). Check Out: einen bestimmten Stand auschecken. Branch: einen Zweig (z.B. My_branch) erstellen, um parallel und risikofrei zu arbeiten. Merge: einen Zweig wieder in einen anderen (z.B. main) zusammenfuehren.
11. Zentrales vs. dezentrales Repository
Zentrales Repository (Beispiel Subversion): alle Entwickler committen direkt in ein zentrales Repository. Dezentrales Repository (Beispiel Git): jeder Entwickler hat ein lokales Repository, das zusaetzlich mit einem zentralen Repository synchronisiert wird. Die Welt hat sich auf Git und Freunde geeinigt, wegen: Versionskontrolle fuer den einzelnen Entwickler lokal, Offline-Arbeiten/Netzwerkunabhaengigkeit, schnelles Arbeiten (volle Speicherung bei jedem Commit) und Sicherheit durch Checksummen.
12. Arbeitsablauf im Team mit dezentralen Repositories
Typischer Ablauf: 1. Pull, um den aktuellen Stand lokal zu haben. 2. Code aendern, bis alle Tests gruen sind. 3. Kollegen aktualisieren das zentrale Repository. 4. Erneut Pull, um die Aenderungen der Kollegen lokal zu bekommen. 5. Nochmal bauen und Tests laufen lassen. 6. Aenderungen ins zentrale Repository pushen (Commit oder Pull Request). 7. Bauen, Pruefen, Testen ueber die CI/CD-Pipeline. 8. Benachrichtigung ueber Pruefungen und Tests. 9. Kollegen integrieren die Aenderungen.
13. Trunk Based
Ein Hauptzweig (Trunk/Main); Commits der Entwickler gehen direkt in den Hauptzweig; Lieferung erfolgt aus dem Hauptzweig (z.B. 1.3.0-RC01 -> RC02 -> RELEASE). Voraussetzung: der Hauptzweig muss immer gesund (potenziell in die Produktion lieferbar) sein; im Fehlerfall werden Korrektur und alle weiteren Commits mitgeliefert. Nachteile: Qualitaetssicherung (Testen, Code Checks, Code Review) erst nach dem Commit im Hauptzweig (Verseuchung); keine Zuordnung der Commits zu Aufgaben/Features.
14. Feature-Zweige
Fuer jedes Feature bzw. jeden Bugfix ein eigener Zweig (z.B. [REQ] NGHR-2834, [FIX] NGHR-3042). Vorteile: der Zweck jedes Commits ist im Versionsmanagement sichtbar; ohne Risiko etwas ausprobieren; Wechsel zwischen mehreren Aufgaben einfach und klar; Heimat fuer die Qualitaetssicherung im zentralen Repository vor dem Zusammenfuehren eines Feature-Zweigs. Nachteil: Probleme beim Zusammenfuehren, wenn zu selten in den Hauptzweig committet wird.
15. Git-Flow
Mehrere langlebige Zweige: Development, Release, Hotfixes, Main (Trunk). Hauptsaechlich wird in den Entwicklungszweig committet; Stabilisierung (Bugfixes) erfolgt im Release-Zweig, waehrend die Entwicklung am naechsten Release ungestoert weitergehen kann. Dringende Problembehebungen laufen in Hotfix-Zweigen. Der letzte Commit im Hauptzweig ist die Produktivversion. Indikationen: Team kann den Hauptzweig nicht jederzeit gesund halten; laengere Testphase noetig; organisatorische Gruende (Release-Zyklen, Genehmigungen). Nachteile: Komplexitaet; Auseinanderentwicklung von Release- und Entwicklungszweig (Problem beim Zusammenfuehren). Merke: Zusammenfuehren nicht vergessen.
16. Umgebungszweige (Antipattern)
Idee: ein Zweig je Umgebung (DEV/TEST/PROD). Das klingt vernuenftig, ist aber ueberfluessig: es darf keinen Unterschied geben, ob ein Release in DEV/TEST/PROD laeuft; die Commits im Test- und Produktionszweig sind reine Kopien; Konfigurationsdaten (z.B. Datenbankverbindung) in ein Release zu codieren ist ein Antipattern. Besser: Commit-ID (z.B. a43de74) oder Versionsbezeichner (z.B. 3.4.2-RC03) in das Release aufnehmen; der Inhalt der Commits ist identisch, alles andere waere falsch.
17. Mehrere Releases unterhalten
Bisher wurde angenommen, es gebe nur ein produktives Release (funktioniert bei Inhouse-System oder Cloud-Service). Bei an Kunden ausgelieferter Software funktioniert das nicht: Kunden vermeiden Upgrades (oft aus guten Gruenden), es gibt Wartungszusagen des Herstellers und Bugfixes, insbesondere Sicherheitsfixes. Loesung: fuer jedes Release ein Zweig; nach jeder Auslieferung muss entschieden werden, was in welche Zweige uebernommen wird (alle Aenderungen zusammenfuehren oder selektive Commits).
18. Feature Toggles
Noch nicht fertiggestellte Funktionalitaeten werden mit einem Schalter versehen. So kann man unfertige Aenderungen liefern (technischer Go-Live) und sie spaeter aktivieren (Business Go-Live); ein Toggle hat einen Zustand ON/OFF. Vorteile: Entkopplung von Deployment und Verhaltensaenderung; unfertige Entwicklungen/Tests blockieren das Release-Deployment nicht; partielle Aktivierung (z.B. fuer eine Untermenge von Anwendern); schnelles Zurueckrollen bei Fehlschlag; Versionsmanagement ohne Release-Zweige. Nachteile: Verwaltung der Toggles auf allen Umgebungen macht das Konfigurationsmanagement komplexer; Nachvollziehbarkeit schwieriger (der Code allein ist nicht mehr fuer das Verhalten verantwortlich); Risiko durch falsche Feature-Konfiguration; Disziplin noetig fuer den Toggle-Lebenszyklus von der Erstellung bis zum Ausbauen.
19. Datenbankentwicklung im Versionsmanagement
Die Datenbank haengt am Release: das Datenbankschema (jede Tabelle ist im Code durch Objekte/Datenstrukturen repraesentiert, Datenzugriff erfolgt ueber Datenbankbefehle im Code) und Daten, deren Werte im Code zur Steuerung abgefragt werden (Beispiel: Kunden in Kategorien A, B, C, die in die Rabattberechnung eingehen). Wenige Plattformen unterstuetzen kombinierte Code- und Datenbankentwicklung - ein notorisches Problem bei Produkten mit Customizing und Code-Erweiterungen; eine Ausnahme ist ABAP (SAP) mit Versionskontrolle von Code, Datenbankschema und Daten (Customizing).
20. Datenbankentwicklung - das Rezept (Migrationsskripte)
Das Datenbankschema wird ueber Skripte entwickelt (nicht aus dem Code generieren lassen). Die Skripte werden mit dem Code unter Versionskontrolle gestellt. Jede Aenderung der Datenbank ist ein Skript, das die Differenz zur bestehenden Datenbank beschreibt. Bei jedem Deployment (DEV/TEST/PROD) werden nur die Skripte ausgefuehrt, die auf dieser Umgebung noch nicht ausgefuehrt wurden. Wichtig: bestehende Skripte duerfen nie mehr geaendert werden. Toolunterstuetzung: Skripte pro Release ablegen (SQL, JSON, XML); eine Tabelle in der Datenbank protokolliert die bereits installierten Skripte; das Tool fuehrt die noch benoetigten Skripte bei Programmstart aus. Beispiele: Liquibase oder Flyway.
21. Versionsmanagement und Projektmanagement
Projektmanagement-Artefakte sind Anforderungen (Use Cases, User Stories), Testfaelle/Testprotokolle/Testbefunde und Meldungen aus der Produktion. Codeaenderungen beziehen sich immer auf diese Artefakte
- Grundsatz: Keine Aktion ohne Ticket. Der Bezug wird hergestellt im Artefakt (als Zielversion/Lieferversion/Version des Auftretens) und im Versionsmanagement (jeder Commit und jeder Branch enthaelt die ID des Artefakts im Titel/Kommentar, z.B. NGHR-2748
- Fehler: Mitarbeiterstatus aendert sich nicht bei Deaktivierung des Mitarbeiters).
22. Versionsmanagement richtig aufsetzen und anwenden
Aufsetzen: als einzige Quelle der Wahrheit (ein Release vollstaendig aus einem Commit erzeugbar); fuer alles Releaseabhaengige (Code, Datenbank, Dokumentation, ggf. Spezifikation/Testfaelle/Testergebnisse); umgebungsunabhaengig; definiert (A fool with a tool is still a fool - passendes Konzept ausarbeiten, vereinbaren, dokumentieren, befolgen); einfach (der Bau darf nicht zwei Tage dauern). Anwenden: die Werkzeuge beherrschen; haeufig committen (alle 1-2 Stunden, vorher Merge aus dem zentralen Repository); haeufig zusammenfuehren (a merge a day keeps the doctor away); aussagekraeftige Commit-Kommentare; aufraeumen (lokale Historie vor dem Zusammenfuehren via Rebase bereinigen, abgeschlossene Feature-Zweige loeschen).
23. Verwendete Bibliotheken / Abhaengigkeiten
Direkte Abhaengigkeiten: welche Bibliothek in welcher Version, sicher aus einem Repository beziehen. Transitive Abhaengigkeiten: Bibliotheken verwenden wiederum Bibliotheken. Versionskonflikte sind moeglich (z.B. Bibliothek in Version 3 und 4 eingebunden) und muessen aufgeloest werden. Unterschiedliche Verwendungen/Ziele: nur zum Kompilieren, nur zum Testen, nur zur Laufzeit. Ausserdem: pruefen, ob neue Versionen vorhanden sind bzw. Sicherheitsprobleme behoben wurden (pruefen, anzeigen, aktualisieren).
24. Semantic Versioning (semver.org)
Regelwerk fuer die Namensgebung von (Bibliotheks-)Versionen, Schema MAJOR.MINOR.PATCH (Beispiel 1.10.0 -> 1.10.1 -> 1.11.0 -> 2.0.0 -> 2.1.0). Major: inkompatible Aenderungen der API. Minor: rueckwaertskompatibel hinzugefuegte Funktionalitaet. Patch: rueckwaertskompatible Problembehebungen. Verwendung: als Kompatibilitaetsinformation und zum Aufloesen von Versionskonflikten (dazu weitere Kriterien wie Naehe zum Stamm im Baum der transitiven Abhaengigkeiten).
25. Abhaengigkeiten anzeigen und aktualisieren (Maven)
mvn dependency:tree zeigt direkte und transitive Abhaengigkeiten mit Version und Ziel; das Ziel Kompilieren schliesst Test und Laufzeit ein, das Ziel Test schliesst Kompilieren ein, aber Laufzeit aus. mvn versions:display-dependency-updates zeigt verfuegbare Updates. mvn versions:use-latest-releases aktualisiert. Automatisierung durch Renovate-Bots: Pruefung auf neue Releases, Erzeugung eines Pull Requests mit den Aenderungen, Review durch Entwickler/Architekt.
26. Zentrales Abhaengigkeitsmanagement (JAR Hell)
Wird die Version der Abhaengigkeiten in jedem Projekt einzeln definiert, entsteht JAR Hell (inkonsistente Versionen ueber die Projekte). Loesung: Versionen zentral definieren, damit sie konsistent sind. Ein Parent legt die zu verwendenden Versionen fest (dependencyManagement mit expliziter Version, transitive Abhaengigkeiten einschliessen); die Module referenzieren den Parent und uebernehmen die Version, definieren ihre Abhaengigkeiten also ohne Versionsnummer. Beispiel: Maven Multi-Modul-Projekt NGHR mit Parent-pom.xml (modules: common, employee, authorization, payroll) und Modul-pom.xml, die auf den Parent verweist.
27. Pipeline - Bestandteile (lokaler und nicht lokaler Teil)
Lokaler Teil: Build (Kompilieren, Testen, Paketieren; Quellcode -> ausfuehrbarer Code; nicht zusammengefuehrter Code) und Deploy (Installieren und Starten in der lokalen Umgebung, wenn moeglich). Nicht lokaler Teil: Build (mit zusammengefuehrtem Code) und Deploy (Installieren und Starten in zentraler Umgebung).
28. Lokaler Teil - Maven Build-Phasen
mvn compile: Uebersetzen des Quellcodes in Binaercode (Quellen in /src/main/java und /src/main/resources, Ergebnis in /target/classes). mvn test: Kompilieren und Ausfuehren aller JUnit-Tests (Test-Quellen in /src/test, Ergebnis in /target/test-classes, Testergebnisse in /target/surefire-reports). mvn package: Zusammenstellen des Installationspakets (jar in /target, optional mit Abhaengigkeiten). Optional mvn install: Paket ins lokale Maven-Repository (HOME/.m2/repository). Optional mvn deploy: Paket ins zentrale Maven-Repository - das ist KEIN Deployment in eine Umgebung, sondern das Artefakt kann von Kollegen als Abhaengigkeit genutzt werden. /src ist unter Versionskontrolle, /target (u.a. classes, generated-sources, surefire-reports) ist ausgeschlossen.
29. CI/CD Pipeline - Ueberblick
Die CI/CD-Pipeline wird fuer jede abgeschlossene Entwicklung durchlaufen: Lokale Entwicklung abgeschlossen -> Continuous Integration (CI) -> Continuous Delivery (CD) -> (Continuous Deployment) -> neues Release in der Produktion. Entwicklung abschliessen erfolgt ueber einen Pull Request. Der Zielzweig ist geschuetzt (Branch Protection): keine direkten Commits moeglich, um zu vermeiden, dass Code mit ungenuegender Qualitaet in den Zweig kommt (Verseuchung).
30. Continuous Integration (CI)
Kontinuierliche Integration von Entwicklungen in den Zielzweig. Ausloeser: Pull Request. Schritte (koennen variieren): 1. Formatierung, 2. statische Code Checks, 3. Kompilieren, 4. Unit- und Integrationstests, 5. Code Review, 6. wenn alle Checks bestanden: Merge. Bei Erfolg wird die Entwicklung im Zielzweig committet.
31. Continuous Delivery (CD)
Kontinuierliche Lieferung der Entwicklung in das Testsystem (nicht in die Produktion). Ausloeser: jeder Commit im Zielzweig. Schritte (koennen variieren): 1. Kompilieren, 2. Unit- und Integrationstests, 3. Paketieren, 4. Deployment Entwicklungsumgebung, 5. optional weitere automatische Tests auf der Entwicklungsumgebung, 6. Deployment Testumgebung (automatisch, zeitgesteuert oder manuell ausgeloest). Ergebnis bei Erfolg: das Release steht auf der Testumgebung zur Verfuegung.
32. Warum bei CD nochmals kompilieren und testen (Arten von Versionskonflikten)
Obwohl der Code in CI schon kompiliert/getestet und der Merge erfolgreich war, kann es noch Konflikte geben. Versionskonflikte: garantiert keine (sonst waere der Merge nicht erfolgreich gewesen). Syntaxkonflikte: der Compiler kann nicht kompilieren, z.B. weil eine Methode fehlt oder eine andere Signatur hat als vom Zielzweig erwartet - niemand garantiert, dass die Aenderung im Pull Request aktuell ist. Semantische Konflikte: es kompiliert, aber die Funktion ist nicht wie erforderlich (z.B. Parameter/Rueckgabewert anders verwendet als erwartet). Laufzeitunterschiede: kompiliert und funktioniert, aber das Laufzeitverhalten ist anders (Performanz, Ressourcenverbrauch).
33. Continuous Deployment
Kontinuierliche Lieferung in die Produktionsumgebung. Ausloeser: Continuous Delivery erfolgreich. Ergebnis: automatisches Deployment auf der Produktionsumgebung. Oft nicht moeglich oder nicht sinnvoll; setzt 100% Testautomatisierung voraus. Merke die Abgrenzung: Continuous Delivery liefert bis in die Testumgebung, Continuous Deployment automatisch bis in die Produktion.
34. Pipeline - Bemerkungen
Die CI/CD-Pipeline beschleunigt den Entwicklungsprozess (zwei Tage manuelle Integration/Deployment sind nicht akzeptabel; Ziel < 1 Tag vom Commit zum Deployment in der Produktion). Sie ist eine Investition (Know-how und Zeit, Abstimmung im gesamten Projekt inklusive Anwender, Abhaengigkeit vom Versionsmanagement erschwert spaetere Aenderungen). Testautomatisierung ist entscheidend: Fehler schneller zum Anwendertest zu liefern bringt nichts; automatische Rueckmeldung an Entwickler ueber Fehlschlaege; Ziel < 15% Fehlschlagquote.
35. Konfigurationsmanagement - Vorgehen und Ziele
Vorgehen: Unterschiede zwischen den Umgebungen minimieren und die verbleibenden Unterschiede richtig verwalten. Ziele: Vergleichbarkeit (alle Umgebungen verhalten sich gleich; Antipattern Snowflake - alle Schneeflocken sind aehnlich, aber keine ist exakt gleich, z.B. jahrelang haendisch gewartete Server oder Entwickler-Endgeraete vs. installierter Server). Wiederholbarkeit (Aufsetzen ist wiederholbar und damit wiederherstellbar; im Idealfall braucht man Konfigurationsdateien, Backup der persistierten Daten und Bare Metal: Server, Betriebssystem, Speicherplatz). Einfachheit (eine oder wenige Datenquellen fuer Konfigurationsdaten, dokumentierte Skripte zum Aufsetzen einer Umgebung).
36. Vergleichbare Umgebungen: Klassisch, Virtualisierung, Container
Klassisch: Anwendung, Bibliotheken, Server/Datenbank direkt auf Betriebssystem und Hardware - Schwachstellen: unterschiedliche Versionen und Konfigurationen, deaktivierte Komponenten/alte Versionen hinterlassen Spuren, Komponenten ggf. nicht unter Kontrolle des Teams, Interferenz zwischen Anwendungen -> Schneeflocke sehr wahrscheinlich. Virtualisierung (VM auf Hypervisor): Image speicher-/weitergeb-/wiederherstellbar, aus Skripten erzeugbar (Versionskontrolle), OS waehlbar, volle Isolation zur Laufzeit; aber schwergewichtig (jede VM hat vollen OS-Kernel, Image mehrere GB, minimale VM 2 CPU/8 GB, Boot-Zeit ca. 1 Minute). Container (auf Container Engine): Definitionsdatei (Versionskontrolle) -> Image -> gestartet -> Container; Image enthaelt Laufzeit, Tools, Infrastruktur; leichtgewichtig (nur einmal voller OS-Kernel, Mini-OS nutzt den OS-Kernel des Rechners), Mehrfachinstanziierung, Create once run everywhere, unabhaengig vom Infrastrukturprovider; aber keine vollstaendige Isolierung. Docker ist die bekannteste Loesung.
37. Lokale Entwicklungsumgebung
Wenig Abhaengigkeit von der IDE: Abhaengigkeit von einer IDE(-Version) vermeiden (in Jahrzehnten denken
- IDE noch verfuegbar? Lizenzbedingungen geaendert?); Ausnahme: das Softwareprodukt gibt eine IDE vor; man darf eine IDE mit einheitlichen Formatierungsregeln, Code Checks und Plugins vorgeben. Kommandozeile, ausschliesslich: Kompilieren, Testausfuehrung und Bauen muessen immer von der Kommandozeile moeglich sein (ebenso Versionskontrolle, Datenbankschema, Dateisystem)
- Voraussetzung fuer Automatisierung. VM oder Container, da jeder Laptop eine Schneeflocke ist: das Team definiert eine lokal laufende VM, oder Container mit einer IDE, die eine HTTP-Schnittstelle bietet.
38. Unterschiede verwalten - Regeln fuer Konfigurationsdaten
Konfigurationsdaten unter Versionskontrolle: Nachvollziehbarkeit, Zuruecksetzen bei Problemen, Aenderungsprozess ggf. mit Qualitaetskontrolle (Fehler bei Konfigurationsaenderungen koennen gravierend sein, z.B. Pull Request mit Code Review). Versionskontrolle fuer Konfiguration und Code trennen, damit sich beide unabhaengig entwickeln koennen (Code: definierter Stand auf alle Umgebungen; Konfiguration: Verwaltung der Unterschiede). Separat fuer jede Umgebung (DEV/TEST/PROD): oberste Ebene der Verzeichnishierarchie ist die Umgebung. Versionierung pro Umgebung entweder ueber Option 1 (eigenes Repository) oder Option 2 (Zweig im Repository).
39. Geheimnisse (Secrets)
Geheimnisse (Passwoerter, Zertifikate, Tokens) duerfen nie unverschluesselt in der Versionskontrolle abgelegt werden
- am besten legt man sie dort gar nicht ab. Cryptographic Failures nimmt Platz zwei der OWASP Top 10:2021 ein. Optionen: Keyvault (bevorzugt
- sicher, zentrale Verwaltung, Protokollierung der Zugriffe, Lebensdauer/Erneuerung; als Feature von Cloud-Providern oder als eigene Anwendung), Umgebungsvariablen, verschluesselt in der Versionskontrolle.
40. Konfiguration auf Umgebungen bringen
Konfigurationsdaten liegen vor als Umgebungsvariablen, Dateien (Property-, XML-, YAML-Dateien), Eintraege in der Datenbank oder ueber Pflege per UI/CLI bei IaaS/PaaS. Herausforderungen: Verteilen der Daten auf die Umgebungen erfordert Skripte oder Tools (wenn eine Komponente nur Pflege ueber UI ermoeglicht, ist Automatisierung kaum sinnvoll); ggf. ist zeitgleiche Aenderung in vielen Zielen noetig (Beispiel: Aktivierung eines Toggles in einem verteilten System mit 12 Microservices und 28 Instanzen).
41. Konfigurationsservice
Fuer Anwendungen, die auf Komponenten in getrennten Laufzeiten verteilt und u.U. mehrfach instanziiert sind und eine konsistente Konfiguration ueber alle Instanzen brauchen. Jede Instanz kommt mit minimaler lokaler Konfiguration aus: URL fuer den Konfigurationsservice und Typ der Umgebung (DEV/TEST/PROD); der Konfigurationsservice bezieht die Daten aus dem Versionsmanagement. Beispiel: Spring Cloud Config. Funktioniert fuer die selbst geschriebenen Anwendungen, nicht fuer die Infrastruktur (Web-Server, DB, Netzwerk).
42. Infrastructure as Software
Die Anwendung benoetigt Infrastruktur (Netzwerk, Storage, Mailservice, Datenbank, Berechtigungen, Secrets, Web-Server, Logging); IaaS/PaaS-Cloud-Anbieter (Google Cloud, AWS, Azure) haben diese Infrastruktur. Manuelle Konfiguration im Admin-Portal ist problematisch (schon kleine Setups >> 100 Datenpunkte; Aenderungen schwer sicher/schnell, Vergleich DEV-TEST-PROD aufwendig, keine Nachvollziehbarkeit/Wiederherstellung, Qualitaetssicherung und Policies nicht erzwingbar, Updates schwierig). Infrastructure as Software (Beispiel Terraform): deklarative Konfiguration in Dateien (was, nicht wie), fuer diverse Zielplattformen, unter Versionskontrolle; die Pipeline laeuft nach Commit oder Pull Request mit Code Review; die CLI des Cloud-Anbieters verarbeitet die Dateien automatisch, prueft Policies, generiert/injiziert/vernichtet Secrets bei Bedarf. Damit sind die Ziele Vergleichbarkeit, Wiederholbarkeit und Einfachheit erreichbar.
Merksätze
Klausur-Stichworte (aus der Zusammenfassung)
Theißen hat gesagt: alle prüfbaren Themen tauchen als Stichwort in den Zusammenfassungs-Folien auf. Genau diese Stichworte stehen hier.
- Entwicklungssicht: Umgebungen, Werkzeuge, Prozesse
- Release und Konfiguration: Bestandteile, Trennung von Release und Konfiguration
- Anforderungen an die Entwicklungssicht: qualitativ, quantitativ
- Versionsmanagement: Grundlegende Operationen, Zentrales und Dezentrales Repository, Arbeitsablauf
- Versionsmanagement (Release): Trunk-Based, Feature-Zweige, Git Flow, Feature Toggles, Datenbankentwicklung, Verbindung zum Projektmanagement
- Versionsmanagement (Abhaengigkeiten): Direkte und transitive Abhaengigkeiten, Versionskonflikte, Verwendungen (kompilieren/testen/ausfuehren), Semantic Versioning, Zentrales Abhaengigkeitsmanagement
- Pipeline - Lokaler Teil: Schritte, Dateisystem
- Pipeline - Nicht-lokaler Teil: CI (Continuous Integration) mit Pull Request, Branch Protection, Schritte; CD (Continuous Delivery) mit Schritten; Continuous Deployment
- Pipeline: Arten von Versionskonflikten
- Konfigurationsmanagement - Vergleichbare Umgebungen: Traditionelles Deployment, Virtuelle Maschinen, Container, Lokale Entwicklungsumgebungen
- Konfigurationsmanagement - Unterschied verwalten: Versionskontrolle, Trennung vom Release, IT-Sicherheit
- Konfigurationsmanagement - Konfiguration auf Umgebung bringen: Dateien, Umgebungsvariablen, Datenbank, Manuelle Pflege (UI/CLI), Konfigurationsservice, Infrastructure as Code
Übungsfragen
F1 Welche sechs Architektur-Sichten werden unterschieden, und welche Aspekte behandelt die Entwicklungssicht?
Es gibt die Geschaeftssicht, Kontextsicht, Logische Sicht, Entwicklungssicht, Datensicht sowie die Verteilungs- und Laufzeitsicht. Die Entwicklungssicht behandelt die Werkzeuge, die Entwicklungsrichtlinien, die Verwaltung des Codes, die Konfiguration und den Bau der Anwendung.
F2 Was ist der Unterschied zwischen Validierung und Verifikation?
Validierung beantwortet die Frage Baue ich das Richtige? und bezieht sich auf Ziele und Anforderungen. Verifikation beantwortet die Frage Baue ich es richtig? und bezieht sich auf Design, Implementierung und Tests. Beide finden auf jeder Stufe des Entwicklungsprozesses statt.
F3 Warum werden Release und Konfiguration getrennt verwaltet, und wie unterscheiden sie sich bezueglich der Umgebungen?
Code und Konfiguration muessen sich unabhaengig voneinander entwickeln koennen. Releases sind umgebungsagnostisch, das heisst ein Release muss auf jeder Umgebung ausfuehrbar sein. Konfigurationen sind umgebungsspezifisch und verwalten die Unterschiede zwischen DEV, TEST und PROD. Umgebungsabhaengige Daten in ein Release zu codieren ist ein Antipattern, sonst kann man einen Produktionsfehler lokal nicht reproduzieren.
F4 Nennen Sie die qualitativen und quantitativen Anforderungen an die Entwicklungssicht.
Qualitativ: Vollstaendigkeit (jede Version vollstaendig aus einem Repository baubar), Reproduzierbarkeit, Nachvollziehbarkeit und Sicherheit (Supply-Chain-Angriffe sind sehr effektiv). Quantitativ: haeufige Lieferungen (1 pro Arbeitstag), schnelle Lieferungen (< 1 Tag vom Commit bis zur Produktion), stabile Lieferungen (< 15% Fehlschlagrate, < 1 h Rollback) und keine Downtime, auch bei Rollback.
F5 Warum hat sich die Praxis auf dezentrale Repositories wie Git geeinigt?
Weil Git Versionskontrolle fuer den einzelnen Entwickler lokal erlaubt, Offline-Arbeiten und Netzwerkunabhaengigkeit ermoeglicht, schnelles Arbeiten durch volle Speicherung bei jedem Commit bietet und Sicherheit durch Checksummen gewaehrleistet.
F6 Vergleichen Sie Trunk Based und Feature-Zweige hinsichtlich ihrer Vor- und Nachteile.
Bei Trunk Based committen alle Entwickler in einen Hauptzweig, aus dem geliefert wird; Vorteil ist die Einfachheit, Nachteil ist, dass Qualitaetssicherung erst nach dem Commit im Hauptzweig stattfindet (Verseuchung) und es keine Zuordnung der Commits zu Aufgaben gibt. Bei Feature-Zweigen gibt es je Feature/Bugfix einen Zweig; Vorteile sind sichtbarer Commit-Zweck, risikofreies Ausprobieren, einfacher Aufgabenwechsel und Qualitaetssicherung vor dem Zusammenfuehren; Nachteil sind Merge-Probleme, wenn zu selten in den Hauptzweig committet wird.
F7 Was kennzeichnet Git-Flow, und in welchen Situationen ist es indiziert?
Git-Flow nutzt mehrere Zweige (Development, Release, Hotfixes, Main); hauptsaechlich wird in den Entwicklungszweig committet, Stabilisierung erfolgt im Release-Zweig, dringende Fixes in Hotfix-Zweigen, und der letzte Commit im Hauptzweig ist die Produktivversion. Es ist indiziert, wenn das Team den Hauptzweig nicht jederzeit gesund halten kann, eine laengere Testphase noetig ist oder organisatorische Gruende wie Release-Zyklen bestehen. Nachteile sind Komplexitaet und die Auseinanderentwicklung von Release- und Entwicklungszweig.
F8 Warum gelten Umgebungszweige (je ein Zweig fuer DEV/TEST/PROD) als Antipattern?
Weil es keinen Unterschied geben darf, ob ein Release in DEV, TEST oder PROD laeuft; die Commits in Test- und Produktionszweig waeren nur Kopien und Konfigurationsdaten in ein Release zu codieren ist ein Antipattern. Besser ist es, eine Commit-ID oder einen Versionsbezeichner in das Release aufzunehmen; der Inhalt der Commits muss identisch sein.
F9 Was sind Feature Toggles und welche Vor- und Nachteile bringen sie mit sich?
Feature Toggles sind Schalter, mit denen noch nicht fertige Funktionalitaeten versehen werden, sodass man unfertige Aenderungen liefern (technischer Go-Live) und spaeter aktivieren kann (Business Go-Live). Vorteile: Entkopplung von Deployment und Verhaltensaenderung, unfertige Entwicklungen blockieren das Deployment nicht, partielle Aktivierung, schnelles Zurueckrollen, Versionsmanagement ohne Release-Zweige. Nachteile: komplexeres Konfigurationsmanagement, schwierigere Nachvollziehbarkeit, Risiko durch Fehlkonfiguration und noetige Disziplin ueber den Toggle-Lebenszyklus.
F10 Wie sollte die Datenbankentwicklung im Versionsmanagement gehandhabt werden?
Das Datenbankschema wird ueber Skripte entwickelt (nicht aus dem Code generiert), die mit dem Code unter Versionskontrolle stehen. Jede Aenderung ist ein Skript, das die Differenz zur bestehenden Datenbank beschreibt; bei jedem Deployment werden nur die noch nicht ausgefuehrten Skripte angewendet, und bestehende Skripte duerfen nie mehr geaendert werden. Eine Protokolltabelle merkt sich die bereits installierten Skripte; Beispiele fuer Tools sind Liquibase und Flyway.
F11 Was besagt Semantic Versioning und wozu wird es verwendet?
Semantic Versioning folgt dem Schema MAJOR.MINOR.PATCH: Major steht fuer inkompatible API-Aenderungen, Minor fuer rueckwaertskompatibel hinzugefuegte Funktionalitaet und Patch fuer rueckwaertskompatible Problembehebungen. Es dient als Kompatibilitaetsinformation und zum Aufloesen von Versionskonflikten, wobei weitere Kriterien wie die Naehe zum Stamm im Baum der transitiven Abhaengigkeiten herangezogen werden.
F12 Was ist JAR Hell, und wie loest zentrales Abhaengigkeitsmanagement das Problem?
JAR Hell entsteht, wenn jedes Projekt die Versionen seiner Abhaengigkeiten selbst definiert, sodass die Versionen ueber die Projekte inkonsistent werden. Zentrales Abhaengigkeitsmanagement loest das, indem ein Parent die zu verwendenden Versionen zentral festlegt (inkl. transitiver Abhaengigkeiten) und die Module diese ohne eigene Versionsnummer uebernehmen, was zu konsistenten Versionen fuehrt.
F13 Was ist der Unterschied zwischen Continuous Integration, Continuous Delivery und Continuous Deployment?
Continuous Integration integriert Entwicklungen per Pull Request in den Zielzweig (Formatierung, statische Checks, Kompilieren, Tests, Code Review, dann Merge). Continuous Delivery liefert automatisch bis in die Testumgebung, nicht in die Produktion, ausgeloest durch jeden Commit im Zielzweig. Continuous Deployment liefert nach erfolgreicher Continuous Delivery automatisch bis in die Produktion und setzt 100% Testautomatisierung voraus, ist aber oft nicht moeglich oder sinnvoll.
F14 Warum wird in der CD-Pipeline nochmals kompiliert und getestet, obwohl der Code schon in CI geprueft wurde?
Weil trotz erfolgreichem Merge noch Konflikte auftreten koennen: Syntaxkonflikte (der Compiler scheitert, z.B. weil eine Methode fehlt oder eine andere Signatur hat, da niemand garantiert, dass die Pull-Request-Aenderung aktuell ist), semantische Konflikte (es kompiliert, aber Parameter oder Rueckgabewert werden anders verwendet als erwartet) und Laufzeitunterschiede (anderes Laufzeitverhalten wie Performanz oder Ressourcenverbrauch). Versionskonflikte sind garantiert ausgeschlossen, sonst waere der Merge nicht erfolgreich gewesen.
F15 Was bedeutet Branch Protection und welchen Zweck erfuellt sie?
Branch Protection macht den Zielzweig zu einem geschuetzten Zweig, in den keine direkten Commits moeglich sind, sondern nur ueber einen Pull Request. Der Zweck ist zu vermeiden, dass Code mit ungenuegender Qualitaet in den Zweig gelangt (Verseuchung).
F16 Was ist das Snowflake-Antipattern, und welche Ziele verfolgt das Konfigurationsmanagement dagegen?
Das Snowflake-Antipattern beschreibt Umgebungen, die alle aehnlich, aber keine exakt gleich sind, etwa durch jahrelang haendisch gewartete Server. Das Konfigurationsmanagement verfolgt dagegen die Ziele Vergleichbarkeit (gleiches Verhalten der Anwendung auf allen Umgebungen), Wiederholbarkeit (wiederherstellbares Aufsetzen) und Einfachheit (wenige dokumentierte Datenquellen und Skripte).
F17 Vergleichen Sie Virtualisierung und Container als Mittel fuer vergleichbare Umgebungen.
Virtuelle Maschinen erlauben Speichern, Weitergeben und Wiederherstellen von Images, freie OS-Wahl und volle Isolation zur Laufzeit, sind aber schwergewichtig, da jede VM einen vollen OS-Kernel hat (Images mehrere GB, lange Boot-Zeit). Container werden aus einer versionierten Definitionsdatei erzeugt, sind leichtgewichtig (Mini-OS nutzt den OS-Kernel des Rechners), erlauben Mehrfachinstanziierung und Create once run everywhere unabhaengig vom Provider, bieten aber keine vollstaendige Isolierung. Docker ist die bekannteste Loesung.
F18 Wie muessen Geheimnisse (Secrets) behandelt werden, und wie ordnet der Foliensatz das sicherheitsmaessig ein?
Geheimnisse wie Passwoerter, Zertifikate und Tokens duerfen nie unverschluesselt in der Versionskontrolle abgelegt werden, am besten gar nicht dort. Cryptographic Failures nimmt Platz zwei der OWASP Top 10:2021 ein. Als Optionen gelten der bevorzugte Keyvault (sicher, zentrale Verwaltung, Zugriffsprotokollierung, Lebensdauer/Erneuerung), Umgebungsvariablen oder verschluesselte Ablage in der Versionskontrolle.
F19 Was ist ein Konfigurationsservice und wofuer ist er geeignet bzw. nicht geeignet?
Ein Konfigurationsservice liefert eine konsistente Konfiguration ueber viele Instanzen verteilter Komponenten; jede Instanz kommt mit minimaler lokaler Konfiguration aus, naemlich der URL des Konfigurationsservices und dem Typ der Umgebung. Ein Beispiel ist Spring Cloud Config. Er funktioniert fuer die selbst geschriebenen Anwendungen, nicht aber fuer die Infrastruktur wie Web-Server, Datenbank oder Netzwerk.
F20 Was versteht man unter Infrastructure as Software und welche Vorteile hat es gegenueber manueller Konfiguration im Admin-Portal?
Infrastructure as Software bedeutet, die Infrastruktur deklarativ in Dateien zu beschreiben (was, nicht wie), die unter Versionskontrolle stehen und ueber eine Pipeline nach Commit oder Pull Request automatisch verarbeitet werden, ein Beispiel ist Terraform. Gegenueber manueller Portal-Konfiguration (schon kleine Setups mit weit ueber 100 Datenpunkten) bietet es Nachvollziehbarkeit, schnelle sichere Wiederherstellung, erzwingbare Policies und automatische Secret-Verwaltung und macht so Vergleichbarkeit, Wiederholbarkeit und Einfachheit erreichbar.
F21 Wie haengen Versionsmanagement und Projektmanagement zusammen?
Codeaenderungen beziehen sich immer auf Projektmanagement-Artefakte wie Anforderungen, Testfaelle und Meldungen aus der Produktion, nach dem Grundsatz Keine Aktion ohne Ticket. Der Bezug wird sowohl im Artefakt (als Ziel-, Liefer- oder Auftretensversion) als auch im Versionsmanagement hergestellt, indem jeder Commit und jeder Branch die ID des Artefakts im Titel oder Kommentar traegt.
F22 Welche Bestandteile gehoeren zu einem Release und welche zu einer Konfiguration?
Zu einem Release gehoeren Quellcode, Abhaengigkeiten/Bibliotheken, eingebundene Dateien, das Datenbankschema, releaseabhaengige Daten und Dokumentation. Zu einer Konfiguration gehoeren die verwendete Infrastruktur, deren Parameter, Verbindungsparameter (Ports, URLs, Passwoerter, Zertifikate), die Entwicklungsumgebung, die Information ueber die Art der Umgebung und Feature Toggles.
F23 Was bedeutet der lokale und der nicht-lokale Teil der Pipeline?
Der lokale Teil umfasst Build (Kompilieren, Testen, Paketieren des noch nicht zusammengefuehrten Codes) und Deploy in die lokale Umgebung, sofern moeglich. Der nicht-lokale Teil umfasst Build des zusammengefuehrten Codes und Deploy in eine zentrale Umgebung.