Domain Driven Refactoring
Anwendungen können im Laufe der Zeit anfällig für technische Schulden und ineffizienten Code werden. Durch gezieltes Refactoring können Ihre Anwendungen nachhaltig optimiert und zukunftssicher gemacht werden.
Bevor wir Sie bei Ihrem Refactoring begleiten, möchten wir Ihnen eine mögliche Vorgehensweise vorstellen, die sich darauf fokussiert, dass die Funktionalität Ihrer Anwendungssysteme beibehalten und sichergestellt wird.
Wie funktioniert ein Domain Driven Refactoring?
Technische, taktische und teamorganisatorische Domain-Driven Transformation
Schritt 1: Technische Stabilität sicherstellen
Schritt 2: Fachlichkeit stärken
Strategische Domain-Driven Transformation
Schritt 3: Wiederentdeckung der Fachdomäne
Schritt 4: Modellieren der fachlichen Soll-Architektur
Schritt 5: Abgleich der Ist- und Soll-Architektur
Technische, taktische und teamorganisatorische Domain-Driven Transformation
Bevor strategische Maßnahmen ergriffen werden können, stellen wir sicher, dass die technische Basis Ihrer Anwendungen für Ihre zukünftigen Weiterentwicklungen vorbereitet ist. Darauf aufbauend können teamorganisatorische Maßnahmen ergriffen werden, um die Effizienz und Produktivität der Entwicklungsprozesse zu steigern.
Schritt 1: Technische Stabilität sicherstellen
Build und Deployment automatisieren
Automatisiertes Bauen, Testen und Bereitstellen der Anwendung nach jedem Commit durch den Einsatz von CI/CD-Servern wie Jenkins, GitHub Actions oder GitLab CI und das Nutzen von Teil-Deployments.
Konsistente Infrastrukturressourcen
Anbieterunabhängige Bereitstellung von Infrastrukturressourcen durch den Einsatz von Infrastructure as Code Lösungen mit Terraform und der Verwendung der AWS, Azure und GCP Provider.
Die Technologiebasis stärken
Durch die Aktualisierung von Programmiersprachen, Frameworks und Abhängigkeiten auf aktuelle Versionen können Sicherheitslücken geschlossen, die Performance verbessert und ggf. alternative Frameworks verwendet werden.
Den Bugs auf der Spur
Wir erhöhen Ihre Testabdeckung beim Bugfixing und wenden die Pfadfinderregel an, indem wir den Code überarbeiten und mit Tests abdecken. Dabei implementieren wir verschiedene Testarten wie Unit Tests für Klassen, Integrationstests für Komponenten und UI-Tests für das Frontend.
Compiler-Warnungen auflösen
In Programmiersprachen wie Java und TypeScript werden Warnungen und Fehlermeldungen während des Starts und des Betriebs ausgegeben. Vernachlässigte Syntaxänderungen oder veraltete Codestandards werden basierend auf Ihrer verwendeten Programmiersprache auf den aktuellen Stand gebracht.
Codemetriken einführen
Damit behalten wir auch nach den Änderungen den Überblick über die Codequalität, indem wir Metriken wie die Testabdeckung, die Codekomplexität und die Codequalität einführen. Dazu nutzen wir Dashboardlösungen wie SonarQube oder CodeCov, um frühzeitig zyklomatische Komplexität und Sicherheitslücken zu erkennen.
Allgemeine Fehlerrobustheit
Die Robustheit gegen Nullpointer, das Gewährleisten der Funktionsweise von Klassen und Schnittstellen sowie das Auffangen von unerwartetem Verhalten stehen im Fokus. An dieser Stelle unterstützen wir Sie bei der Implementierung von Optionals, Exception Handling und Design by Contract.
Sicherheitsrichtlinien umsetzen
Durch die Umsetzung von Sicherheitsrichtlinien, wie das Verhindern von SQL-Injections, Cross-Site-Scripting und das Einschränken von Zugriffen auf Datenbanken und Funktionen, steht die Sicherheit Ihrer Anwendung im Vordergrund.
Schritt 2: Fachlichkeit stärken
Fachlichen und technischen Code trennen
Die Maßnahmen umfassen die Trennung des Datenbankzugriffs vom fachlichen Sourcecode durch Repositories, die Verlagerung von Oberflächenzugriffen aus fachlichen Klassen in die UI-Schicht sowie die Überprüfung von Vererbungsbeziehungen zwischen fachlichen und technischen Klassen.
Kohäsion erhöhen
Unter Verwendung der bereits existierenden Ubiquitous Language entwickeln wir fachlich angereicherte Domänenmodelle. Klassen dienen einem bestimmten Zweck und sind keine überladenen Klassen mit Getter- und Setter-Methoden.
Die Domäne sichtbar machen
Der Sourcecode sollte stets die jeweilige Fachlichkeit widerspiegeln. Dazu ersetzen wir Standardtypen durch fachliche Typen und machen die Identität von Entities unveränderlich.
Kopplung verringern
Einerseits teilen wir die bestehenden Module in kleinere, fachlich separierte Bounded Contexts auf. Zudem lösen wir Zyklen auf, ersetzen direkte Referenzen durch ID-Referenzen und verbessern die Ordnerstrukturen Ihres Repositorys.
Dokumentation sinnvoll einsetzen
Fachlichkeit sollte nicht nur in den Köpfen der Entwickler existieren. Aus diesem Grund unterstützen wir Sie bei der Erstellung von Domain Storys oder Domain Events im bestehenden Sourcecode.
Software als soziotechnisches System
Jedes Repository ist ohne die Interaktion zwischen den Entwicklern, Fachbereichen und Endnutzern leider nicht zukunftsfähig. Falls Sie bereits den Architekturschnitt und die Teamorganisation angepasst haben, sind wir gerne ein Teil Ihres Stream-aligned- oder Plattform-Teams.
Strategische Domain-Driven Transformation
Um die Fachlichkeit in Ihren Anwendungssystemen im Sourcecode, Datenbankmodell und auf Infrastrukturebene abzubilden, haben wir exemplarische Maßnahmen identifiziert, die Ihnen dabei helfen, einen ersten Eindruck von den Möglichkeiten einer Domain-Driven Transformation zu erhalten.
Schritt 3: Wiederentdeckung der Fachdomäne
Ist-Situation identifizieren
Zusammen mit Ihren Fachexperten, Domänen-Modellierern und Entwicklern beteiligen wir uns an Ihren Diskussionen und Workshops, um die Ubiquitous Language zu identifizieren und die technische Fachsprache aus der Diskussion auszuschließen.
Essenzielle Abläufe identifizieren
Welche Schritte sind tatsächlich durch die Fachlichkeit begründet? Wir helfen Ihnen dabei, die aktuelle Anwendung auf technologisch bessere Lösungen zu überführen und die abgebildeten Prozesse auf ihre Essenz zu reduzieren.
Subdomänen im Soll-Prozess finden
Nachdem die Ist-Situation festgestellt wurde, passen wir die abgebildeten Software-Prozesse an die Sollprozesse an.
Schritt 4: Modellieren der fachlichen Soll-Architektur
Soll-Context-Map erstellen
Aus jeder identifizierten Subdomäne wird ein Bounded Context erstellt, der den Soll-Zustand darstellen wird. Diese Bounded Contexts können durch Event Storming, Domain Storys usw. entstehen.
Subdomänen kategorisieren
Basierend auf den bestehenden Subdomänen der Arbeitsprozesse erstellen wir eine Context-Map, die Ihre Subdomänen in Core, Supporting und Generic Subdomains unterteilt. Diese Subdomains unterstützen das Team bei der Aufteilung der Legacy-Systeme in Microservices oder modulare Monolithen.
Bounded Context den Teams zuordnen
Während der Aufteilung der Anwendungszuständigkeiten können wir als Teil des Entwicklungsteams Bestandteile eines Bounded Context übernehmen und die technische Verantwortung für die Umsetzung tragen.
Interaktion zwischen Bounded Context definieren
Damit die Funktionsweise einer Subdomäne autonom bleibt, betrachten wir die Schnittstellen und Kommunikationswege zwischen den Bounded Context genauer.
Schritt 5: Abgleich der Ist- und Soll-Architektur
Soll-Context-Map mit Sourcecode abgleichen
Um überladene Domänenklassen auf Ihre Subdomänen aufzuteilen, duplizieren wir bestehende Klassen und reduzieren sie auf ihre tatsächlich erforderliche Funktionsweise. Zudem entwickeln wir ein Konzept für die Kommunikation zwischen den Domänen.
Refactoring der Schichten Ihrer Systeme
Die Transformation Ihrer Anwendungssysteme umfasst auch die domänenspezifische Aufteilung Ihrer Datenbanken, Benutzeroberflächen und Geschäftslogik.
Subdomänen im Soll-Arbeitsprozess finden
Nachdem die Ist-Situation festgestellt wurde, passen wir die abgebildeten Software-Prozesse an die Sollprozesse an. Lassen Sie uns Zusammenhänge und Subdomänengrenzen im Sourcecode finden. Domain-Driven Design kann uns dabei mit Domain Storytelling, Event Storming und der Identifizierung von Pivotal Events unterstützen.