Thomas Mahringer Selbstständig

„Durch die Kombination aus TypeScript-Interfaces und einem Domänenschema lassen sich typsichere, hierarchische Datenabfragen erstellen.“

Generische, JSON-basierte Datenabfragen haben sich in vielen Anwendungsfällen als Alternative zu klassischen REST-Endpoints etabliert – vor allem, wenn Apps laufend weiterentwickelt und verändert werden. Dank TypeScript können wir eine statisch typisierte „Grammatik“ für eine JSON-Abfragesprache erstellen, ohne auf komplexere Zusatztools zurückgreifen zu müssen.

Im ersten Artikel haben wir besprochen, wie man die Idee „überall TypeScript“ nicht nur als client- und serverseitige Programmiersprache entwickeln, sondern noch viel weiter denken kann: In unserem Beispiel wurde TypeScript dank seines Metadatenkonzepts zu einer domänenspezifischen Sprache, in der wir das Domänennetzwerk von Kunden, Kaufvorgängen und Tickets beschrieben haben. Aus dem Domänenmodell konnten wir automatisiert ein Schema erzeugen, das uns in diesem und im kommenden Artikel dabei helfen wird, hierarchische Datenabfragen zu formulieren und die Abfragen auf einem Server generisch auf eine relationale Datenbank zu mappen. In diesem Artikel werden wir die Abfragesprache selbst gestalten und dazu auf TypeScript Union Types zurückgreifen.

Die Grundidee: hierarchische Abfragen in JSON definieren

Die Basis für die Beispielabfragen bildet unser einfaches Domänenmodell (Abb. 1):

  • Ein Kunde kann N Einkäufe tätigen. Jeder Einkauf ist genau einem Kunden zugeordnet.
  • Einem Einkauf ist genau ein Artikel (Stock Keeping Unit (SKU)) zugeordnet, jeder Artikel kann an beliebig vielen Einkäufen beteiligt sein.
  • Ein Kunde kann N Tickets/Reklamationen aufgeben. Jedes Ticket hat genau einen Owner.
  • Einem Einkauf können mehrere Tickets zugeordnet werden. Jedes Ticket hat genau einen Grund (Reason).
Abb. 1: Der Ausschnitt des Domänenmodells für unsere Beispielabfragen

Abb. 1: Der Ausschnitt des Domänenmodells für unsere Beispielabfragen

In Listing 1 wird die Grundidee der hierarchischen Abfrage anhand des Beispiels „Kundensuche“ deutlich: Wir suchen alle Kunden, die „Satya Nadella“ heißen. Unsere Suchanfrage beschreiben wir durch ein Plain-JavaScript-Objekt: Liefere die Properties id, firstName und lastName von Kunden, die dem Kriterium Vorname == Satya und Nachname == Nadella entsprechen. Das JavaScript-Objekt lässt sich einfach in JSON umwandeln und z.B. mittels XHR2 an ein Backend senden. Was stört uns an dieser Abfrage? Sie basiert rein auf einem JavaScript-Objekt und Strings, die die gewünschten Bedingungen und Daten beschreiben. Das bedeutet, dass wir irgendetwas in die Abfrage schreiben könnten und erst bei der Antwort vom Backend erfahren, ob die Anfrage in Ordnung war. Das öffnet Tür und Tor für Tippfehler, z.B. fristName statt firstName.

const simpleCustomerQuery = {
  name: "Customer-Nadella",
  class: "Customer",
  select: [„id“, „firstName“, „lastName“],
  restrict: 
  {op: „AND“, restrict:[
    {property: „firstName“, op: „EQ“, value: "Satya"}, 
    {property: „lastName, op: „EQ“, value: "Nadella"}
    ]
...

Der nächste Schritt: TypeScript-Interfaces statt Plain-JavaScript-Objekt

Da wir (meist) in TypeScript denken, ist die Lösung aber denkbar einfach: Wir definieren den Typ der Abfrage als Interface. Damit kann der Transpiler überprüfen, ob die Abfrage syntaktisch korrekt ist.

Den vollständigen Artikel lesen Sie in der Ausgabe:

Windows Developer 9.18 - "Docker für .NET-Entwickler"

Alle Infos zum Heft
579851365Mit TypeScript Union Types die Grammatik für eine hierarchische QL definieren
X
- Gib Deinen Standort ein -
- or -