wiki/c-work/4-done/2026-04-gateway-duplicate-class-names.md
2026-06-02 09:42:12 +02:00

133 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- status: done -->
<!-- started: 2026-04-09 -->
<!-- component: gateway -->
# Gateway: Doppelte Klassennamen bereinigen
## Beschreibung und Kontext
Beim Aufräumen der `@i18nModel`-Migration (Phase 2) wurde festgestellt, dass mehrere Python-Klassen im Gateway **denselben Namen** tragen, obwohl sie in verschiedenen Modulen leben. Das ist problematisch, weil:
1. **i18n-Kollision:** `@i18nModel` registriert nach `cls.__name__` in einem globalen Dict — bei gleichem Namen überschreibt der letzte Import den ersten.
2. **Lesbarkeit:** Import-Aliase (`from ... import TaskResult as WorkflowTaskResult`) sind fragil und leicht vergessen.
3. **Tooling:** IDE-Suche, Debugging-Stacktraces und `getModelClasses()` liefern mehrdeutige Treffer.
**Business-Treiber:** Saubere Klassennamen verhindern stille Label-Fehler in der UI und reduzieren Wartungsaufwand bei zukünftigen Erweiterungen.
---
## Vollständige Liste der Duplikate
Ermittelt per AST-Scan über `platform-core/modules/` (nur Klassen, die in **mehr als einer Datei** vorkommen):
### Kritisch: Pydantic-Modelle mit `@i18nModel` (i18n-Dict-Kollision)
| Klassenname | Datei 1 | Datei 2 | Beschreibung |
|-------------|---------|---------|--------------|
| **`TaskResult`** | `datamodels/datamodelChat.py` | `datamodels/datamodelWorkflow.py` | Chat: Aufgabenergebnis mit Status/Feedback. Workflow: Minimales Ergebnis mit `actionResult`. Beide haben `@i18nModel("Aufgaben-Ergebnis")`. |
| **`RequestContext`** | `datamodels/datamodelWorkflow.py` (Pydantic `BaseModel`) | `auth/authentication.py` (plain `class`) | Workflow: Normalisierter Benutzer-Input. Auth: Request-Kontext mit User/Mandate/Rollen. Kein i18n-Konflikt (Auth-Klasse ist kein Pydantic-Modell), aber Name ist irreführend. |
### Mittel: Lokale Hilfsklassen (kein i18n, aber verwirrend)
| Klassenname | Datei 1 | Datei 2 | Beschreibung |
|-------------|---------|---------|--------------|
| **`AiResponse`** | `datamodels/datamodelWorkflow.py` (Pydantic) | `serviceAi/subStructureFilling.py` (inline `class` in try/except, 4×) | Workflow: Vollständiges AI-Antwort-Modell. StructureFiller: Minimaler Wrapper `AiResponse(content)` als Fallback bei Parse-Fehlern. |
| **`TableData`** | `datamodels/datamodelDocument.py` (Pydantic) | `neutralization/.../subProcessList.py` (`@dataclass`) | Document: Strukturierte Tabelle mit Headers/Rows/Caption. Neutralization: Einfache Tabelle mit `source_type`. |
| **`Token`** | `datamodels/datamodelSecurity.py` (Pydantic `PowerOnModel`) | `shared/jsonContinuation.py` (`@dataclass`) | Security: DB-Token (JWT, Refresh etc.). JsonContinuation: JSON-Parser-Token (internes Parsing). |
### Niedrig: Architektur-Helfer (domänengetrennt, kaum Verwechslungsgefahr)
| Klassenname | Dateien | Beschreibung |
|-------------|---------|--------------|
| `ChatObjects` | `features/chatbot/interfaceFeatureChatbot.py`, `interfaces/interfaceDbChat.py` | Identische Rolle (Chat-Objekt-Container), ggf. zusammenführbar. |
| `ConnectionHelper` | `workflows/methods/methodOutlook/helpers/connection.py`, `workflows/methods/methodSharepoint/helpers/connection.py` | Jeweils Outlook- bzw. SharePoint-spezifisch; Name ist generisch, aber Module sind klar getrennt. |
| `DocumentParsingHelper` | `workflows/methods/methodJira/helpers/documentParsing.py`, `workflows/methods/methodSharepoint/helpers/documentParsing.py` | Jira- bzw. SharePoint-spezifisch; gleiche Situation wie `ConnectionHelper`. |
| `StructureGenerator` | `serviceAi/subStructureGeneration.py`, `serviceGeneration/subStructureGenerator.py` | Zwei Services mit ähnlicher Aufgabe; ggf. Konsolidierung prüfen. |
| `_ResolverDbAdapter` | `features/graphicalEditor/routeFeatureGraphicalEditor.py`, `features/workspace/routeFeatureWorkspace.py` | Interner Adapter (`_`-Prefix); lebt nur im jeweiligen Route-Modul. |
| `_ServicesAdapter` | 4× in `serviceCenter/services/*/main*.py` | Interner Adapter pro Service; bewusst gleichnamig, nie cross-importiert. |
---
## Lösungsvorschlag
### 1. `TaskResult` → Umbenennung (Priorität: hoch)
**Problem:** Beide Klassen haben `@i18nModel("Aufgaben-Ergebnis")` — der letzte Import gewinnt im Label-Dict.
**Lösung:**
| Aktuell | Neu | Modul |
|---------|-----|-------|
| `TaskResult` in `datamodelChat.py` | **`ChatTaskResult`** | Chat-Domäne: Status, Feedback, Error |
| `TaskResult` in `datamodelWorkflow.py` | **`WorkflowTaskResult`** | Workflow-Domäne: taskId + actionResult |
**Betroffene Imports (5 Dateien):**
- `workflows/processing/modes/modeBase.py` — importiert aus `datamodelChat`
- `workflows/processing/modes/modeDynamic.py` — importiert aus `datamodelChat`
- `workflows/processing/modes/modeAutomation.py` — importiert aus `datamodelChat` + `datamodelWorkflow` (bereits `as WorkflowTaskResult`)
- `workflows/workflowManager.py` — importiert aus `datamodelWorkflow` (bereits `as WorkflowTaskResult`)
- `workflows/processing/workflowProcessor.py` — importiert aus `datamodelWorkflow`
- `tests/unit/datamodels/test_workflow_models.py` — importiert aus `datamodelWorkflow`
**i18n-Labels anpassen:**
- `ChatTaskResult`: `@i18nModel("Chat-Aufgabenergebnis")`
- `WorkflowTaskResult`: `@i18nModel("Workflow-Aufgabenergebnis")`
**Aufwand:** Klein (6 Dateien, reine Umbenennung + Import-Anpassung).
### 2. `AiResponse` in `subStructureFilling.py` → Inline-Klasse eliminieren (Priorität: mittel)
**Problem:** 4× identische `class AiResponse` inline in try/except-Blöcken als Fallback-Wrapper.
**Lösung:** Eine private Klasse `_AiResponseFallback` am Modulanfang definieren, die 4 Inline-Definitionen ersetzen.
```python
@dataclass
class _AiResponseFallback:
content: Any
```
**Aufwand:** Klein (1 Datei, 4 Stellen).
### 3. `TableData` in `subProcessList.py` → Umbenennen (Priorität: mittel)
**Lösung:** `TableData` in `subProcessList.py`**`NeutralizationTableData`** (oder `_ParsedTableData`). Wird nur modulintern verwendet.
**Aufwand:** Minimal (1 Datei).
### 4. `Token` in `jsonContinuation.py` → Umbenennen (Priorität: niedrig)
**Lösung:** `Token`**`JsonToken`** (passend zu `TokenType``JsonTokenType`). Wird nur modulintern verwendet.
**Aufwand:** Minimal (1 Datei, rein intern).
### 5. `RequestContext` — Kein Handlungsbedarf
Die Auth-`RequestContext` ist kein Pydantic-Modell und hat kein `@i18nModel`. Die Workflow-`RequestContext` ist ein Pydantic-Modell mit `@i18nModel`. Es gibt **keine Import-Überschneidung** (Auth wird nie aus `datamodelWorkflow` importiert und umgekehrt). Kein Refactoring nötig.
### 6. Niedrige Kategorie — Kein Handlungsbedarf
`ChatObjects`, `ConnectionHelper`, `DocumentParsingHelper`, `StructureGenerator`, `_ResolverDbAdapter`, `_ServicesAdapter` leben in klar getrennten Domänen und werden nie cross-importiert. Umbenennung wäre kosmetisch.
---
## Umsetzungsreihenfolge
| Schritt | Was | Dateien | Aufwand |
|---------|-----|---------|---------|
| 1 | `TaskResult``ChatTaskResult` / `WorkflowTaskResult` | 8 | 30 min |
| 2 | Inline `AiResponse``_AiResponseFallback` | 1 | 10 min |
| 3 | `TableData``NeutralizationTableData` | 1 | 5 min |
| 4 | `Token``JsonToken` | 1 | 5 min |
**Gesamtaufwand:** ~50 min, kein Risiko für Laufzeitverhalten (reine Umbenennungen).
---
## Validierung
- `python -c "import app"` muss fehlerfrei durchlaufen
- Bestehende Tests (`tests/unit/datamodels/test_workflow_models.py`) anpassen und grün halten
- `getModelAttributeDefinitions` für betroffene Modelle prüfen (Labels eindeutig)