cardo4

cardo – damit verbinden unsere Kunden seit nunmehr 15 Jahren Zuverlässigkeit, Produktivität, Flexibilität und Kontinuität.

Wir sind im Jahr 2015 die Herausforderung angegangen die Grundlage zu schaffen, diesen hohen Anforderungen  auch in den nächsten fünfzehn Jahren gerecht werden zu können.

Die folgenden Zeilen sollen die Änderungen vor allem für Entwickler des Systems und Nutzer der Programmschnittstellen (API) im Detail darstellen, sind aber auch für Systembetreuer von Interesse. Neben den technischen Änderungen werden auch die Konzepte/Überlegungen, die diesen zu Grunde liegen, dargestellt.

Motivation

Wie der Versionssprung in der ersten Stelle vermuten lässt, bringt cardo4 bringt einige grundlegende Neuerungen mit sich:

  • Konsequenter Einsatz von HTML5 Technologien, Trennung von dem Einsatz proprietärer Internet Explorer Erweiterungen
  • Konsequenter Einsatz von TypeScript als vollständiger Ersatz von JavaScript (im Browser kommt nat. nach wie vor JavaScript zum Einsatz)
  • Stärkere Verschmelzung von Server und Client-Code (vor allem im Bereich Kommunikation via Ajax-Methoden)
  • Trennung von der Nutzung von „Classic-ASP“ für alle Kernkomponenten
  • Trennung von dem Client Framework ExtJs und Erstellung/Nutzung eines eigene UI - Clientframework „KISS“
  • Nutzung von OpenLayers3 als Grundlage für die Kartenkomponente
  • Einführung des Konzepts der „Bekannten Dinge“ (WellknownTypes) als grundlegenden Gegenstand zur Kommunikation aller Module/Funktionen innerhalb der Umgebung
  • Auslegung der serverseitigen Architektur auf horizontale Skalierbarkeit und durchgängige 64 Bit Unterstützung
  • Vollständige Neuimplementierung des Geodatenservers „Iwan“, Arbeitstitel „Iwan7“

Machen wir uns nichts vor: Die Welt dreht sich, und scheinbar schneller als je zuvor. Viele der technologischen Entwicklungen der letzten Jahre sind vor allem durch eines geprägt: Wandel und Wechsel.

Wir sehen hier ebenso Chancen wie Risiken. Bei nüchterner Betrachtung, und in Anbetracht der langjährigen Erfahrung auf dem Gebiet der Softwareerstellung und vor allem auch in der Rolle als Anbieter von Lösungen, kommen wir zu dem Schluss: Es gibt gute Tendenzen denen man folgen sollte, aber die technologischen Bewegung müssen mit Bedacht und unter dem Verfolgen einer langfristigen Strategie bewertet werden. Es gilt wie so oft: finde den richtigen Mittelweg.


Wir möchten hier nicht altbacken klingen, aber die ganze Hypes aus der Branche (ich ziele hier mit meinen Worte auf diverse technische Frameworks ab) sind unter Betrachtung in der Rolle des Lieferanten einer Software die in vielen Organisationen unternehmenskritisch relevant ist und wo individuelle Anpassungen in größerem Umfang selbständig vorgenommen werden sollen unter dem Aspekt nach nachhaltigen Nutzung als zu instabil einzustufen (instabil meint hier nicht die technische Zuverlässigkeit, sondern die Stabilität der API bei z.B. Versionswechseln).


Dies vorab,  auf die Beantwortung der Frage  „Warum nehmen die nicht einfach XYZ“, die sich der eine oder andere Leser an dieser Stelle bereits gestellt haben könnte.

Warum TypeScript

Meinung des Autors dieser Zeilen: Mit JavaScript und den aktuellen (von uns eingesetzten) Entwicklungsumgebungen, ist es nicht möglich langfristig pflegbare, komplexe Anwendungen zu erstellen.

TypeScript (und die damit einhergehende Integration in die Entwicklungsumgebung Visual Studio) ist an dieser Stelle ein Segen für alle Entwickler, mit dem diese Lücke geschlossen wird. Wir möchten hier nicht zu viele Details verlieren, das Internet bietet eine mehr als auskömmliche Quelle für alle Informationen zu diesem Thema.


