Geschrieben von

Michael

am

4.6.2020

Scrum-Poker während dem Corona-Lockdown

Obwohl wir in der Schweiz keine vollständige Schliessung hatten, haben die meisten Entwicklungsteams in den letzten drei Monaten von zu Hause aus gearbeitet und werden wahrscheinlich noch einige Wochen in ihren Heimbüros bleiben.

Während dieser Zeit mussten viele Teams Stories für ihren Scrum-Prozess schätzen. Nach einigen Versuchen mit Chat-Nachrichten haben wir schnell ein Tool eingesetzt, das wir einmal an einem VIUday entwickelt haben, um das VUE-Javascript-Framework zusammen mit Firebase für die Datenspeicherung kennenzulernen.

Das Tool ist bei weitem nicht perfekt und die UX war nicht wirklich durchdacht - aber es funktioniert - und wenn du das gleiche Bedürfnis hast und es ausprobieren willst, kannst du das gerne auf scrum.viu.ch tun.

No items found.

6 Mins Read

7.2.2020

Was ist ein Headless CMS?

Mehr lesen

Während dieser Unterschied dazu führt, dass das CMS den Inhalt über APIs in strukturierten Formaten anbieten muss und dementsprechend eine Wiederverwendung in verschiedensten Kanälen möglich wird, ist die andere damit einhergehende Änderung viel bedeutender. Und zwar führt die Loslösung vom Layout im CMS dazu, dass sich die Datenstruktur von «Seiten» und «Komponenten» lösen kann. Der Fokus wird stärker auf den eigentlichen Inhalt und dessen Struktur gelegt. Wohlverstanden, viele «traditionelle» CMS erlauben das auch, aber bei Headless CMS ist es die Grundannahme.

Dies hat einige Auswirklungen:

  • Fokus auf Inhalte und nicht auf Seiten
  • Kanal-Unabhängige Inhalte
  • Kein WYSIWYG Editieren (zumindest bei fast allen Headless CMS nicht)
  • Keine implizite Navigation (diese würde ja jeweils wieder nur für die Webseite funktionieren)

Gleichwohl werden die meisten Headless CMS Projekte einen oder mehrere «Seiten»-Inhaltstypen haben. Der meiste Inhalt sollte aber nicht in diesen Seiten liegen, sondern nur von der Seite angezogen werden. Der Inhalt kann also auch ohne Seite funktionieren (ein Chatbot, der FAQs beantwortet, sollte keine Links auf Seiten, sondern den Antwort-Text liefern).

Warum ist Headless jetzt in aller Munde?

Headless CMS gibt es schon seit geraumer Zeit – und einige «traditionelle» CMS unterstützen Headless Funktionalität seit vielen Jahren. Das Thema nahm aber erst in den letzten Jahren richtig an Fahrt auf. Dies liegt wohl vor allem an folgenden Punkten:

  • Die Multichannel-Wiederverwendung von Inhalten nimmt zu
  • Content Marketing gewann stark an Bedeutung – da hier viel Geld in Inhalte investiert wird, ist eine Wiederverwendung wichtiger denn je
  • Die unabhängige Implementierung des Web-Channels wurde mit Verwendung von Frontend-Technologien (z.B. React mit Next.js) einfacher
  • Die Anzahl interaktiver Elemente auf Webseiten nahm zu – diese Komponenten sind sehr oft auf strukturierte Daten angewiesen und können mit «Seiten» nicht viel anfangen
  • Mit responsiven Layouts mussten sich Editoren schon länger davon lösen, das Aussehen einer Seite genau definieren zu können
Was bedeutet das für Editoren und Marketing-Verantwortliche?

Für alle, die bisher mit «traditionellen» CMS gearbeitet haben, ist es wichtig die Änderungen genau zu verstehen und auch die Gründe und Vorteile, welche sich daraus ergeben, zu kennen. Nur so wird man über das anfängliche «ich kann die Seite gar nicht direkt editieren» hinwegkommen. Wenn das aber geschafft ist, wird auch für Editoren die Arbeit einfacher. Sie müssen sich nicht (oder nur beschränkt) um Komposition kümmern und können die Inhalte in genau den Strukturen abfüllen, welche dafür konzipiert wurden. Jeder Konsument der Inhalte ist dann verantwortlich für eine dem Kanal angepasste Darstellung.

