Notwendige Basis: Ziel-Architektur(en)
Softwareentwickler möchten mit ihrer Arbeit natürlich sofort loslegen. Aber Vorsicht: Die Implementierung einer "App" beginnt nicht in der Entwicklungsumgebung. Zuvor müssen strategische, technische und architektonische Entscheidungen getroffen werden – die notwendige Basis für eine erfolgreiche Software, vor allem auf mehreren Plattformen.
- Christian Liebel
Softwareentwickler möchten mit ihrer Arbeit natürlich sofort loslegen. Aber Vorsicht: Die Implementierung einer "App" beginnt nicht in der Entwicklungsumgebung. Zuvor müssen strategische, technische und architektonische Entscheidungen getroffen werden – die notwendige Basis für eine erfolgreiche Software, vor allem auf mehreren Plattformen.
Jeder kennt sie, jeder hat sie, jeder will sie (vermeintlich): Die Rede ist von Apps – also jener Sorte Anwendung, die üblicherweise nur einen kleinen, genau definierten Funktionsumfang aufweist. Damit stehen sie vielen althergebrachten Windows-Anwendungen für Desktop-Rechner gegenüber, die eine große Zahl komplexer Use-Cases abbilden. Aber gerade weil Apps nur einen eingeschränkten Funktionsumfang mit sich bringen, kann man sie auch von unterwegs sehr gut bedienen und verwenden. Mobile Geräte wie Smartphones und Tablets erfreuen sich nach wie vor großer Beliebtheit, da sie leicht mitzunehmen und schnell einsatzbereit sind. Da versteht es sich von selbst, dass viele Unternehmen im Mobile-App-Markt mitmischen und ihre Software in die neue Welt bringen möchten.
Hinter dem Wunsch "wir möchten eine App" verbirgt sich allerdings viel mehr als nur die grafische Benutzeroberfläche, die der Anwender auf iOS, Android oder Windows zu sehen bekommt. Der eigentliche Treibstoff einer App sind die Daten, die sie anzeigt und/oder verarbeitet. Sie sollen auf allen Gerätetypen und allen Plattformen gleichermaßen zur Verfügung stehen. Damit ist ein Netzwerk (sei es Internet oder Intranet) als Medium für den Zugriff auf diese Daten bereits gesetzt. In unserer hochvernetzten Welt sind daher immer Server (bzw. Services) im Spiel. Die App stellt dabei nur eine mögliche Ausprägung der Visualisierung und Nutzung der Daten und der damit verbundenen Abläufe und Prozesse dar.
Leichtgewichtige Services statt Monolithen
Software am Stück, wie es viele klassische Windows-Anwendungen sind, ist durch das geänderte technologische Umfeld für Apps keine Option. Software muss stattdessen nach Use-Cases geschnitten, Daten über Services im Sinne der Serviceorientierung bereitgestellt werden. Hat man das erreicht, kann man beliebige Anwendungstypen – kleine Apps, größere Apps, Kommandozeilentools bis hin zu Desktop-Anwendungen – darauf aufbauend implementieren.
Die Idee der Serviceorientierung ist allerdings nicht besonders neu: Dass dem weithin bekannten, (irgendwie) alles könnenden und aus mehreren Millionen Lines of Code bestehenden Monolithen keine rosige Zukunft beschieden ist, dürfte für wenig Überraschung sorgen. Stattdessen wird fachliche Funktionalität in einzelne sogenannte Microservices gekapselt. Aufgrund ihrer viel geringeren Komplexität lassen sich diese erheblich einfacher implementieren, bereitstellen, betreiben, nutzen und weiterentwickeln.
Da die Datenhaltung aus der Anwendung herausgelöst wird, ist immer in verteilten Systemen zu denken. Die Modellierung sollte daher unter dem Leitsatz Distributed-First erfolgen. Damit all das in einer gleichermaßen einfachen wie interoperablen Art und Weise geschehen kann, werden Programmierschnittstellen über das HyperText Transfer Protocol Secure (HTTPS) oder Web Sockets über SSL/TLS (WSS) verwendet. Diese sogenannten Web APIs bilden gemeinsam mit Push-Services das Rückgrat einer leichtgewichtigen Servicearchitektur. Damit das alles auch sicher erfolgt, lassen sich mithilfe von HTTPS die Authentizität des entfernten Servers feststellen und Inhalte verschlüsselt übertragen.
Bidirektionale Kommunikation dank Web APIs und Push Services
Für Web APIs existieren viele Definitionen und Paradigmen. Hier kann sich jeder für ein eigenes Modell entscheiden. Mit Representational State Transfer (REST), JSON API oder GraphQL seien hier nur einige Ansätze genannt. Wir finden, die HTTPS-basierte Kommunikation zwischen Web APIs und Konsumenten sollte möglichst schlank und pragmatisch erfolgen. Aus diesem Grund verwenden wir die JavaScript Object Notation (JSON) als Datenaustauschformat, die über einen wesentlich geringeren Overhead verglichen zur Extensible Markup Language (XML) verfügt und sich in der mobilen Web-Welt längst durchgesetzt hat.
Erforderliche Daten können vom Client in einem Request-Response-Verfahren über HTTP-GET-Operationen von einem fachlichen Service im JSON-Format beziehen und diese in die jeweilige native Objektstruktur umwandeln. Umgekehrt kann der Client mithilfe von HTTP-POST- oder HTTP-PUT-Operationen Daten zum Service senden, indem er die native Objektstruktur zuvor nach JSON serialisiert. Zur Implementierung von Web APIs muss das Rad jedoch nicht neu erfunden werden. Für die gängigsten Serverplattformen gibt es robuste Web-API-Frameworks, die reich an Features sind. Zu diesen zählen exemplarisch:
- .NET: ASP.NET Web API
- Java: Jersey/JAX-RS
- Node.js: Restify
Da unsere Software fortan ein verteiltes System darstellt, kann es passieren, dass zeitgleich Änderungen an Datensätzen durch Dritte vorgenommen wurden. Sollen Änderungen im Datenbestand an die verbundenen Clients (egal ob mit UI oder ohne) übermittelt werden, reicht die reine Request-Response-Semantik nicht aus. Um die Umkehr dieses Konzepts zu implementieren, greift man auf ein Push-Services-Design-Pattern zurück: Darüber kann der Server seine Clients proaktiv über durchgeführte Änderungen informieren. Technologisch lässt sich eine solche Push-Kommunikation beispielsweise entweder über HTTP Long Polling, über Server-Sent Events (SSE) oder via WebSockets realisieren (über WebSockets Secure ist auch hier ein sicherer Austausch möglich). Damit Entwickler sich nicht um die zugrundeliegenden Netzwerk- und Protokoll-Details kümmern müssen, gibt es auch hier Programmier-Frameworks für alle größeren Plattformen:
- .NET: ASP.NET SignalR
- Java: Atmosphere
- Node.js: Socket.IO
Ich will SPAs: Mit Webtechnologien zum Erfolg
Wenn wir von "echten" Cross-Platform-Lösungen sprechen, meinen wir Anwendungen auf Basis moderner Webtechnologien. Diese Anwendungen können nicht nur im Browser ausgeführt werden (nennen wir diese doch "Web App"), sondern auch als native Anwendungen verpackt und "quasi nativ", sprich ohne Fensterdekoration eines Browsers und eingebettet in einen nativen Anwendungsrahmen ausgeführt werden (das wäre dann also die "App App"). Damit können mit einer Single Codebase Browser, Mobilplattformen und Desktop-Plattformen (Windows, OS X, Linux) gleichermaßen adressiert werden. Und noch nicht genug: Auch alle weiteren Plattformen, auf denen ein Browser zur Verfügung steht, können bedient werden.
In dieses Technologiespektrum fügen sich die sogenannten Single-Page Web Applications (SPA) hervorragend ein. Sie bestehen aus HTML5-, CSS- und JavaScript-Quelldateien, die für die Präsentation, Gestaltung und Logik beim Anwendungsstart einem Server bezogen werden. Bewegt sich der Anwender innerhalb der SPA, so findet im Gegensatz zu Ansätzen wie ASP.NET Web Forms keine tatsächliche Webseitennavigation statt. Es wird lediglich der für die nächste View benötigte Datenstand vom entfernten Server bezogen (siehe Abb.).
Wird die Anwendung auf ein Gerät deployt, werden in diesem Bundle alle Views eingebettet, sodass die Anwendung auch ohne bestehende Internetverbindung funktioniert. Das bedeutet jedoch nicht zwangsläufig, dass für jede Änderung gleich ein komplettes Redeployment der App über den jeweiligen App-Store angestoßen werden muss. Da am Ende die gesamte Anwendung aus HTML, CSS und JavaScript-Source besteht, ist ein Nachladen oder Aktualisieren von Inhalten gemäß Store-Richtlinien durchaus möglich.
User-First: Der Anwender im Mittelpunkt
Wenn unsere App ein Erfolg werden soll, muss sie eine gute User Experience (UX) aufweisen. Mit diesem Begriff ist allerdings nicht nur eine ansprechende Benutzeroberfläche gemeint, sondern es schließt auch funktionale Aspekte der Anwendung mit ein. Anwender verwenden längst nicht mehr nur Windows und sitzen vor einem Desktop-PC am Schreibtisch. Eine zunehmende Anzahl von Menschen arbeitet nicht mehr an einem festen Arbeitsplatz. Und bereits seit mehreren Jahren greifen mehr mobile Geräte auf das Internet zu als Desktops oder Laptops – Trend weiterhin steigend.
Möchte man Lösungen entwickeln, die gleichermaßen auf Desktop-PCs wie auf Mobilgeräten funktionieren, beginnt man oft zunächst beim Entwerfen der Sichten für Mobilgeräte (Mobile-First). Es liegt in der Natur der Sache, dass auf Mobilgeräten wie Smartphones oder Tablets weniger Bildschirmfläche zur Verfügung steht. Die vorherrschende Eingabeart auf diesen Geräten ist zudem die Touch-Bedienung, die längst nicht so präzise ist wie die Eingabe per Maus. Diesen Umständen muss Rechnung getragen werden. Die Eingabemasken oder Funktionen für Desktop-PCs können dann aufbauend auf den mobilen Sichten erweitert werden. Somit wird sichergestellt, dass für jede Gerätebauform eine sinnvolle UX zur Verfügung steht.
Das Smartphone ist für viele Menschen ein ständiger Begleiter – egal ob zu Hause, auf der Arbeit, in der Bahn oder auf der Decke im Park. Lokale Speichertechnologien erlauben das Persistieren von Anwendungszuständen, selbst wenn keine Internetverbindung zur Verfügung steht – und ja, das funktioniert selbst im Browser! Anwender können auf einem synchronisierten Datensatz arbeiten, selbst wenn sie gerade durch einen Tunnel fahren oder sich in Gebieten mit schlechtem Empfang aufhalten. Dieses Thema ist zu einem späteren Zeitpunkt nur mit massivem Aufwand integrierbar, weswegen es von Beginn an berücksichtigt werden sollte (Offline-First).
Mobile-First und Offline-First bilden gemeinsam das Paradigma User-First – denn der Anwender sollte beim Entwurf der App im Mittelpunkt stehen. Und weil diese beiden Punkte besonders spannend sind, wollen wir uns im nächsten Artikel ausgiebig damit befassen. ()