Da auch Nicht-Programmierer diese Zeile lesen, hier ein kleines Gleichnis (Ostern ist gerade vorbei): Alle Dinge funktionieren nur nach bestimmten Regel, werden die Regeln verletzt … nun ja, dann funktionieren diese Dinge eben nicht mehr.

Einhaltung von Regeln kann mit viel Disziplin erreicht werden. Aber Disziplin ist endlich und setzt vor allem viel Vorwissen voraus.

Stellen Sie sich vor, Sie haben eine Sortieranlage für Eier verschiedener Größen. Es sind drei gleich große Öffnungen vorhanden, eine für Eier mit Größe 1, eine für Eier mit Größe 2 und eine für Eier mit Größe 3 (ja, die Öffnungen sind auch so beschriftet), jetzt versuchen Sie den Eiern mal zu sagen, in welches Loch Sie fallen sollen. Der Leser kennt die Lösung: er würde Öffnungen gemäß der Größen anfertigen. Diesen Zwang (eben die Typisierung) bringt uns der TypeScript Transpiler. Richtig angewandt und eingesetzt (so strikt als möglich) geht hier nun kein Ei mehr in die falsche Öffnung.


Wichtig ist hier zu erwähnen: Wir nutzen Typescript hier so strikt als möglich, es gibt für alles in der cardo4 Umgebung ein Interface, der Type „any“ ist verboten und alle Komponenten sind auch tatsächlich in TypeScript implementiert. Aktuell sind wir auch bestrebt, jede neue Typescript Version zu nutzen und die dort gefundenen neuen Features zu nutzen.