Was bedeutet das für die Entwicklung?

Das CMS ist nicht mehr länger die Basis der Entwicklung. Die Wahl der verwendeten Frameworks und der Programmiersprache ist offen. Dies gibt viel Freiheit und ermöglicht die sinnvolle Nutzung von vorhandenem Wissen oder zum Teil sogar von bereits programmierten Artefakten (Styleguides, die z.B. auf React-Komponenten basieren können sehr leicht für das Rendering dieser Komponenten verwendet werden).

Auf der anderen Seite bedeutet dies auch, dass man auf einiges verzichten muss, was CMS bisher mitgebracht haben:

  • Authentifizierung / Berechtigungen
  • Session Management
  • Personalisierung / A/B-Testing
  • Navigations-Aufbau

Für diese Funktionalitäten gibt es wiederum Services, welche man kaufen kann. Aber selbst, wenn man einen solchen Service zuzieht muss die Integration selbst entwickelt werden. Dies bedeutet initial einen Mehraufwand – im Idealfall spart man sich diesen Aufwand aber an anderer Stelle wieder ein – und kann die Funktionalitäten in anderen Projekten wiederverwenden.

Integrationen

Heute gibt es kaum mehr ein Web-Projekt, welches nicht davon lebt, dass es eine oder mehrere Integrationen in Backend-Systeme zur Verfügung stellt und dem Benutzer damit Zugang zu den verschiedensten Self-Service-Funktionen ermöglicht. Sehr oft wird das CMS als Platform für diese Integrationen verwendet. Dies ist hier nicht mehr möglich. Es gibt prinzipiell zwei Varianten, wie man damit umgehen kann.

Integration über den Browser

Bei diesem Ansatz liefert der Server nur das «Gerüst» der Seite bzw. alle Inhalte, welche nicht aus dem Backend-System kommen. Der Browser lädt danach die Informationen direkt via API vom Backend-System nach. In Praxis wird hier fast immer noch ein weiterer Layer dazwischenstehen – aus Sicherheitsgründen und/oder um die Daten in eine Struktur zu bringen, welche für die Webapplikation sinnvoll ist.

Diese Integration bewährt sich vor allem, wenn eine Authentifizierung gegenüber dem Backend-System notwendig ist. Dabei muss nur der Browser das entsprechende Token besitzen (nach einem Login via Federated Authentication) und kann dieses dann für den Zugriff auf diverse Systeme und Daten verwenden.

Integration über die Rendering-Applikation

Sollten Daten integriert werden, welche unbedingt auch von Suchmaschinen indexiert werden sollen und dementsprechend öffentlich sind, macht eine Integration innerhalb der Rendering-Applikation für den Web-Kanal Sinn. Damit können diese Inhalte auf dem Server gerendert werden und eine Suchmaschine kann das fertige HTML lesen und indexieren. Dies ist übrigens auch einer der wichtigsten Gründe, weshalb Server-Side-Rendering (SSR) für so viele Inhalte wie möglich zur Verfügung stehen sollte.

Anbieter und Tools

Wir haben uns im Laufe der Zeit diverse Headless CMS angeschaut und diese auch teilweise ausprobiert. Dies soll aber kein Review der Anbieter werden. Wichtig ist bei der Auswahl auf jeden Fall, dass man sich (unter anderem) folgende Punkte anschaut:

  • Preis: Es gibt alles von gratis Systemen bis zu relativ teuren SaaS Angeboten.
  • Interface / Usability: Die Systeme unterscheiden sich stark in der Übersichtlichkeit, Geschwindigkeit und allgemeinen Editoren-Usability.
  • «Template»-Vererbung/Wiederverwendung: Welche Flexibilität man beim Aufbau der Inhaltstypen hat beeinflusst die «technische Sauberkeit» der Lösung oft stark und kann auch das Editieren vereinfachen oder unnötig komplex machen.
  • SDKs / Dokumentation: Für den Bau der Webseite oder anderer Kanäle stehen oft SDKs für verschiedene Programmiersprachen zur Verfügung. Wichtig ist die Qualität des SDKs da dadurch der Aufwand der Implementierung von Lösungen stark beeinflusst wird. Wichtig ist auch, dass die Dokumentation komplett ist und man vom Anbieter guten Support erhält.
  • Performance & Stabilität: Da viele Systeme von einem Headless CMS abhängig sein können, machen sich Probleme mit dem Headless CMS auch an vielen Stellen bemerkbar und viele Applikationen können dadurch ausgebremst werden.
