Standort Hagen Fachbereich Technische Betriebswirtschaft

Webtechnologie

Die Lehre von den Techniken des World Wide Web und von ihren Auswirkungen auf Wirtschaft und Gesellschaft

— Teil II: Fortgeschrittene Webtechniken und digitale Ökonomie —

Vorlesungsskript für das sechste Semester Wirtschaftsinformatik

Andreas de Vries

Version: 21. September 2021

Dieses Skript unterliegt der Creative Commons License CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/deed.de) Inhaltsverzeichnis

IV Fortgeschrittene Webtechniken und Konzepte 6

17 jQuery 7 17.1 Entstehungsgeschichte, Lizenz, Dokumentation ...... 7 17.2 Einbindung der Bibliothek ...... 8 17.3 Syntax ...... 8 17.4 DOM-Manipulation mit jQuery ...... 9 17.5 CSS-Formatierungen ...... 11 17.6 AJAX mit jQuery ...... 12 17.7 jQuery Mobile ...... 13

18 AngularJS 16 18.1 Grundlegende Konzepte ...... 16 18.2 Erste Beispiele: HTML wird (fast) eine Programmiersprache ...... 20 18.3 Grundelemente von AngularJS ...... 22 18.4 Erste Datenbankzugriffe mit AngularJS ...... 23 18.5 Single Page App mit Components und Datenbankzugriffen ...... 25 18.6 Angular ...... 30 18.7 Bewertung und Ausblick ...... 30

19 WebSockets 32 19.1 Das WebSocket Protokoll ...... 33 19.2 Die WebSocket API ...... 34 19.3 Programmierung eines WebSocket-Clients ...... 35 19.4 Anwendungsfälle ...... 38 19.5 Webkonferenzen mit WebRTC ...... 40

20 Webservices versus REST 44 20.1 SOA: automatisierte Dienste ...... 44 20.2 REST ...... 53

21 NoSQL: Big Data und verteilte Datenbanken 57 21.1 Das CAP-Theorem ...... 59 21.2 Typen von NoSQL-Datenbanken ...... 62 21.3 MapReduce ...... 63 21.4 Konsistentes Hashing ...... 66 21.5 Vektoruhren ...... 67

2 Webtechnologie 3

V Digitale Ökonomie 72

22 Die digitale Revolution 73 22.1 Drei Entwicklungen ...... 74 22.2 Kurze Wirtschaftsgeschichte ...... 75 22.3 Ökonomische Mechanik: Das Coase’sche Gesetz ...... 77 22.4 Web 2.0, vernetzte Mobilität und Big Data ...... 78 22.5 Die Generation Y ...... 80 22.6 Begriffsdefinition Digitale Ökonomie ...... 81 22.7 Geschäftsmodelle ...... 82

23 und seine Kerntechnologien 85 23.1 Wirtschaftliche Kennzahlen ...... 85 23.2 Suchmaschinen ...... 87 23.3 Der PageRank-Algorithmus ...... 87 23.4 Googleware und Cloud Computing ...... 91 23.5 Maschinelles Lernen mit TensorFlow ...... 95

24 97 24.1 Geschäftsmodell ...... 98 24.2 WhatsApp und die Internet.org Vision ...... 99 24.3 Wirtschaftliche Kennzahlen ...... 101 24.4 Informationstechnik ...... 101

25 Mathematik sozialer Netzwerke 103 25.1 Definition elektronischer sozialer Netzwerke ...... 103 25.2 Netzwerkstrukturen ...... 104 25.3 Wachstum von Netzen ...... 111 25.4 Netzwerkeffekte ...... 112 25.5 Systemische Risiken in Netzen ...... 120 25.6 * Ramsey-Zahlen ...... 124

26 Künstliche Intelligenz 129 26.1 Überblick, Einordnung und Begriffe ...... 130 26.2 Was ist Intelligenz? ...... 130 26.3 Rechenleistung von Mensch und Computer ...... 133 26.4 IBMs Ansatz mit Daten und Algorithmen ...... 135 26.5 Neuronale Netze und ...... 137 26.6 Sind KI-Systeme intelligent? ...... 142 26.7 Die Singularität ...... 144 26.8 Big Data: Korrelationen statt Kausalität ...... 144 26.9 Kybernetik: Messen, Steuern und Regeln von Verhalten ...... 145 26.10Ethik künstlicher intelligenter Systeme ...... 146 26.11Was müssen wir tun? ...... 149

27 Digitales Geld 151 27.1 Definition und Geschichte des Geldes ...... 151 27.2 Geld als Währung ...... 156 27.3 Spezifische Eigenschaften digitalen Geldes ...... 160 27.4 Bitcoin ...... 161 4 Andreas de Vries

28 Computer und Finanzmärkte 167 28.1 Geschichte ...... 167 28.2 Algorithmischer Handel ...... 172

Literatur 184

Index 185 Vorwort

Das vorliegende Skript führt das Skript Webtechnologie 1 – Grundlagen fort. Es werden zunächst fortgeschrittene Webtechniken behandelt, bevor Begriffe und Konzepte zum Grundverständnis der digitalen Ökonomie untersucht werden. Einen Schwerpunkt der fortgeschrittenen Webtechniken bilden die sogenannten Webframe- works, also Programmbibliotheken, die die Programmierung von Webanwendungen auf Server- und Clientseite vereinfachen, aber auch CSS-Bibliotheken. Es hat sich in den letzten Jahren ein wahrer „Zoo“ solcher Bibliotheken gebildet, basierend auf ganz verschiedenen Programmier- sprachen wie JavaScript, PHP, Java, ASP oder C++. Eine aktuelle Liste der meist verbreiteten findet man unter https://de.wikipedia.org/wiki/Liste_von_Webframeworks. In diesem Skript werden z.B. den wichtigen JavaScript-Bibliotheken jQuery und Angular jeweils ein Kapitel gewidmet. Die hier behandelten Themen sind Teil der in letzter Zeit aktuell gewordenen „Fullstack- Entwicklung“, die genau die integrative Sicht auf die verschiedenen Techniken zur Erstellung von Webauftritten teilt wie das vorliegende Skript. Als deutschsprachiges Darstellung dazu ist Ackermann (2021) sehr zu empfehlen.

Hagen, im September 2021 Andreas de Vries

5 Teil IV

Fortgeschrittene Webtechniken und Konzepte

6 17 jQuery

Kapitelübersicht 17.1 Entstehungsgeschichte, Lizenz, Dokumentation ...... 7 17.2 Einbindung der Bibliothek ...... 8 17.3 Syntax ...... 8 17.4 DOM-Manipulation mit jQuery ...... 9 17.5 CSS-Formatierungen ...... 11 17.6 AJAX mit jQuery ...... 12 17.7 jQuery Mobile ...... 13