Um die Brücke zwischen dem serverseitigen Code (hier .Net, c#)  und dem clientseitigen den gleichen Zwängen zu unterwerfen, werden aus allen Ajax-Methoden TypeScript Methoden und Interfaces für die transportierten Daten über eine Visual-Studio Erweiterung automatisch erstellt.


Dabei werden eigene Ajax-Komponenten verwendet, die diverse Belange abdecken. Dazu gehören:

  • Erstellung aller .Net Typen (Input und Output) als Typescript – Interface.
  • Spezifische Behandlung clientseitig bereits bekannter Typen, z.B. Geometrien, WellknownTypes, Binärdaten, Arrays.
  • Bereitstellung der typisierten Ajax-Methoden zum unmittelbaren Aufruf mit ebenso typisiertem Promise als Antwortobjekt.
Was sind „Bekannte Dinge“

In einer komplexen Umgebung wie dem cardo System drängt sich zwangsläufig die Frage auf, wie die Komponenten, Module, Anwendungen (letztendlich meinen diese Begriffe alle das Gleiche: spezifischen ausführbaren Programmcode für die Erfüllung einer bestimmten Aufgabe) mit den im System befindlichen Gegenständen (sprich: den Daten) sinnvoll agieren können, bzw. ihre Dienste anbieten können.

cardo als Integrationssystem ist hier mit einen schier unbegrenzten Menge verschiedener Daten konfrontiert. Die Strukturen, Speicherorte, Formate sind nahezu beliebig. Also muss ein Mechanismus geschaffen werden, der diese Spezifika abstrahiert und den eingangs genannten Softwarekomponenten einen gemeinsamen Nenner bietet.
Dazu eine Vorabbetrachtung, der „Dinge“ die es in cardo gibt:

  • Einen strukturierten Inhaltsbaum mit Beschreibungen, Berechtigungen, Metadaten
  • Vom Betreuer in diesen Inhaltsbaum eingestellte (Geo)Datenquellen (die die oben genannten Eigenschaften erben) beliebigen Inhaltes
  • Ad-Hoc „produzierte“ Datenquellen, z.B. Uploads, als Ergebnis von Abfragen oder als Ergebnis der Aktion von Anwendungen
  • Ad-Hoc „produzierte“ Datensätze, z.B. als Ergebnis einer Abfrage einer Ortsinformation (wie dem cardo Gazetteer-Dienst, GSS etc.)
  • Datenquellen mit Bearbeitungsmöglichkeiten (mit oder ohne Geometrie, bzw. mit spezifischen oder allgemeine Anforderungen an die Geometrie, wie Topologie)
  • Fachanwendungen

Diese Liste erscheint auf den ersten Blick nicht sehr umfangreich, ist aber tatsächlich vollständig. Der Leser möge bedenken, dass hinter den genannten im Detail eine Vielzahl an Thematiken steckt (die Liste der Flurstücke des Landes X, die Ergebnisse einer Eigentümerrecherche, die Luftbilder als WMTS Dienst, WMS Dienst oder als lokale ECW Datei,  Ein B-Plan auf GML Basis, Daten einer Vermessung als DXF Datei, eine Fachschale „Baumkataster“, Daten aus einer Excel-Tabelle, Ein komplexer View mit Daten aus dem internen Oracle Datawarehouse ….).


Im Gegenzug bietet das System programmtechnische Unterstützungen, implementiert im Kern oder durch Erweiterungen, um mit diesen Dingen umzugehen. Z.B:. Jede Geodatenquelle kann in der Karte dargestellt werden. Jedes Thema aus den Inhaltbaum hat Metadaten, diese können dargestellt oder erfasst werden. Jede (Geo)datenquelle kann als Sachdatentabelle dargestellt werden. Einzelne Datensätzen mit Geometrie können als Objekt in der Karte dargestellt werden. Anwendungen können gestartet werden. Alle tabellenähnlichen Daten können, in z.B. CSV oder XLS, exportiert werden. Anwendungen können zu bestimmten Datensätze mehr Details liefern (der Klassiker: Eigentümerliste zu Flurstücken). Alle tabellenähnlichen Datenquellen können durch quellenübergreifende Abfragen Analysiert usw.


Diese grundlegenden Möglichkeiten sind schon recht umfangreich, können aber nat. im Ergebnis den gleichen Mechanismus weiternutzen und damit weitere Mehrwerte produzieren. Greifen wir aus der Liste der beispielhaft genannten Möglichkeiten das letztgenannte, themenübergreifende Abfragen, heraus. Das Ergebnis einer Abfrage ist wiederrum, meist, etwas tabellenähnliches, d.h. dieses Ad-Hoc Produzierte kann wiederrum durch das Modul „Tabellenansicht“ oder „Tabellenexport“ weiterverarbeitet werden. Und wenn eine Geometriesspalte enthalten ist, dann ist es auch durch das Modul „Karte“ nutzbar. Und wenn das Ergebnis eine Spalte mit dem Namen „ALKNR“ enthält, dann kann vielleicht dazu die Anwendung „ALKIS“ die Liste der Eigentümer zum dem (vermeintlichem) Flurstück beschaffen.


Eine letzte Überlegung dazu fehlt noch. Personalisierung ist ein wichtiges Thema als Schlüssel zu einer produktiven und komfortablen Nutzung eine Systems. Soll der letzte Sitzungszustand wiederhergestellt werden, eine Liste der persönlichen Favoriten bereitgestellt werden oder soll anderen Kollegen die Ergebnisse von Arbeitsschritten zur Verfügung gestellt werden, dann muss die Programmumgebung Möglichkeiten bereitstellen, die benutzten Daten, sowie die dafür verwendeten Anwendungen persistent zu Speichern.


Genau für die Abbildung dieses Zusammenspiel zwischen „Dingen“, der Umgebung und dem auswertendem „Programmteil“ haben wir das Konzept der „WellknownTypes“ in cardo integriert. Benannte Dinge erlauben damit:

  • Die eindeutige Kennzeichnung einer Datenquelle oder Anwendung
  • Eine Semantik, die das Beschriebene funktional benennt
  • Möglichkeiten zur Wiederherstellung (Ad-Hoc generierter Datenquelle)

Das System verfügt über verschiedene Mechanismen, die bei jeder Verwendung einer Instanz eines WellknownType greifen. Dazu gehört die Buchführung der Nutzung pro Anwender, die Wiederherstellung der Daten bei produzierten Daten bei der Ersten Wiederverwendung, Bereitstellung von Methoden zur Serialisierung und Deserialisierung und vor allem der Ausführungsschicht, die Anwendungen im Kontext der Nutzung zum Start anbietet und den entsprechenden Aufruf initiiert.


Zum besseren Verständnis des eben genannten, soll das Verhalten am Ablauf der Suchfunktion in cardo4 erläutert werden:

  • Der Nutzer aktiviert das Suchfeld in der cardo4 Umgebung
  • Das System listet sofort alle zuletzt genutzten WellknownType Instanzen, sortiert nach der Häufigkeit der Benutzung auf
  • Der Nutzer gibt ein Suchwort ein, der Suchprozess wird serverseitig angestoßen, das System ruft nun alle bekannten Suchprovider mit dem eingegeben Begriff auf, jeder antwortet mit einer Liste von WellknownType Instanzen

Clientseitig wird die Ergebnisliste präsentiert (jeder WellknownType hat einen Titel und ein Icon), bei der Anzeige der Treffer ruft das System für jede der so gefundenen Instanzen jede in der aktuellen Umgebung registrierte Anwendung/Modul auf und fragt, ob es mit der Instanz umgehen kann, und wenn ja, welche Optionen zum Starten angeboten werden soll.

  • Das Ergebnis wird dem Nutzer in Form der entsprechenden Startoptionen zum Suchtreffer präsentiert.
  • Der Nutzer wählt eine Aktion am jeweiligen Treffer aus.
  • Das System erhöht die Nutzungsstatistik für den WellknownType und ruft die Anwendung, ggf. mit der ausgewählten Option, auf (z.B.: „Ebene Flurstücke“ => „Anzeige in Karte, Zoom auf diese Ebene) und übergibt die gewählte Instanz des WellknownType an die Anwendung.

Dieser Mechanismus des Startens einer Aktion zu einer WellknownType Instanz ist an sehr vielen Stellen im Kernsystem und auch den Kernkomponenten in genau dieser Form verfügbar und steht als API Methode für Dritte zur Verfügung.
Zusammengefasst bedeutet dies, ein WellknownType …

  • Ist ein Zeiger auf ein Datum,
  • stellt durch die Art des Typs die Semantik dessen dar, worauf gezeigt wird,
  • ist serialisierbar,
  • kann Ad-Hoc produziert werden,
  • kurzum: ist das zentrale Bindeglied zwischen Programmfunktionen und den Daten
Warum ein eigenes Client Framework – warum KISS

Für die Auswahl eines Client-Frameworks haben wir einige der Verfügbaren genauer unter die Lupe genommen. Folgende Vorgaben haben wir dabei aufgestellt, die zu prüfen waren:

  • vollständig in Typescript implementiert,
  • Saubere und typisierte Datenmodelle,
  • Bestmögliche Performance bei Umgang und Darstellung auch größerer Datenmengen/komplexer Oberflächen,
  • durchgängige Nutzung von aktuellen HTML5 Features, frei von Altlasten,
  • keine weiteren Abhängigkeiten zu anderen APIs,
  • ausreichende Freiheiten bei der Nutzung als Entwickler, kein zu starke Kapselung der UI Elemente,
  • aktiv in der Entwicklung,
  • Stabilität der API bei Versionswechseln,
  • überschaubare und stabile Lizenzkosten, auch für Mitentwickler (redistributierbare Lizenz),
  • sauberes Zusammenspiel mit Visual Studio und „unseren“ Werkzeugen,
  • nachvollziehbar, frei von „Magie“ (die Entwickler unter Ihnen wissen wahrscheinlich was hiermit gemeint ist)

Wir sind hier nicht fündig geworden, so dass wir hier einen eigenen Weg gegangen sind.

Die Anforderungsliste für die anzugehende programmtechnische Umsetzung entspricht im groben der oben aufgeführten Wunschliste.

Eine Ausnahme bildet die Kartenkomponente, hier haben wir OpenLayers3 den Vorzug vor unseren eigenen Entwicklungen gegeben. Vor allem das Vektorrendering ist hier sehr ausgefeilt. Die Programmschnittstelle ist sehr gut überlegt und nutzbar. Die TypeScript Vorgabe ist hier zwar nicht gegeben, aber durch die Kapselung in unsere API wiederrum  zumindest nach außen erfüllt.

Der Name KISS ist übrigens gleichzeitig einer der Leitsprüche, den wir bei der Umsetzung vor Augen haben wollen: „Keep it Simple and Stupid“