Sitecore und Headless

Als langjähriger Sitecore Entwickler möchte ich natürlich auch erwähnt haben, dass sich Sitecore auch sehr gut als Headless CMS eignet. Es bringt (schon lange) die wichtigsten Features eines Headless CMS mit.

  • Freie Definition der Datenstrukturen
  • API-Zugriff auf alle Inhalte

Was bis 2017 gefehlt hatte war eine SDK für die Verwendung in den bekanntesten Frontend Frameworks. Dies wurde mit JSS aber eingeführt.

Zusätzlich zu den Funktionen eines Headless CMS bietet Sitecore auch Funktionen an, die man sich aus einem Enterprise CMS gewohnt ist, welche aber reine Headless-CMS meist nicht anbieten:

  • Authentifizierung / Autorisierung
  • Baumstruktur der Inhalte
  • Flexible Layouts (falls man die Seiten-Komposition den Editoren überlassen möchte)
  • Personalisierung / A/B-Testing
  • Analytics
  • u.v.m.

Sitecore hat im letzten Jahr klar kommuniziert, dass man in Zukunft (auch) auf SaaS-Angebote setzen wird. Man darf also gespannt sein, ob dies auch ein reines Headless Angebot wird (da dies verhindern würde, dass Sitecore Lösungen betreuen muss, welche Code von Dritten enthält). Mitte 2020 wird man hier wohl genaueres wissen.

Progressive Decoupling

Bei neuen Projekten stellt sich initial die Frage, ob ein Headless CMS oder ein eher traditioneller Ansatz gewählt werden soll. Viel häufiger (zumindest bei unseren Kunden) werden sowieso bereits beide Ansätze parallel eingesetzt. Meist gibt es ein «traditionelles» CMS, welches auch die meisten Seiten «produziert» und gleichzeitig via APIs Inhalte für Applikationen (Single Page Applications oder auch integrierte Komponenten) liefert.

Es ist also möglich die Vorteile beider Ansätze gleichzeitig zu nutzen – und damit natürlich auch einen Wechsel von Traditionell zu Headless schrittweise anzugehen. Dies kann insbesondere bei grossen und schon in die Jahre gekommenen Lösungen ein sinnvolles Vorgehen sein, um eine Modernisierung zu erreichen. Dabei fokussiert man am Anfang vor allem auf Inhalte und Daten, welche sich einfach strukturieren lassen (wie z.B. News, Blogs, Veranstaltungen, …) und bereits in anderen Kanälen benötigt werden.

6 Mins Read

16.1.2020

Get a Quote at Record Speed! All You Need is a Photo of Your Vehicle Registration

Mehr lesen

What are these days for? We intentionally take breakout sessions from which we draw inspirations, new perspectives and fresh ideas. A perfect place to experiment and learn in order to serve our customers not only with state-of-the-art solutions, but also with cutting-edge technology. So getting a speed offering was a challenge we passionately took on and today the idea has gone live.

We have been working for Zurich Insurance Switzerland for many years and always appreciated the open-minded culture where business and IT work hand in hand. Based on this background, we were confident that Zurich would be willing to give our intention to combine image recognition with the buying process a go. Being constantly on the lookout for customer-friendly services and convenient processes for their customers, the Digital Business Team bought into the idea immediately.

Excitingly enough, the internal Data and Analytics Team was working on a similar project already. Like us, they saw the huge potential that artificial intelligence (AI) offers for better user experience and lean internal processes. The team had already managed to produce accurate data by using Microsoft and Google technology and build an advanced algorithm to read the standardized Swiss vehicle registration document (Fahrzeugausweis). Even poorly exposed photos or skewed documents delivered reliable results and they were able to send high-quality data into the rating machine. We were honestly impressed by the job they had done so far and joined forces to finalize the innovative functionality.

Give it a go! Experience yourself the new way of buying car insurances.

Screenshot of vehicle registration scan component on zurich.ch
Screenshot of vehicle registration scan component on zurich.ch

6 Mins Read

19.10.2019