JavaScript spielt in der professionellen Webprogrammierung eine ganz zentrale Rolle, insbe- sondere aufgrund seiner Fähigkeiten, DOM-Manipulationen und asynchrone HTTP-Requests dynamisch auszulösen. Da allerdings die dazu notwendigen Anweisungen in JavaScript recht aufwendig sind — mit Funktionen wie getElementById zur DOM-Manipulation oder dem im we- sentlichen immer gleichen Dreischritt zur Implementierung eines asynchronen HTTP-Requests — wurden immer wieder spezielle JavaScript-Bibliotheken entwickelt, um die Programmie- rung zu vereinfachen. Eine der wichtigsten und verbreitesten dieser Bibliotheken ist jQue- ry, das zu einem De-Facto-Standard der Webprogrammierung geworden ist: Nach W3Techs (http://w3techs.com/) wird jQuery auf fast 70 % aller Webauftritte eingesetzt.

17.1 Entstehungsgeschichte, Lizenz, Dokumentation jQuery wurde 2006 von John Resig veröffentlicht und ist seit April 2013 in der Version 2 verfügbar. Da diese Version nur noch mit modernen Browserversionen kompatibel ist (also insbesondere nicht mit dem Internet Explorer bis einschließlich Version 8), wird die Ver- sion 1 parallel weitergeführt. jQuery ist als freie Software unter der MIT-Lizenz (https: //tldrlegal.com/license/mit-license) verfügbar, darf also auch für kommerzielle Zwecke verwendet werden, wobei jede Kopie ihr Copyright beinhalten muss. Die API-Dokumentation von jQuery ist unter

http://api.jquery.com/ verfügbar, ein sehr gutes Tutorial unter http://www.w3schools.com/jquery/.

7 8 Andreas de Vries: Webtechnologie

17.2 Einbindung der Bibliothek

Da jQuery eine JavaScript-Bibliothek ist, benötigt man zur dessen Verwendung keine beson- dere Installation, sondern bindet es per Hyperlink in das HTML-Dokument ein. Die aktuellste Variante findet man unter

http://code.jquery.com/

Dort ist jede Version in einer „unkomprimierten“ und einer „minifizierten“ Fassung verfügbar. Die erste ist kommentiert und formatiert und somit gut lesbar, die andere ist unformatiert und ohne Kommentare, aber mit deutlich weniger Speicherbedarf. Die minifizierte Fassung eignet sich also zur reinen Nutzung besser als die unkomprimierte. Man kann nun die gewünschte Version der Bibliothek einfach auf den eigenen Server herunterladen und sie dann per Link einbinden, man kann aber auch die Originalbibliothek einfach verlinken. Die minifizierte Version 3.3.1 beispielsweise kann man im Head des HTML-Dokuments mit

einbinden. Empfohlen ist die Einbindung mit einer Überbrüfung der „Subresource Integrity“ des W3C:

17.3 Syntax

Basis einer jQuery-Anweisung ist der Aufruf der Funktion $, oder synonym jQuery, mit einem Selektor und einer Aktion:

$(Selektor).Aktion(...); oder synonym jQuery(Selektor).Aktion(...);

(Gebräuchlicher ist die Verwendung von $.) Der Selektor ist hierbei ein CSS-Selektor zur Auswahl eines oder mehrerer HTML-Elemente, die Aktion ist eine auszuführende Funktion aus der jQuery-Bibliothek. Für den Selektor gibt es im Wesentlichen vier Varianten, beispielhaft mit der Aktion hide() aufgelistet, die die ausgewählten HTML-Elemente per CSS verstecken lässt:

$("#test").hide() versteckt alle HTML-Elemente mit der ID "test". $(".test").hide() versteckt alle HTML-Elemente der Klasse "test". $("p").hide() versteckt alle

-Elemente. $(this).hide() versteckt das aktuelle Element (funktioniert normaler- weise nur innerhalb eines selektierten Elements);

Diese Anweisungen müssen in eine anonyme Funktion (auch „Callback-Funktion“ oder „Lambda- Ausdruck“ genannt) eingepackt werden:

$(function(){ $(document).ready(function(){ ... oder äquivalent ... }); }); §17 jQuery 9

und sollten im des HTML-Dokuments programmiert (bzw. als externe JS-Datei dort eingelesen) werden. Auf diese Weise wird garantiert, dass das gesamte Dokument vollständig geladen ist, bevor jQuery-Code ausgeführt wird. Ein Aufruf dieser Art entspricht dem in JavaS- cript oft verwendeten Programmiermuster IIFE (immediatley invoked function expression). Neben diesen „Selektor-Aktion“-Anweisungen kann man in jQuery auch direkt vordefinierte Nutzfunktionen durch

$.Nutzfunktion(...); oder synonym jQuery.Nutzfunktion(...); aufrufen. In der API-Dokumention (http://api.jquery.com/) sind die vorhandenen Nutzfunk- tionen mit

jQuery.Nutzfunktion (...) aufgeführt. Die auf selektierte Elemente möglichen Aktionen sind dagegen einfach mit

.Aktion (...) beschrieben.

17.4 DOM-Manipulation mit jQuery

Als erstes Programmbeispiel mit jQuery betrachten wir eine Version des Programms aus Kapitel 16 (Listing 16.2), das nach Klicken der Schaltfläche ein neues

  • -Element an die geordnete Liste
      hängt: Listing 17.1: DOM Manipulation mit jQuery 10 Andreas de Vries: Webtechnologie

        Ein direkter Vergleich der jQuery-Anweisungen mit einem äquivalenten Programm in „reinen“ JavaScript zeigt die Philosophie und die funktional orientierte Sicht von jQuery. Das jQuery Programm

        $(function() { $("button").click(function(){ // Event-Handler für alle Buttons console.log("$(this).val():" + $(this).val()); if ($(this).val() === "hinzufuegen"){ $("#liste") .append($("

      1. Die Zeichen an der Wand
      2. ")); } else if ($(this).val() === "loeschen"){ $("#liste") .children() .last() .remove(); } }); }); würde in JavaScript (fast) äquivalent wie folgt lauten:

        var modifizieren = function(aktion) { var wurzel = document.getElementById('liste');

        if (aktion === "hinzufuegen"){ var neu = document.createElement('li'); wurzel.appendChild(neu); var neuerText = document.createTextNode("Die Zeichen an der Wand."); neu.appendChild(neuerText); } else if (aktion === "loeschen"){ if (wurzel.hasChildNodes()) { wurzel.removeChild(wurzel.lastChild); } } }; mit den Ereignisbehandlern

        Im jQuery-Quelltext wird die objektorientierte API des DOM derart gekapselt, dass sie eine „fluente“ („fließende“) Programmierung hintereinandergeschalteter Funktionen erlaubt, wie in Zeile 15 bis 17 in Listing 17.1. Außerdem brauchen die Ereignisbehandler nicht mehr im HTML- Quelltext in den betreffenden Elementen implementiert zu werden, sondern über die Selektoren ausschließlich in JavaScript. Damit ist eine saubere Trennung zwischen der Ablaufdynamik und den HTML-Inhalten möglich. §17 jQuery 11

        17.5 CSS-Formatierungen

        Etwas einfacher und auch durchweg gebräuchlicher als direkte DOM-Manipulationen, wie im vorigen Abschhnitt besprochen, sind dynamische Veränderungen von Formatierungen über CSS. Hier stehen in jQuery mit hide, show und toggle (umschalten) drei wirkmächtige Funktionen zur Verfügung, die hier stellvertretend für dynamische Effekte aufgelistet seien. Die Funktionen modifizieren dabei gar nicht die Struktur des DOM, sondern ändern lediglich die style-Attribute der HTML-Elemente. Als Beispiel sei das folgende jQuery-Programm gelistet, das durch Klicken der Schaltfläche „Umschalten“ bewirkt, dass alle Abätze des HTML-Dokuments angezeigt werden oder nicht: Listing 17.2: Zeigen und Verbergen von HTML-Elementen mit jQuery

        Dies ist ein erster Absatz.

        Dies ist ein anderer kleiner Absatz.

        Untersucht man die HTML-Elemente mit den Entwicklertools des Browsers, so erkennt man, dass lediglich das style-Attribut aller

        -Elemente verändert wird, entweder von

        • Clyde
        • Fred
        • Bonny
        Lassen Sie das Programm ablaufen und beobachten Sie dabei im Entwicklertool des Firefox („Inspector“) oder des Chrome Browsers („Elements“) die sich dynamisch verändernden Ein- stellungen der CSS-Anweisungen!

        17.6 AJAX mit jQuery

        Die einfachste Möglichkeit zur Implementierung von AJAX-Ereignissen ist über die Nutzfunk- tion $.ajax (bzw. jQuery.ajax). Es gibt zwei Versionen (siehe http://api.jquery.com/jQuery. ajax/), die gebräuchlichere erwartet als Arguent ein JSON-Objekt setting mit den Einstellungen der asynchronen HTML-Anfrage:

        • type: Die Methode der HTML-Anfrage, also "GET" oder "POST"

        • url: Der URL der HTML-Anfrage

        • data: Die zu übermittelnden Daten der HTML-Anfrage,

        • success: Der Ereignisbehandler bei Erfolg der HTML-Anfrage.

        Beispielhaft sei hier ein einfacher asynchroner Aufruf des Spiegelskripts auf Hägar beschrieben: Listing 17.4: AJAX mit jQuery §17 jQuery 13

        Während also mit jQuery ein einziger Funktionsaufruf zur Erzeugung der asynchronen HTTP- Anfrage genügt,

        $.ajax({ type: "POST", url: "http://haegar.fh-swf.de/AJAX/spiegel.php", data: "y=x^2-1&x=1", success: function(response){ $("#ausgabe").html("

        Serverantwort

        " + response); } }); muss man in JavaScript für denselben Zweck 7 Anweisungen programmieren:

        var request = new XMLHttpRequest(); request.onreadystatechange = function() { // Event Handler if (request.readyState === 4 && request.status === 200) { document.getElementById("ausgabe").innerHTML = "

        Serverantwort

        " + request.response; } }; request.open("POST", "http://haegar.fh-swf.de/AJAX/spiegel.php"); var data = new FormData(); data.append("y","x^2-1" ); data.append("x",1); request.send(data); Zu beachten ist dabei, dass in jQuery die AJAX-Anweisungen aufgrund der verzögerten Aus- führung im des Dokuments programmiert werden können, während die reinen Java- Script-Anweisungen nach dem

        -Element geschrieben werden sollten, also wenn es zum Ausführungszeitpunkt bekannt ist, oder als Funktionsaufruf des Ereignisbehandlers onload im -Element. Eine genauere Beschreibung der für die Funktion $.ajax möglichen Parameter sind in der API-Dokumentation unter

        http://api.jquery.com/jquery.ajax/ beschrieben. Die wichtigsten Parameter sind bereits in obigem Listing 17.4 aufgeführt. Bemer- kenswert ist außerdem der Parameter dataType, der als Standard per Intelligent Guess eines der Formate xml, json, script (für JavaScript-Quelltext) oder html auswählt.

        17.7 jQuery Mobile jQuery Mobile ist eine für Wischgesten optimierte JavaScript-Bibliothek, die auf jQuery und auf eine spezifische CSS-Bibliothek aufbaut. Sie ist kompatibel mit den gängigen Smartphones und Tablets. Sie erlaubt es durch gekapseltes JavaScript, vorwiegend mit HTML-Elementen und geeigneten Attributen dynamische Apps zu programmieren. Als ein einführendes Beispiel sei die folgende App, die zwei miteinander verlinkte Seiten mit einfachen Effekten darstellt: 14 Andreas de Vries: Webtechnologie

        Listing 17.5: Eine zweiseitige App für mobile Endgeräte

        jQuery Mobile Example

        Welcome To My Homepage

        Welcome!

        I’ glad to be a mobile app developer.

        If you click on the link below, it will take you to Page Two.

        Go to Page Two

        Footer Text

        Welcome To My Homepage

        Now you’re on Page Two.

        Click me - I'm collapsible!

        I'm not expanded by default.

        If you click on the link below, it will take you to Page Two.

        Go to Page One

        Footer Text

        Die App ist verfügbar unter

        http://haegar.fh-swf.de/Webtechnologie/jQuery-mobile.html

        Testen Sie sie mit Ihrem mobilen Endgerät oder mit den Entwicklertools des Google Chrome! Im des Dokuments werden die notwendigen CSS- und JavaScript-Bibliotheken gela- den, bevor mit

        -Elementen über das Attribut data-role die Struktur einer Seite festgelegt wird:

        ...
        §17 jQuery 15

        ...

        ...

        Jedes

        -Element mit der data-role="page" sollte dabei eine eigene ID bekommen. Die Rollen von "header", "main" und "footer" sind (hoffentlich) selbsterklärend und können bei Betrachtung der App nötigenfalls erschlossen werden. Weitere Informationen: Die Dokumentation zur API befindet sich unter

        http://api.jquerymobile.com/, ein gutes Tutorial unter http://www.w3schools.com/jquerymobile/. 18 AngularJS

        Kapitelübersicht 18.1 Grundlegende Konzepte ...... 16 18.1.1 Einzelseiten-Webanwendungen ...... 16 18.1.2 Model-View-ViewModel (MVVM) ...... 17 18.1.3 Datenbindung (data binding)...... 18 18.1.4 Dependency Injection ...... 18 18.2 Erste Beispiele: HTML wird (fast) eine Programmiersprache ...... 20 18.3 Grundelemente von AngularJS ...... 22 18.4 Erste Datenbankzugriffe mit AngularJS ...... 23 18.5 Single Page App mit Components und Datenbankzugriffen ...... 25 18.5.1 Bindings ...... 26 18.5.2 Beispielprogramm ...... 26 18.6 Angular ...... 30 18.7 Bewertung und Ausblick ...... 30

        AngularJS ist eine clientseitige JavaScript-Bibliothek zur Erstellung von Einzelseiten-Weban- wendungen nach dem Entwurfsmuster Model View ViewModel (MVVM). AngularJS wird seit 2009 von Google als quelloffenes Projekt entwickelt. Wichtigste Eigenschaften von AngularJS sind die Zwei-Wege-Datenbindung zum Abgleich von Darstellung und Daten, und Dependency Injection zur Auflösung von Abhängigkeiten zwischen verschiedenen Komponenten. Sie stellen jede für sich sehr moderne Konzepte der Programmierung und des Software Engineering dar und werden daher in einem ersten Abschnitt kurz theoretisch behandelt. AngularJS ist flexibel erweiterbar durch sogenannte Services zur Erstellung eigener Routinen und Algorithmen und durch Direktiven zur Erstellung wiederverwendbarer HTML-Elemente.

        18.1 Grundlegende Konzepte

        18.1.1 Einzelseiten-Webanwendungen

        Eine Einzelseiten- oder Single-Page-Webanwendung (englisch Single-page Web Application, SPA) ist eine Webanwendung, die aus einem einzigen HTML-Dokument besteht und deren Inhalte dynamisch nachgeladen werden. Diese Art von Web-Architektur steht im Gegensatz

        16 §18 AngularJS 17 zu klassischen Webanwendungen, welche aus mehreren, untereinander verlinkten HTML-Do- kumenten bestehen. Eine Einzelseiten-Webanwendung ermöglicht eine Reduzierung der Ser- verlast, gibt dem Anwender das Gefühl einer klassischen Desktopanwendung und erlauben die Umsetzung von selbständigen Webclients, die auch temporär offline verwendbar sind. Insbeson- dere aus letzterem Grund eignen sie sich für den Einsatz in störanfälligen und oft unterbrochenen Verbindungen mobiler Endgeräte. Die Informationen dieses Kapitels basieren vor allem auf dem Buch1 sowie auf der Website http://www.w3schools.com/angular/.

        18.1.2 Model-View-ViewModel (MVVM) Eines der wichtigsten Architekturmuster des Software Engineering ist das Model-View-Con- troller (MVC). Es zählt zu den Mustern der interaktiven Systeme, die allgemein Mensch-Ma- schine-Interaktion strukturieren. In den 1980er Jahren von Trygve Reenskaug für die Program- miersprache Smalltalk entwickelt, trennt es die Verantwortlichkeiten von Datenhaltung (Model), Darstellung (View) und Ablauflogik (Controller) und lagert sie in separate Schichten aus. Siehe dazu Abbildung 18.1 (rechts). In einer dynamischen Webanwendung kann die strikte Trennung von Ablauflogik (Con- troller) und Darstellung (View) allerdings nicht aufrecht erhalten werden, da der Controller HTML-Code generieren muss, der grundsätzlich Teil der View-Komponente ist. Damit trägt aber am Ende der Server die Hauptlast der Webanwendung, worunter die Interaktivität und das Antwortverhalten bei hoher Nutzung leiden kann, während der Browser vergleichsweise wenig zu tun hat. Er ist in diesem Falle nur noch ein sogenannter Thin Client. Mit dem Muster Model-View-ViewModel (MVVM) wird der Controller durch eine Proxy- Schicht auf dem Client (!) ersetzt, die ViewModel genannt wird. Dorthin werden lediglich

        Model Model

        Daten- Daten- UPDATE / SELECT transformation persistierung INSERT

        Browser ViewModel Controller Server

        Zwei-Wege- View- Datenbindung funktionalität Request

        View View

        Anwender Anwender

        Abbildung 18.1: Das MVVM-Muster (links) für eine Webanwendung, im Vergleich dazu das MVC-Muster (rechts). Da bei MVC die Hauptlast der Webanwendung auf dem Server läuft, ist der Browser in diesem Fall ein Thin Client. Bei MVVM dagegen hat er mit der Poxy-Schicht MVVM einen großen Teil der Arbeitslast und ist daher in diesem Fall ein Fat Client. diejenigen Daten geliefert, die tatsächlich für die Anzeige gebraucht werden. Oft müssen die Daten auch auf bestimmte Art und Weise transformiert werden, bevor sie zur Anzeige kommen; auch hierfür ist das ViewModel zuständig. Außerdem definiert es die innerhalb der Anzeige benötigte Funktionalität: Dort müsste beispielsweise ein Ereignisbehandler definiert werden, der auf einen Button-Klick reagiert.

        1Tarasiewicz und Böhm (2014). 18 Andreas de Vries: Webtechnologie

        So plausibel das MVVM-Muster auch auf den ersten Blick erscheint, wirft es sofort ein großes Problem auf: die Datenredundanz zwischen Model, ViewModel und View. Wie kann dieses Problem gelöst werden? Betrachten wir dazu im nächsten Abschnitt einen Ansatz, der sich als großenteils erfolgreich realisierbar herausgestellt hat.

        18.1.3 Datenbindung (data binding) Aufgrund der engen Verzahnung von Model, ViewModel und Model und dadurch implizier- ten grundsätzlichen Datenredundanz ergibt sich sofort das Problem der Synchronisation der Schichten. D.h. jede Datenaktualisierung, sei sie im Model durch die Datenbank oder im View durch eine Anwendereingabe, muss in den jeweils anderen Schichten nachvollzogen werden. Ansonsten kann es sehr schnell zu Inkonsistenzen der Daten kommen, beispielsweise weil mitt- lerweile ein Anwender einen Dateninhalt geändert hat, den etwas später ein anderer verändern will: Hat zum Beispiel ein Anwender den letzten vorhanden Artikel im Bestand gekauft, so muss das ViewModel jedes anderen Anwenders sofort angepasst werden, sonst wird dieser Artikel möglicherweise mehrfach verkauft. Als ein Konzept zur Lösung dieses Synchronisationsproblems des MVVM-Musters hat sich die Datenbindung, vor allem die „Zwei-Wege-Datenbindung“, etabliert. Wir werden dieses gleich im nächsten Programmierbeispiel betrachten. Die Zwei-Wege-Datenbindung ist im MVVM ein Mechanismus zur automatischen Synchronisation von Viewmodell und View bei Änderung von Daten, sei es durch den Nutzer in der View oder durch andere Nutzer oder Prozesse im mit dem Model synchronisierten Viewmodell. Normalerweise muss man eine solche Datenbindung zwischen den Schichten mühsam pro- grammieren. Beispielsweise müssen für alle eingaberelevanten DOM-Elemente jeweils extra ein Ereignisbehandler registriert werden, der die betroffenen Variablen des Models ändert. Entsprechend muss auch die Logik des umgekehrten Weges programmiert werden, also die Ak- tualisierung der DOM-Elemente nach einer Änderung des Daten des Models. Auf diese Weise entsteht bereits für relativ einfache Anwendungen jede Menge sogenannter „Boilerplate-Code“ (etwa „Textbaustein-“ oder „Klebe-Code“), der die eigentliche Anwendungslogik verschmutzt.

        18.1.4 Dependency Injection Ein grundlegendes Problem komponentenbasierter Softwaresysteme, die wartbar, testbar und komponentenweise austauschbar sein sollen, ist die Auflösung von Abhängigkeiten der Kompo- nenten untereinander. Eine einfache Abhängigkeit ist bereits gegeben, wenn eine Komponente eine andere für ihren Ablauf benötigt. In einer objektorientierten Programmiersprache beispiels- weise wäre dies der Fall, wenn ein Objekt zu seiner Erzeugung ein anderes verwendet. Durch solche Abhängigkeiten kann ganz schnell ein verschlungenes Netz von Abhängigkeiten entste- hen, das eine Modifikation des Softwaresystems oder den Austausch einzelner Komponenten praktisch unmöglich macht. Im Software Engineering hat sich daher in den 2000er Jahren das auf Martin Fowler2 zurück gehende Entwurfsmuster der Dependency Injection (DI) etabliert. Ihr liegt das abstrakte Prinzip der Umkehrung des Kontrollflusses (Inversion of Control (IoC)) zugrunde, also zum Beispiel eine Umkehrung der Aufrufe von Funktionen oder der Ablaufsteuerung eines Programms. (Ge- treu dem Hollywood-Prinzip, “Don’t call us, we’ll call you!”3) Eine typische Realisierung dieses Prinzips sind beispielsweise Event Handler, da sie Funktionen implementieren, deren Aufruf nicht in der Anwendung selbst geschieht, sondern aus einer der Programme der API-Bibliothek

        2Fowler (2004). 3Fowler (2005). §18 AngularJS 19 erfolgt, initiert von einem spontanen Event. Ermöglicht wird eine solche Umkehrung des Kon- trollflusses beispielsweise durch Interfaces, Plug-Ins oder Callback-Funktionen. Ein anderes

        var callback = function (x) { return x*x; } [1, 2, 3].map(callback);

        Hauptprogramm

        [...] callback calls calls

        map API

        Abbildung 18.2: Inversion of Control durch eine Callbackfunktion.

        Beispiel für eine Kontrollflussumkehrung ist eine serverseitig programmierte Webanwendung, wie etwa mit PHP, da die Ausführungsverantwortung beim Server liegt, die Initiierung und das Ergebnis des Kontrollflusses jedoch beim Client4. Das Entwurfsmuster der Dependency Injection oder der automatischen Übergabe von Ab- hängigkeiten nun ist eine spezielle Form der Kontrollflussumkehrung und besagt, dass eine Komponente ihre Abhängigkeiten von anderen Komponenten nicht selbst erzeugt, sondern von einer zentralen Komponente des Systems, dem „Assembler“, übergeben bekommt5. Dadurch können Abhängigkeiten zwischen Komponenten also ausschließlich durch die zentrale Kom- ponente erzeugt und damit zentral aufgelöst werden. Eine Möglichkeit dafür ist die zentrale Bereitstellung einer Klasse für die Abhängigkeit sowie einer Schnittstelle, die von abhängigen Klassen implementiert werden muss, um zur Laufzeit die Abhängigkeiten zur Verfügung gestellt zu bekommen:

        Listing 18.1: Einfache Implementierung einer Dependency Injection in Java interface Injizierbar { public void injiziere(Abhängigkeit abhängigkeit); }

        class Abhängiges implements Injizierbar { private Abhängigkeit abhängigkeit;

        public void injiziere(Abhängigkeit abhängigkeit) { this.abhängigkeit = abhängigkeit; } }

        public class Injizierer { public static void main(...) { Abhängigkeit abhängigkeit = ...; Injizierbar abhängiges = new Abhängiges(...); abhängiges.injiziere(abhängigkeit); } }

        4Tarasiewicz und Böhm (2014):§2.1.3. 5Fowler (2004). 20 Andreas de Vries: Webtechnologie

        Die Klasse Injizierer kann hier die Abhängigkeit über deren Konstruktor spezifizieren und zu- sätzlich aus möglicherweise mehreren injizierbaren Klassen auswählen (solange sie die Schnitt- stelle implementieren). Mit der automatischen Übergabe von Abhängigkeiten weist ein Softwaresystem eine lose Kopplung der Komponenten auf. Lose Kopplung führt dazu, dass Änderungen in einer Kompo- nente keine Änderungen in einer anderen Komponente bedingen, wenn die Schnittstelle unver- ändert bleibt. Lose Kopplung ist daher eine hinreichende Bedingung für maximale Wartbarkeit und Testbarkeit eines Systems gegebener Komplexität.

        18.2 Erste Beispiele: HTML wird (fast) eine Programmier- sprache

        Genug der Theorie, wie kann man denn nun mit AngularJS programmieren? In diesem Abschnitt werden wir einführende Programmbeispiele vorstellen, die die Datenbindung verwenden, aber auch ein Schleifenkonstrukt und eine (Art) Selektionsstruktur kennenlernen. Dadurch wird HTML scheinbar zu einer vollständigen Programmiersprache, in Wirklichkeit ist es natürlich JavaScript, aber aufgerufen durch erweiterte HTML-Attribute, die sogenannten Direktiven. Betrachten wir zunächst ein Programm mit AngularJS, das das Prinzip der Datenbindung (data binding) illustriert.

        Listing 18.2: Beispiel einer Datenbindung in AngularJS

        Gib einen Text ein:

        {{ eingabe }}

        Zunächst sehen wir, dass die Bibliothek im in Zeile 5 eingebunden wird. Der Kern des Programms besteht aus den Zeilen 10 bis 13:

        {{ eingabe }}

        Mit der Direktive ng-app, also ein „künstliches“ HTML-Attribut, wird eine Applikation in AngularJS initialisiert, hier ist es die als Standard vorhandene namenlose Applikation. Eine Applikation muss stets bereits mit ihrem Namen definiert sein, um sie über diese Direktive damit aufrufen zu können. Mit der Direktive ng-model wird eine Variable in AngularJS festgelegt, §18 AngularJS 21

        hier ist es die Variable eingabe, die den Wert des -Elements erhält. In dem Ausdruck (expression)

        {{ eingabe }} schließlich wird der aktuelle Wert der Variable ausgegeben. Hier ist es eingepackt in ein

        - und ein tt-Element zur Ausgabe in Schreibmaschinenschrift. Was geschieht in diesem Programm? Gibt der Anwender in dem Eingabefeld einen Text ein, so wird nach jedem Tastendruck der aktualisierte Wert der Variable angezeigt. Man hat also in dem HTML-Dokument zu jedem Zeitpunkt in zwei verschiedenen Elementen denselben Wert stehen, es handelt sich um eine (hier noch einfache) Datenbindung. Die Datenbindung ist eine mächtige Technik und ermöglicht mit relativ wenig Quelltext bemerkenswerte Effekte. So wird im nächsten Beispielprogramm ein Farbenwähler erstellt, der durch Schiebereglern festgestellte Farben nach dem RGBA darstellt.6 Listing 18.3: 2-Wege-Datenbindung in AngularJS: Ein Farbenwähler (nach Tarasiewicz und Böhm (2014:§1.1)) R:
        G:
        B:
        A:

        Hier wird in Zeile 7 die Angularapplikation für das gesamte -Element definiert. Hier werden auch mit der Direktive ng-init die Werte der verwendeten Variablen r, g, b und a initialisiert. Die entsprechenden Schiebereglern (Zeilen 8 bis 11) werden über die Direktive ng-model mit diesen Werten voreingestellt und im

        -Element mit Hilfe der CSS-Funktion rgba als Farbe dargestellt. Im letzten Beispielprogramm dieses Abschnitts wird über die Direktive ng-repeat eine Schleife zum Durchlaufen eines Arrays erzeugt, die alle Einträge ausgibt, sowie eine zweite Schleife, die bestimmte Elemente des Arrays filtert, also selektiert. Damit bietet AngularJS, zumindest auf den ersten Blick, alle Kontrollstrukturen einer vollständigen Programmiersprache in HTML-Syntax. Aber es gibt Einschränkungen. Aber zunächst das Programm:

        Listing 18.4: Beispiel einer Schleife in AngularJS

        6RGBA erweitert das RGB-Farbmodell mit den Werten für Rot, Grün und Blau jeweils ganzzahlig zwischen 0 und 255 um den Alphawert U zwischen 0 und 1, der die Transparenz der Farbe festlegt (0: transparent, also unsichtbar, 1: nicht transparent, also opak). 22 Andreas de Vries: Webtechnologie

        {{ wort }}

        {{ wort }}

        Es gibt als

        -Überschrift „Hallo Welt, hallo Angular!“ aus, und in dem

        -Element das gefilterte Wort „Angular!“. Das ergibt sich, da in Zeile 6 die Angularapplikation mit dem Array woerter und vier Einträgen initialisiert wird und die Direktive ng-repeat als eine foreach- Schleife durch das Array woerter läuft. In Zeile 8 wird dieselbe Schleife mit | filter: ... durchlaufen, also einem Filter. Ein Filter übernimmt in der funktionalen Programmierung die Rolle der Selektion, also der if-Anweisung der imperativen Programmierung. Ein Problem ergibt sich bei gleichen Einträgen des Arrays, AngularJS bricht dann die Verarbeitung ab und ... gibt nichts aus, was die Fehlersuche nicht gerade vereinfacht. Man muss in diesem Falle bei der Direktive ng-repeat zusätzlich die Option track by $index angeben:

        {{wort}}

        Der doppelte Eintrag ist hier das Wort „ich“. In diesem Beispiel wird überdies die Direktive ng-bind benutzt, die eine ähnliche Wirkung wie ein {{}}-Ausdruck hat. Obwohl etwas umständ- licher in der Schreibweise, sollte sie bei komplexeren Webanwendungen bevorzugt werden, da sie als ein Elementattribut die Datenbindung erst anzeigt, wenn die Seite geladen ist. In extre- men Fällen kann es dagegen bei einem {{xyz}}-Ausdruck passieren, dass er vor Vollendung des Ladens unausgewertet angezeigt wird, also wörtlich als „{{xyz}}“. Weitere Hinweise zur Direktive ng-repeat findet man in der Dokumentation der API https: //docs.angularjs.org/api/ng/directive/ngRepeat, zur Direktive ng-bind siehe https://docs. angularjs.org/api/ng/directive/ngBind. Ist also HTML mit AngularJS eine vollständige Programmiersprache wie Java, JavaScript oder PHP? Immerhin ermöglicht die HTML-Syntax Schleifen und Selektionen. Die Antwort ist Nein, da es, vereinfacht gesagt, keine while-Schleife gibt: Eine Programmiersprache muss die Mächtigkeit haben, Algorithmen auszuführen, die potenziell unendlich lang laufen können.7 Das ist mit AngularJS nicht möglich.

        18.3 Grundelemente von AngularJS

        Zunächst sei als Standardreferenz die Dokumentation der API von AngularJS erwähnt:

        https://docs.angularjs.org/api/

        AngularJS basiert auf den folgenden Grundelementen, siehe Abbildung 18.3. Das übergreifende Strukturelement in AngularJS bilden Module. Sie kapseln zusammenhängende Anwendungs- komponenten und dienen als Container für Controller, Routen, Services, Direktiven und Filter. Modulen in AngularJS können im Sinne der Dependency Injection bequem andere Module als Abhängigkeiten einbinden. Sofern diese Module zuvor in einem 24 Andreas de Vries: Webtechnologie

        VornameNameURI
        {{ eintrag.vorname }} {{ eintrag.name }} {{ eintrag.web }}

        Listing 18.6: Das serverseitige PHP-Skript, das in Listing 18.5 aufgerufen wird.

        if (isset($_GET['action']) && $_GET['action'] == "list"){ $mysqli = new mysqli("localhost", "user", "c5dDC8VJemscKPQS", "AdressDB"); $mysqli->query("SET CHARACTER SET'utf8'" ); $mysqli->query("SET NAMES'utf8'" );

        $sql = "SELECT * FROM adressen"; $result = $mysqli->query("SELECT * FROM adressen");

        $array = array(); while ($adresse = $result->fetch_assoc()) { $array[] = $adresse; } echo json_encode($array); } ?>

        Hier wird in den Zeilen 7 bis 17 das Modul addressApp erzeugt und ihr sofort der Controller lstCtrl hinzugefügt:

        var addressApp = angular.module('addressApp', []); addressApp.controller('listCtrl', function($scope, $http) { ... });

        Der Controller wiederum besteht aus einer Funktion, die den Angularservice $http aufruft. Er ist in https://docs.angularjs.org/api/ng/service/$http dokumentiert und erwartet ein JSON-Objekt mit den Attributen method und url:

        $http({ method: "GET", url: "http://..." }).then(function success(response) { $scope.response = response.data; }, function error(response) { §18 AngularJS 25

        $scope.response = response.statusText; }); }); Die Funktion ist ein Promise8, also eine asynchron aufgerufene Funktion, auf deren Resultat eine then-Funktion mit zwei Callbackfunktionen reagiert, eine für den Erfolgsfall und eine für den Fehlerfall. Die Konstruktion mit der then-Funktion ist also die Entsprechung der Ausnah- mebehandlung mit try-catch in der synchronen objektorientierten Programmierung.

        18.5 Single Page App mit Components und Datenbankzugrif- fen

        In diesem Abschnitt erstellen wir eine kleine Single-Page App (SPA) mit Components. Com- ponents sind in AngularJS als Teil eines Moduls implementierbar und lehnen sich an die Web- Components an, das sind selbst definierbare HTML-Tags. In AngularJS hat jede Component einen Namen und bezieht sich damit auf HTML-Tags, die jeden Großbuchstaben durch einen Bindestrich und den entsprechenden Kleinbuchstaben ersetzt. Die Component "adressenListe" beispielsweise wird mit den Tags

        ... verwendet. Sie wird in AngularJS mit der Funktion component eines Moduls definiert und neben dem Namen mit einem Objekt

        { templateUrl: "...", controller: function(...) {...}, bindings: {...} } versehen, das die Adresse der Templatedatei, den Controller und optional die Bindung zu im- portierenden oder exportierenden Daten benennt. In AngularJS zeichnet sich eine Component grundsätzlich dadurch aus, dass alle Daten nur innerhalb ihres Controllers gültig sind, ein- und ausgehende Datenflüsse sowie von der Component gefeuerte Ereignisse müssen über das Bindings-Objekt definiert werden. Als Konsequenz ist die $scope-Variable von AngularJS als öffentliches Objekt in einer Component wirkungslos. Stattdessen muss im entsprechenden Tem- plate mit $ctrl auf den Controller mit seinen Properties zugegriffen werden (Abbildung 18.4). Hierbei ist innerhalb einer Component auch gewährleistet, dass immer nur auf das passende

        $ctrl bindings $ctrl ←→

        Abbildung 18.4: Verantwortlichkeitsbereiche (Scopes) zweier verschachtelter Components und der Datenbin- dungen zwischen ihren Controllern ($ctrl).

        Controllerobjekt $ctrl zugegriffen wird. Für weitere Details zu Components siehe den Developer Guide von AngularJS, https: //docs.angularjs.org/guide/component.

        8https://docs.angularjs.org/api/ng/service/$q#the-promise-api 26 Andreas de Vries: Webtechnologie

        18.5.1 Bindings Üblicherweise können in AngularJS Daten an irgendeiner Stelle verändert werden und sind mit der 2-Wege-Bindung auch überall verändert. In Components wird mit diesem allgemeinen Grundsatz gebrochen, eine Component soll nur diejenigen Daten ihres lokalen Zuständigkeits- bereichs ändern können. Nur so kann in einer komplexen Anwendung nachverfoĺgt werden, wer welche Daten wann verändert hat. Für Components in AngularJS gelten daher folgende Konventionen:

        • Eingaben in eine Component sollten mit den Binding < für aus der Elternkomponen- te eingehende Daten (Einwegbindung) versehen werden, beispielsweise für ein Objekt adresse:

        bindings: { adresse: '<' }

        • Ausgaben an die Elternkomponente werden mit den Binding & definiert, typischerweise als in der Component gefeuerte Ereignisse. Beispielsweise würden die in den Funktionen onUpdate oder onDelete des Controllers der -Komponente gefeuerten Ereignisse

        bindings: { onUpdate: '&', onDelete: '&' }

        in der Elternkomponente die Ereignisbehandler on-update oder on-delete aufru- fen, wenn sie dort mit

        ...

        angegeben werden. Hierbei sind die drei Punkte in Anführungszeichen jeweils die zustän- digen Ereignisbehandler im Controller der -Komponente.

        18.5.2 Beispielprogramm Mit Components lässt sich nun eine webbasierte Single-Page App programmieren, indem ei- nerseits gleich mit dem Startaufruf alle Components aufgebaut werden, allerdings mit den Direktiven ng-hide bzw. ng-show abhängig von dem aktuellen Wert von Schaltervariablen des zuständigen Controllers angezeigt bzw. verborgen werden. Abhängig von spezifischen Ereignis- behandlern, beispielsweise über die Direktive ng-click können diese Schaltervariablen verän- dert werden. Eine Beispielanwendung ist mit den folgenden Listings gegeben. Zunächst de Datei index.html, die das Viewmodel implementiert: Listing 18.7: Die Index-Seite der App 28 Andreas de Vries: Webtechnologie

        Hier wird das Modul sowie seine beiden Components definiert. Die Component adressenListe wird ab Zeile 10 definiert, Die erste ist zur Darstellung der gesamten Adressenliste zustän- dig und enthält den Controller zur Steuerung der Datenbindung zum Model. Die Component adressenDetail ab Zeile 36 ist zur Anzeige und Editierung einer einzelnen Adresse verantwort- lich und hat einen Controller, der die Anzeige über einen Schalter editMode zur Editierung ein- oder ausschaltet. Über die Bindungen (Zeile 50 bis 53) wird ein Objekt adresse von außen importiert und ein Ereignis onUpdate nach außen gefeuert. Aus diesem Viewmodel ergibt sich noch nicht unbedingt die Hierarchie der Components, sie wird durch den HTML-Teil der Indexdatei und durch die beiden Templates im Unterverzeichnis templates festgelegt. Betrachten wir die Templates zunächst im Detail: Listing 18.8: Template zur Ansicht der Adressliste

        Adressen

        VornameNachnameURIE-Mail
        {{ adresse.vorname }} {{ adresse.name }} {{ adresse.web }} {{ adresse.email }}
        Und: Listing 18.9: Template zum Editieren einer Adresse




        Das erste Template ist zur Darstellung der vollständigen Adressliste vorgesehen, das ande- re zur editierbaren Darstellung einer einzelnen Adresse. Zusammen mit dem HTML-Teil der §18 AngularJS 29

        index.html ergibt sich dadurch die folgende Grobstruktur der Components in der View:

        Adressen

        ... ...
        Der Datenbankkonnektor auf Serverseite schließlich ist in Listing 18.10 angegeben. Listing 18.10: Das serverseitige PHP-Skript, das in Listing 18.7 aufgerufen wird.

        $db = "AdressDB"; $table = "adressen";

        $mysqli = new mysqli("localhost", "user", "c5dDC8VJemscKPQS", $db); $mysqli->query("SET CHARACTER SET'utf8'" ); $mysqli->query("SET NAMES'utf8'" );

        if ($_GET['action'] === "list"){ $sql = "SELECT * FROM $table"; $result = $mysqli->query($sql); $array = array(); while ($entry = $result->fetch_assoc()) { $array[] = $entry; } echo json_encode($array); } else if ($_GET['action'] === "update"){ $entry = json_decode($_GET['json']); $sql = "UPDATE $table SET" ;

        foreach ($entry as $key => $value) { if ($key === "\$\$hashKey") continue; if ($key === "id"){ $where = " WHERE id=$value"; continue; } $sql .= " $key='$value',"; } // Delete last comma: $sql = substr($sql, 0, strlen($sql) - 1); 30 Andreas de Vries: Webtechnologie

        $sql .= $where; $mysqli->query($sql); } ?>

        Bekommt er per $_GET als Aufrufparameter action=list, so selektiert er alle Adressen der Datenbank und gibt sie als JSON-String an die Applikation aus, während mit action=update ein Parameter json mit der zu ändernden Adresse als JSON-Objekt erwartet wird.

        18.6 Angular

        AngularJS wird nur noch bis Ende 2021 unterstützt. Seit 2016 basiert Angular basiert auf der Programmiersprache TypeScript. TypeScript ist abwärtskompatibel zu JavaScript, ermöglicht aber im Gegensatz zu JavaScript:

        • klassenbasierte objektorientierte Programmierung

        • statische Typisierung

        • Generics

        Die wesentlichen Unterschiede zu AngulaJS sind:

        • Angular kennt keine expliziten „scopes“ oder Controller mehr, sondern verwendet eine Hierarchie von Komponenten als zentrales Architekturkonzept.

        • Angular hat eine einfachere Syntax für Ausdrücke: Mit „[...]“ werden Bindings für Eigen- schaften erzeugt, und mit „( )“ Bindings für Events.

        Nähere Informationen und weiterführende Quellen finden Sie unter

        https://de.wikipedia.org/wiki/Angular.

        Um Webanwendungen mit TypeScript zu entwickeln, verwendet man üblicherweise die Entwicklungsplattform Angular CLI (CLI: “command line interface”). Sie ermöglicht es, die TypeScript-Programme in eine lauffähige Website auf Basis von JavaScript zu übertragen. Benötigt werden dazu der Webserver node.js und das Paket ng. Weitere Informationen, auch zur Installation, sind zu finden unter

        https://cli.angular.io/.

        18.7 Bewertung und Ausblick

        Es ist immer ein gewisses Risiko, ein neues Programmierkonzept oder eine aktuelle Softwa- rebibliothek in ein Lehrwerk aufzunehmen. Insbesondere trifft dies zu, wenn es sich wie bei AngularJS um ein Framework handelt, das nicht standardisiert oder auf andere Art und Weise übergeordnet legitimiert ist. So ist die Gefahr nicht vollkommen ausgeschlossen, dass zu dem Zeitpunkt, zu dem Sie diese Zeilen lesen, AngularJS bereits als veraltet gilt und ganz andere Konzepte zu empfehlen sind. Für ein Lehrwerk, das auf die praktischen Probleme der Zukunft vorbereiten und das dafür notwendige Handwerkszeug bereit stellen möchte, wäre das Aufzeigen einer fachlichen Sackgasse oder eines inhaltlichen Irrweges nicht zielführend. §18 AngularJS 31

        Doch es sprechen aus meiner Sicht mehrere Gründe dafür, dass AngularJS auch im Verlaufe des nächsten Jahrzehnts eine bedeutende Rolle spielen wird. Zum Ersten ist es seit mehr als einem halben Jahrzehnt ein Projekt des zur Zeit größten und mächtigsten Innovationstreibers der digitalen Ökonomie, der Google Inc. Ein Ende des Projekts seitens Google ist nicht erkennbar und wäre in den nächsten Jahren mindestens überraschend. Ein weiteres Argument zur Behandlung von AngularJS ist die Tatsache, dass dort moderne und aktuelle Konzepte des Software Engineerings angewandt werden, so Kontrollflussumkehr IoC, Dependency Injection, Datenbindung und lose Kopplung. Selbst wenn AngularJS als System vollständig in Vergessenheit geraten sein sollte, wäre es allein als Anwendungsbeispiel dieser wichtigen Konzepte didaktisch wertvoll. Zum Dritten bewirkt AngularJS einen sehr beachtenswerten Paradigmenwechsel der Soft- wareentwicklung im Web, die effiziente Aufgabenverlagerung weg vom Server hin zum Client. Waren in den ersten Jahren des Internet, also Ende der 1990er Jahre, mit JavaScript, Java Applets und Flash Webanwendungen vorherrschend, die dem Client fast die gesamte Arbeit überließen, so war es in den 2000er und beginnenden 2010er Jahren der Server, auf den aufgrund zentral zu verwaltender Daten mit PHP, Java EE oder ASP konzeptionell die Hauptlast der Webanwen- dungen verlagert wurde; die serverseitigen Skripte und Programme waren zuständig sowohl für Darstellung als auch Ablauflogik eines Webauftritts. Selbst modernere Ansätze wie Ruby on Rails, die mit einer strikteren Architektur die Webanwendungen nach dem MVC-Muster struk- turieren, änderten nichts an der zentralen Rolle des Servers. Erst durch das MVVM-Muster mit einem clientseitigen ViewModel werden große Teile der Ausführung einer Webanwendung dem Client übertragen. Die dadurch erst mögliche lose Kopplung hat mehrere wichtige Vorteile, vor allem die konsequente Trennung der zentralen Funktionen des Models und der Datenspeicherung von den Funktionen der Darstellung und der Bedieneroberfläche auf dem Client. Dies wieder- um ermöglicht die weitgehend getrennte Programmierung von GUI und Datenspeicherung, d.h. View und Model. Es liegt auf der Hand, dass auf diese Weise zentrale Datenspeicherungen von unterschiedlichen Clientsystemen dargestellt und verarbeitet werden können, insbesondere von mobilen Endgeräten. Grundsätzlich könnte AngularJS oder ein darauf aufbauender Ansatz sich zu einer Schlüsseltechnologie für die mobile ubiquitäre digitale Ökonomie entwickeln. 19 WebSockets

        WebSockets sind eine Webtechnik, die auf Basis der TCP/IP-Protokolle einen bidirektionalen Kommunikationskanal zwischen einem Webclient und einem Webserver aufzubauen, also Nach- richten während einer stehenden Verbindung in beide Richtungen geschickt werden können. Das grundsätzliche Problem dabei ist, dass HTTP (bzw. HTTPS) als Protokoll zwischen Browser und Server zustandslos ist und damit auf Protokollebene gar keine Verbindung ermöglicht, erst recht keine bidirektionale. Zwar kann eine Verbindung in der auf HTTP aufsetzenden Anwendungs- schicht aufgebaut werden, beispielsweise durch Sessions, allerdings kann auch hier nach dem starren Request-Response-Muster von HTTP der Server immer nur auf Anfragen des Clients reagieren und nicht selbst spontan Nachrichten an den Client senden.

        Zwar kann man mit dem Objekt XMLHttpRequest, das als Standardobjekt in JavaScript zur Verfügung steht, mit Hilfe des Pollings eine Verbindung simulieren, allerdings sehr aufwendig. Da die Clients vor jeder Servernachricht immer erst eine Anfrage an ihn gestellt haben müssen, kann die Kommunikation bei vielen Servernachrichten und vielen Clients unverhältnismäßig hoch werden und zu stockenden Verbindungen führen. In diesem Kapitel werden wir ein noch recht junges Protokoll kennenlernen, mit dem eine echte bidirektionale Datenübertragungen zwischen Browser und Webserver eingerichtet werden können. Kapitelübersicht 19.1 Das WebSocket Protokoll ...... 33 19.2 Die WebSocket API ...... 34 19.3 Programmierung eines WebSocket-Clients ...... 35 19.3.1 Programmierung eines WebSocket-Servers ...... 36 19.4 Anwendungsfälle ...... 38 19.4.1 Chatsysteme ...... 39 19.4.2 XMPP ...... 39 19.4.3 WhatsApp Web ...... 40 19.4.4 Computerspiele ...... 40 19.5 Webkonferenzen mit WebRTC ...... 40 19.5.1 Jitsi Meet ...... 42

        32 §19 WebSockets 33

        19.1 Das WebSocket Protokoll

        Wie kann man aber überhaupt eine bidirektionale Kommunikation zwischen Browser und Web- server ermöglichen? Da HTTP ein zustandsloses Protokoll ist, kann es über HTTP ganz prinzipi- ell nicht funktionieren. Das darunterliegende TCP dagegen ist verbindungsorientiert und könnte dafür verwendet werden. Die Grundidee ist daher, dass WebSockets über HTTP, also über eine

        logische Kommunikation

        Browser Webserver

        HTTP HTTP Web- Web- Socket TCP Socket TCP

        IP Datenströme IP

        Abbildung 19.1: Prinzip der WebSocket-Verbindung über TCP als „Tunnelverbindung“ durch HTTP und TCP.

        Anfrage eines Webclients, den Aufbau einer bidirektionalen Verbindung über TCP ermögli- chen. Wie in Abbildung 19.1 illustriert, tunnelt eine WebSocket-Verbindung gewissermaßen durch die Protokolle TCP und HTTP. Technisch wird dies dadurch bewirkt, dass der Browser Ein WebSocket tunnelt durch eine HTTP-Anfrage zur Änderung des Protokolls stellt, worauf der Server mit dem Status-Code HTTP, indem 101 antwortet, wenn er diesen Wechsel ausführen kann. der Server die Anfrage WebSockets wurden als Protokoll mit RFC 6455 (http://tools.ietf.org/html/rfc6455) im nicht schließt, Dezember 2011 eingeführt, die WebSocket API zur Implementierung von WebSocket-Clients in sondern mit dem Code 101 Browsern im September 2012 (http://w3.org/TR/websockets). Das WebSocket-Protokoll ba- das Protokoll siert direkt auf TCP, baut jedoch die WebSocket-Verbindung über eine HTTP-Anfrage auf und wechselt. am Ende wieder ab. (RFC 6455, §1.5). Das WebSocket-Protokoll ist in drei Teile gegliedert, das Opening Handshake, die bidirektionale Kommunikation mit Hilfe von Data Frames (also Daten- paketen variabler Länge), und das Closing Handshake. Der schematische Ablauf von Auf- und Abbau einer WebSocket-Verbindung nach Herstellung einer TCP-Verbindung ist in Abbildung 19.2 skizziert. Der URL wird für eine unverschlüsselte Verbindung mit dem Protokollschema

        Client Server TCP-Kanal HTTP Request ws://echo.websocket.org 3 way handshake GET upgrade HTTP Request GET upgrade HTTP Response upgrade Opening Handshake

        WebSocket Verbindung

        Closing Handshake TCP handshake

        Abbildung 19.2: Auf- und Abbau einer WebSocket-Verbindung über TCP. ws:// versehen. Analog wird mit wss:// eine über TLS verschlüsselte Verbindung aufgebaut, 34 Andreas de Vries: Webtechnologie die sich prinzipiell wie in Abbildung 19.2 darstellen lässt, wobei nach dem TCP-Handshake eine TLS-Verbindung mit einem TLS-Hanshake aufgebaut wird und die WebSocket-Verbindung nun innerhalb des TLS-Kanals abläuft. Während eine stehenden WebSocket-Verbindung können beliebig lange Data Frames über- tragen werden, die als Datentyp entweder Unicode-Text oder Binärdaten enthalten (RFC 6455, §5.6). Es gibt drei spezielle Frames, die Control Frames Close, Ping und Pong. Ein Close-Frame beendet eine WebSocket-Verbindung, während der Empfang eines Ping-Frames unverzüglich mit einem Pong-Frame zu beantworten ist. Ping- und Pong-Frames sind dazu vorgesehen, um den Status einer WebSocket-Verbindung zu prüfen, Latenzen (Signallaufzeiten) zu messen oder die Verbindung auch bei längeren Kommunikationspausen zu erhalten (was oft bei Verbindungen über Proxies wichtig sein kann).

        19.2 Die WebSocket API

        Zur Implentierung eines WebSockets im Browser hat das W3C auf Basis des RFC 6455 eine Schnittstelle für WebSocket API’s definiert (http://w3.org/TR/websockets). Hier werden die möglichen Zustände eines WebSockets sowie die möglichen Zustandsübergänge festgelegt, wie sie in Abbildung 19.3 dargestellt sind.

        CONNECTING Objekter- readyState 0 Zustand Beschreibung zeugung CONNECTING Der WebSocket wurde instanziiert und no success? (readyState 0) baut gerade eine Verbindung auf OPEN Die Verbindung ist erfolgreich aufge- yes (readyState 1) baut und ein bidirektionaler Kommuni- OPEN kationskanal steht zur Verfügung readyState 1 send() CLOSING Die Verbindung durchläuft einen Clo- (readyState 2) sing Handschake und wird beendet CLOSING readyState 2 CLOSED Die Verbindung ist geschlossen oder (readyState 3) konnte gar nicht erst aufgebaut werden CLOSED readyState 3

        Abbildung 19.3: Zustände und Zustandsdiagramm eines WebSockets. Nach1

        Ferner muss ein WebSocket-Objekt die in Tabelle 19.1 aufgeführten Event-Handler implemen- tieren, die auf die jeweiligen Ereignisse reagieren. In JavaScript werden die Event-Handler als

        Event Handler Bemerkung onopen(open) Wird ein WebSocket in den Zustand OPEN versetzt, wird ein Ereignis open er- zeugt, das dieser Event Handler verarbeiten kann. onmessage(message) Trifft eine Nachricht beim Client ein, wird das Ereignis message ausglöst und dem Event Handler onmessage übergeben. (Nachrichten umfassen nach RFC 6455, §1.2 insbesondere die Nutzdaten der WebSocket-Verbindung.) onerror(error) Tritt ein Fehler beim Verbindungsaufbau, während der Datenübertragung oder beim Verbindungsabbau auf, wird der Event Handler onerror aufgerufen und mit dem Ereignis error die Gründe dafür übertragen. onclose(close) Gelangt ein WebSocket in den Zustand CLOSED, wird der Event Handler onclose ausgelöst und das Ereignis close übergeben, das weitere Informationen enthält.

        Tabelle 19.1: Die Event Handler eines WebSockets, Gorski, Iacono und Nguyen (2015:S. 83)

        Funktionen implementiert; oft werden dabei insbesondere onopen und onclose ohne Parameter überladen, also als onopen() oder als onclose(). §19 WebSockets 35

        Für weitere Informationen und Demos siehe http://www.websocket.org/. Dort findet man auch einen einfachen WebSocket Echodienst, mit dem man seinen WebSocket-Client auspro- bieren und testen kann.

        19.3 Programmierung eines WebSocket-Clients

        Als Programmierbeispiel eines WebSocket-Systems betrachten wir den einfachsten Fall, einen „Echo-Service“, also ein Kommunikationssystem, bei dem ein zentraler Server einfach die Ein- gaben eines Clients zurücksendet. Für jeden einzelnen Client, der den Server aufruft, erscheint also ein Terminalfenster im Browser, in dem die eigenen Eingaben und die Antworten des Ser- vers erscheinen. Ein solches Echosystem ist für jedes Kommunikationssystem insofern ein gutes Einführungsbeispiel, da weder Client noch Server eine eigene Logik benötigen und sich die Programmierung auf die für die reine Kommunikation notwendigen Anweisungen beschränkt. Betrachten wir zunächst den Echo-Client. Da er vom Browser aus gestartet wird, ist er als JavaScript in einem HTML-Dokument integriert: Listing 19.1: WebSocket-Client für einen Echo-Server WebSockets - A Simple Echo Server

        (Connection readyState: )
        Der HTML-Teil am Ende des Listings ist auf das Wesentliche beschränkt, es ist lediglich ein Textbereich (