Diese Dokumentation beschreibt die durchgeführten Refactoring-Maßnahmen zur Verbesserung der Performance und Wartbarkeit des Flow UI Toolkits.
Das Refactoring konzentrierte sich auf folgende Hauptbereiche:
- Aufspaltung des monolithischen PropertyEditors in kleinere, spezialisierte Komponenten
- Implementierung eines SubflowManager-Utilities zur Reduzierung von redundantem Code
- Optimierung der Visibility-Condition-Auswertung durch Memoization und Abhängigkeitsverfolgung
- Verbesserung der TypeScript-Typen und Implementierung von Discriminated Unions
- Optimierung des State-Managements durch modulare Struktur
- Verbesserung der Pfadnavigation und -auflösung für tiefe Verschachtelungen
- Implementierung einer intelligenten Containertyp-Erkennung und -Anzeige
- Entwicklung von Strukturnormalisierungs- und Validierungsfunktionen für komplexe JSON-Strukturen
- Monolithische Komponente mit über 3000 Zeilen Code
- Zahlreiche verschachtelte Switch-Statements
- Redundante Update-Muster für verschiedene Elementtypen
- Schwer zu warten und zu erweitern
-
Komponentenstruktur:
CommonPropertiesEditor: Bearbeitung gemeinsamer Eigenschaften aller ElementeElementEditorFactory: Factory-Pattern zur Instanziierung des passenden Editors- Spezialisierte Editoren für verschiedene Elementtypen (z.B.
TextElementEditor,BooleanElementEditor) VisibilityConditionEditor: Eigenständige Komponente für die Bearbeitung von Visibility-Bedingungen
-
Wiederverwendbare UI-Komponenten:
TranslatableField: Für mehrsprachige TextfelderSectionTitle: Für Abschnittstitel im PropertyEditor
-
Vorteile:
- Bessere Wartbarkeit durch kleinere, fokussierte Komponenten
- Einfachere Erweiterbarkeit für neue Elementtypen
- Reduzierte Komplexität und verbesserte Lesbarkeit
- Weniger Fehleranfälligkeit durch spezialisierte Komponenten
- Redundanter Code für die Verwaltung von Subflows
- Komplexe und fehleranfällige Update-Logik
- Inkonsistente Implementierung über verschiedene Komponenten hinweg
-
Utility-Funktionen:
updateSubflowElement: Aktualisiert ein Element innerhalb eines SubflowsupdateSubflowElementProperty: Aktualisiert eine bestimmte Eigenschaft eines ElementsremoveSubflowElementProperty: Entfernt eine Eigenschaft eines ElementsfindSubflowByType: Findet einen Subflow nach seinem TypfilterSubflows: Filtert Subflows nach ihren Typen
-
Vorteile:
- Reduzierung von Code-Duplikation
- Konsistente Implementierung von Subflow-Operationen
- Verbesserte Testbarkeit durch isolierte Funktionen
- Einfachere Fehlerbehebung durch zentralisierte Logik
- Ineffiziente Auswertung von Visibility-Bedingungen
- Wiederholte Berechnungen für unveränderte Bedingungen
- Fehlende Abhängigkeitsverfolgung für betroffene Elemente
-
Optimierungsstrategien:
- Memoization für die Evaluierungsfunktion mit Lodash
- Extraktion relevanter Felder aus Bedingungen für effiziente Cache-Schlüssel
- Erstellung einer Abhängigkeitskarte für betroffene Elemente
- Selektive Neuauswertung nur bei Änderung relevanter Feldwerte
-
Neue Funktionen:
extractRelevantFields: Extrahiert alle Feldnamen aus einer Visibility-BedingungcreateDependencyMap: Erstellt eine Abhängigkeitskarte für alle ElementegetElementsToReevaluate: Findet Elemente, die bei Feldänderungen neu evaluiert werden müssen
-
Vorteile:
- Verbesserte Performance durch Vermeidung redundanter Berechnungen
- Effizientere Aktualisierung der UI bei Feldwertänderungen
- Skalierbarkeit für komplexe Formulare mit vielen Visibility-Bedingungen
- Inkonsistente Verwendung von TypeScript-Typen
- Fehlende Discriminated Unions für bessere Typsicherheit
- Unzureichende Null-Checks
-
Typverbesserungen:
- Konsistente Benennung von Eigenschaften (z.B.
fieldNamestattfield_name) - Strikte Null-Checks in kritischen Funktionen
- Verbesserte Typgards für UI-Elemente
- Konsistente Benennung von Eigenschaften (z.B.
-
Vorteile:
- Reduzierte TypeScript-Fehler
- Verbesserte Entwicklererfahrung durch bessere Typinferenz
- Frühzeitige Fehlererkennung während der Entwicklung
- Tiefe Objektmutationen führen zu unnötigen Re-Renders
- Ineffiziente Zustandsaktualisierungen
- Fehlende Memoization für rechenintensive Operationen
-
Optimierungsstrategien:
- Modulare Struktur für gezielte Zustandsaktualisierungen
- Immutable Update-Patterns für Zustandsänderungen
- Memoization für rechenintensive Operationen
-
Vorteile:
- Reduzierte Re-Renders und verbesserte UI-Performance
- Bessere Nachvollziehbarkeit von Zustandsänderungen
- Effizientere Speichernutzung
- Begrenzte Unterstützung für tiefe Verschachtelungen
- Inkonsistente Pfadauflösung bei komplexen Strukturen
- Schwierigkeiten bei der Navigation durch verschachtelte Elemente
- Probleme beim Hinzufügen von Elementen in tiefen Ebenen
-
Verbesserte Funktionen:
getElementByPath: Robuste Funktion zur Auflösung von ElementpfadengetPathContext: Ermittelt den Kontext eines Pfads (übergeordnete Elemente, Containertyp)- Optimierte Breadcrumb-Navigation mit Pfadkontext
- Verbesserte
handleAddElement-Funktion mit Pfadkontext-Berücksichtigung
-
Vorteile:
- Unterstützung für bis zu 6 Verschachtelungsebenen
- Konsistente Pfadauflösung auch bei komplexen Strukturen
- Verbesserte Benutzerführung durch kontextbezogene Navigation
- Zuverlässiges Hinzufügen von Elementen in tiefen Ebenen
- Fehlende einheitliche Erkennung von Containertypen
- Inkonsistente Behandlung verschiedener Container (Gruppe, Array, ChipGroup, etc.)
- Unzureichende visuelle Unterscheidung von Containertypen
- Schwierigkeiten bei der Bearbeitung von Unterelementen
-
Neue Funktionen:
getContainerType: Ermittelt den Containertyp eines Elements (group, array, chipgroup, custom, subflow)getSubElements: Einheitliche Funktion zum Abrufen von Unterelementen- Verbesserte visuelle Darstellung von Containertypen in der UI
- Containertyp-spezifische Aktionen und Bearbeitungsmöglichkeiten
-
Vorteile:
- Einheitliche Behandlung verschiedener Containertypen
- Verbesserte Benutzerführung durch visuelle Unterscheidung
- Optimierte Bearbeitung von Unterelementen
- Unterstützung für komplexe Containerstrukturen wie CustomUIElement mit sub_flows
- Inkonsistente JSON-Strukturen bei Import/Export
- Fehlende Validierung von Strukturen
- Probleme bei der Verarbeitung komplexer JSON-Dateien wie doorbit_original.json
- Inkonsistente Einwicklung von Elementen in PatternLibraryElement-Objekte
-
Neue Funktionen:
normalizeElementTypes: Normalisiert Elementtypen und EigenschaftennormalizeVisibilityCondition: Normalisiert Visibility-BedingungenvalidateFlowStructure: Validiert die Struktur eines FlowsenforcePatternLibraryElementWrapping: Erzwingt die Einwicklung von ElementennormalizeComplexStructure: Spezielle Normalisierung für komplexe Strukturen
-
Vorteile:
- Konsistente JSON-Strukturen bei Import/Export
- Frühzeitige Erkennung von Strukturfehlern
- Verbesserte Unterstützung für komplexe JSON-Dateien
- Zuverlässige Verarbeitung von doorbit_original.json und ähnlichen Strukturen
- Importierte Referenz-Flows (z.B.
doorbit_esg (2).json) enthielten fachliche Feldnamen infield_id.field_name. - Die ursprüngliche Implementierung von
uuidUtils.ensureUUIDshat bei Elementen ohne "-" im Feldnamen UUID-Suffixe anfield_id.field_nameangehängt. - Visibility-Bedingungen und andere Referenzen (z.B. KeyValue-Listen) blieben jedoch auf die ursprünglichen Feldnamen gerichtet.
- Dadurch entstanden Divergenzen zwischen Felddefinitionen und Referenzen sowie falsche Export-Strukturen.
- Klare Trennung von internen und externen IDs:
uuidwird als rein interne ID für Seiten, Subflows, Elemente, Optionen, Chips und Visibility-Bedingungen verwendet.field_id.field_namebleibt fachlich/external und wird beim Import nie automatisch verändert.
- Anpassungen in
uuidUtils.ts:ensureElementUUIDnormalisiertfield_idnur noch von String → Objekt, ohne denfield_nameinhaltlich zu ändern.- ChipGroup-Chips und
other_user_value.text_ui_elementerhalten UUIDs, ihrefield_id.field_name-Werte bleiben jedoch unverändert (nur String → Objekt-Konvertierung, falls nötig). - Neue Hilfsfunktion
stripUUIDFromVisibilityConditionentfernt rekursiv alleuuid-Felder aus Visibility-Bedingungen und normalisiert ggf.field_idvon String → Objekt. transformElementForExportnutztstripUUIDFromVisibilityConditionund entfernt zusätzlich alleuuid-Felder aus verschachtelten Elementen, Chips, Items und Optionen.- Neue Funktion
transformFlowForExporterzeugt aus einem internenListingFloweinen exportfertigen Flow ohneuuid-Felder, inklusive Bereinigung von Seiten- und Subflow-UUIDs sowie deren Visibility-Bedingungen.
- Anpassungen in
App.tsxundJsonPreview.tsx:handleSaveverwendet nuntransformFlowForExport(state.currentFlow), bevor der JSON-Download erzeugt wird.JsonPreviewzeigt die gleiche exportbereite Struktur an, indem estransformFlowForExport(data)verwendet.
- Importierte Referenzdateien wie
doorbit_esg (2).json)können verlustfrei importiert, im Editor bearbeitet und wieder exportiert werden, ohne dass sichfield_id.field_nameoder die Struktur ändern. - Alle internen UUIDs bleiben auf den Editor beschränkt und tauchen im Export nicht mehr auf.
- Visibility-Bedingungen behalten stabile Feldreferenzen, da
field_id.field_namenicht mehr nachträglich verändert wird. - JSON-Preview und tatsächlicher Export verwenden dieselbe Transformationslogik und sind damit konsistent.
Die implementierten Refactoring-Maßnahmen wurden mit automatisierten Tests validiert:
- SubflowManager: Alle Tests erfolgreich
- optimizedVisibilityUtils: Alle Tests erfolgreich
- Bestehende Tests: Keine Regressionen in bestehender Funktionalität
Für zukünftige Verbesserungen werden folgende Maßnahmen empfohlen:
-
Integration der neuen Komponenten:
- Schrittweise Migration vom alten PropertyEditor zum neuen RefactoredPropertyEditor
- Implementierung weiterer spezialisierter Editoren für andere Elementtypen
-
Weitere Optimierungen:
- Implementierung von Immer für unveränderliche Updates
- Erweiterung der Memoization auf weitere rechenintensive Operationen
- Implementierung von React.memo für kritische Komponenten
-
Erweiterte Tests:
- Performance-Tests für Visibility-Condition-Auswertung
- Integrationstests für die neuen Editor-Komponenten
- Stress-Tests für komplexe Formulare mit vielen Elementen