Use Google Coral TPU to speed up Mice recognition

Mehr lesen

This is an update to the blog post "Use AI to Keep Mice out of the House".

The first thing that I updated wasn't even the image recognition itself. Once again it showed, that it is extremly important to get the basics right. The issue was that the tripod holding the camera and the Raspberry Pi was moved around quite often (either by my cat or by a human trying to clean or just walking into it). It was very time consuming to always make sure it was placed correctly. And it showed that the image recognition was not good at working with different angles or distances - so it was key to have it in the same exact position all the time.
To solve that issue, I 3d-printed a camera holder and an arm that could be moved into a good position and fixed there. The following image shows one piece of the puzzle.

This is an update to the blog post "Use AI to Keep Mice out of the House".

The first thing that I updated wasn't even the image recognition itself. Once again it showed, that it is extremly important to get the basics right. The issue was that the tripod holding the camera and the Raspberry Pi was moved around quite often (either by my cat or by a human trying to clean or just walking into it). It was very time consuming to always make sure it was placed correctly. And it showed that the image recognition was not good at working with different angles or distances - so it was key to have it in the same exact position all the time.
To solve that issue, I 3d-printed a camera holder and an arm that could be moved into a good position and fixed there. The following image shows one piece of the puzzle.

Need for Speed

As already mentioned in the first part of the blog - speed is everything. And after I tried everything to improve in this area and just could not get below about 700ms for image recognition, I needed to change tactics. A few months ago, Google made a TPU (tensor processing unit) available that is perfect for DIY projects. The one I'm using is the "USB Accelerator". It is sold under the "Coral" brand and is a small device that can be connected and powered via USB. Read more about the product here. The great thing about this device is, that you can connect it to your Raspberry Pi very easily and it provides amazing speed. The not-so-easy part was, that this TPU needs a specific type of model (they need to be fully quantized). And while google offers some conversion tools, you cannot currently create a quantized model from an existing model (that I could download from Azure CustomVision). So in the end I had to download the images from Azure (which is possible with their api - thanks!) and upload them to Google AutoML. There you can (of course) create a model that works on the Coral TPU.

Once the TPU was connected to the Raspberry Pi and the necessary libraries were installed, I created a little Python script (see below) that would listen to http calls from my node application and reply with the results of the image recogition. Now the whole process takes about 60ms - which amazes me - and is hopefully quicker than my cat will ever be. Currently, I still got some false positives, as I had to retrain the model for the new camera perspective. But I hope I'll have that worked out pretty soon.

This is the python script that calls the TPU to do the image recognition - please note - I'm a complete python newbie.


import os
import io
import time
import numpy as np
import jsonpickle
from PIL import Image
from flask import Flask, request, Response

import edgetpu.classification.engine

# Initialize the Flask application
app = Flask(__name__)

# initialize ai
model = './edgemodel/models_edge_ICN7519559552275459553_2019-08-15_18-34-56-018_edgetpu-tflite_edgetpu_model.tflite'
labels = './edgemodel/models_edge_ICN7519559552275459553_2019-08-15_18-34-56-018_edgetpu-tflite_dict.txt'

with open(labels, 'r') as f:
	pairs = (l.strip().split(maxsplit=1) for l in f.readlines())
	labels = dict((int(k), v) for k, v in pairs)

engine = edgetpu.classification.engine.ClassificationEngine(model)
_, width, height, channels = engine.get_input_tensor_shape()

imageWidth = 640
imageHeight = 480

# route http posts to this method
@app.route('/api/image', methods=['POST'])
def image():
	largeImage = Image.open(request.data)
	smallImage = largeImage.resize((width, height))
	
	results = engine.ClassifyWithInputTensor(np.array(smallImage).reshape(width*height*3), top_k=3)
	
	catValue = 0
	mouseValue = 0
	for result in results:
		if labels[result[0]] == "cat":
			catValue = result[1]
		if labels[result[0]] == "mouse":
			mouseValue = result[1]
	
	# build a response dict to send back to client
	response = {'tags': {'mouse': float(mouseValue), 'cat': float(catValue)}}
	# encode response using jsonpickle
	response_pickled = jsonpickle.encode(response)

	return Response(response=response_pickled, status=200, mimetype="application/json")

# start flask app
app.run(host="0.0.0.0", port=5000)