Zurück zum Blog
Migration Dec 19, 2025 9 Min. Lesezeit

Von WHEN-VALIDATE-ITEM zu TypeScript-Validatoren: 25 Jahre Geschäftsregeln bewahren

Zuletzt aktualisiert Apr 9, 2026

ZUSAMMENFASSUNG

WHEN-VALIDATE-ITEM-Trigger enthalten 38 % aller Oracle Forms Geschäftslogik. Die Übersetzung nach TypeScript erfordert die Trennung von reiner Validierung und Datenzugriff sowie die Nachbildung des Forms-Ausführungsmodells — nicht nur Syntaxkonvertierung.

Wo die Regeln tatsächlich leben

Über 2.400 von uns analysierte .fmb-Dateien hinweg machen WHEN-VALIDATE-ITEM-Trigger 38 % des gesamten eingebetteten PL/SQL nach Zeilenanzahl aus. Sie sind der größte einzelne Behälter für Geschäftslogik in den meisten Oracle Forms Anwendungen — mehr als alle formularübergreifenden Trigger, Package Bodies und Library Units zusammen. Ein Versicherungsträger, mit dem wir zusammengearbeitet haben, hatte 9.700 davon in einem Policenverwaltungssystem, das 2001 erstmals deployed wurde.

Migrationen stehen und fallen damit, wie diese Trigger übersetzt werden.

Was WHEN-VALIDATE-ITEM tun soll

Der Trigger wird ausgelöst, wenn ein Feld den Fokus verliert und sich sein Wert geändert hat. Seine Aufgabe ist zu entscheiden, ob der neue Wert akzeptabel ist. Wenn nicht, löst er FORM_TRIGGER_FAILURE aus, was den Fokus auf das Feld zurücksetzt und eine Meldung anzeigt. Die Regeln variieren — Bereichsprüfungen, feldübergreifende Abhängigkeiten, Datenbankabfragen, regulatorische Grenzwerte.

-- Typischer WHEN-VALIDATE-ITEM
IF :POLICY.COVERAGE_AMOUNT > 1000000
   AND :POLICY.UNDERWRITER_LEVEL < 3 THEN
  MESSAGE('Coverage above 1M requires senior underwriter');
  RAISE FORM_TRIGGER_FAILURE;
END IF;

Dieses Vier-Zeilen-Beispiel berührt zwei Formularfelder, einen fest codierten Schwellenwert und eine Anzeigemeldung. Es ist repräsentativ. Der Median-WHEN-VALIDATE-ITEM-Trigger in unserer Stichprobe hat 11 Zeilen. Das 95. Perzentil liegt bei 84.

Das Übersetzungsziel

Unsere Zielform ist eine reine TypeScript-Validierungsfunktion, die den aktuellen Formularstatus nimmt und entweder null oder ein Fehlerobjekt zurückgibt. Keine Seiteneffekte, kein DOM-Zugriff, keine direkten Datenbankaufrufe aus dem Validator selbst.

export const validateCoverageAmount: Validator<PolicyForm> = (state) => {
  if (state.coverageAmount > 1_000_000 && state.underwriterLevel < 3) {
    return { field: "coverageAmount",
             message: "Coverage above 1M requires senior underwriter" };
  }
  return null;
};

Datenbankabfragen werden in asynchrone Validatoren verschoben, die einen generierten REST-Endpoint aufrufen. Der Validator bleibt rein; der Endpoint besitzt den Datenzugriff. Diese Trennung ist die wichtigste Einzelentscheidung bei der Übersetzung — sie macht die Regeln testbar, cachefähig und auditierbar.

Die schwierigen Fälle behandeln

Nicht jeder Trigger besteht aus vier sauberen Zeilen. Wir haben fünf Muster katalogisiert, die sich einer naiven Übersetzung widersetzen:

  • Implizite Commits. Trigger, die mitten in der Validierung COMMIT aufrufen. Diese werden in explizite Speicherschritte umstrukturiert.
  • Globale Variablen. Referenzen auf :GLOBAL.xyz, die Sitzungsstatus über Formulare hinweg speichern. Diese werden zu einem typisierten Session-Store.
  • DO_KEY-Aufrufe. Trigger, die Navigationsereignisse erneut auslösen. Diese werden zu expliziten Zustandsübergängen.
  • Dynamisches SQL. FORMS_DDL- und EXEC_SQL-Aufrufe. Diese werden für manuelle Überprüfung markiert — etwa 6 % der Trigger fallen hierunter.
  • Formularübergreifende Referenzen. Lesen von Feldern aus einem anderen geöffneten Formular. Diese werden zu sitzungsbezogenen Kontextobjekten.

Rund 91 % der WHEN-VALIDATE-ITEM-Trigger fallen in saubere Muster, die automatisch übersetzt werden. Die verbleibenden 9 % erfordern eine Überprüfung. Zu wissen, welche 9 % das sind, bevor das Projekt beginnt, ist der Unterschied zwischen einer vorhersehbaren Timeline und einer quartalsweisen Verschiebung.

Semantik bewahren, die der Compiler nicht sieht

Die schwierigsten Regeln sind die, die vom Ausführungsmodell von Oracle Forms abhängen. Ein WHEN-VALIDATE-ITEM wird nur ausgelöst, wenn sich das Feld geändert hat — nicht bei jedem Speichern, nicht bei Abfrageergebnissen, nicht bei programmatischer Zuweisung. Wer das falsch macht, löst Validatoren zu oft aus und bricht Workflows, die vorher funktionierten.

Wir bilden die Forms-Semantik explizit nach. Die Validator-Runtime verfolgt den Dirty-Status pro Feld, unterdrückt die Validierung während der Query-Befüllung und respektiert die ursprüngliche Trigger-Hierarchie (Feld, Block, Formular). Die übersetzte Regel ist identisch; die Runtime, die sie aufruft, stellt die Verhaltensübereinstimmung sicher.

Die Übersetzung testen

Jeder migrierte Validator erhält automatisch zwei Tests: einen, der aus dem ursprünglichen PL/SQL-Kontrollfluss generiert wird, und einen, der aus dem Produktions-Traffic gegen das Legacy-System erfasst wird. Der zweite ist wichtiger. Wir spielen sechs Monate echte Formulareingaben sowohl durch die alten als auch die neuen Validatoren und vergleichen die Ergebnisse. Jede Abweichung ist ein Defekt.

Bei den letzten vier Projekten hat diese Wiedergabe zwischen 14 und 71 Defekte pro 1.000 Trigger gefunden — fast alle in den oben genannten schwierigen Mustern.

Die Erkenntnis

WHEN-VALIDATE-ITEM ist der Ort, an dem 25 Jahre institutionelles Wissen leben. Die Übersetzung nach TypeScript ist keine syntaktische Übung — es ist eine semantische, und die Semantik hängt ebenso sehr vom Ausführungsmodell von Forms ab wie vom Code selbst. Die Migrationen, die Geschäftsregeln sauber bewahren, sind die, die reine Validierung vom Datenzugriff trennen, das ursprüngliche Ausführungsmodell nachbilden und echten Traffic vor der Umstellung wiedergeben.