Elektronische Signaturen (#iil21)

Am vergangenen Donnerstag und Freitag (20.-21. Mai 2021) habe ich am STP International Innovation Labs #iil21 teilgenommen. Es war die erste STP LabyDay-Veranstaltung in Zeiten von COVID19. Im Gegensatz zu früheren LabsDays war es diesmal 100% remote. Zusätzlich war der Teilnehmerkreis und der Zeitrahmen größer. Sieben Teams haben in sieben Wochen in ihrer Freizeit an sieben Projekten gearbeitet. Der 24-stündige Hackathon war diesmal nur das Finale. Die Idee der ehemaligen LabsDays und des diesjährigen #iil21 ist es, in kleinen Gruppen an einer eigenen Idee zu arbeiten. Wer schon immer mal ein spezielles Framework oder eine Bibliothek in Verbindung mit einem kleinen Projekts ausprobieren wollte, hat mit dem #iil21 jedes Jahr den perfekten Rahmen dafür. STP übernimmt nicht nur die Verpflegung während des Hackathons, sondern bietet auch Workshops mit externen Trainern und Keynotes mit internen Sprechern an. Dadurch haben wir jedesmal viel Spaß und lernen auch immer eine große Menge dazu.

Mein Kollege und ich bildeten eins der sieben Teams. Unser Thema war “Elektronische Signaturen für Dokumente”. Keiner druckt mehr Dokumente aus und unterschreibt sie manuell, nur um sie anschließend wieder einzuscannen und zu verschicken. Erst recht nicht mehr in Zeiten von Digitalisierung und Home Office. Wir haben uns daher überlegt, wie wir elektronische Signaturen möglichst automatisiert in bestehende Prozesse integrieren können. Es sollten bestenfalls alle manuellen Schritte entfallen. Dadurch würden nicht nur die Unterschreibenden Zeit sparen, sondern auch die Empfänger der unterschriebenen Dokumente.

Um unsere vollautomatisierten Prozesse zu realisieren wollten wir keine eigene App oder Platform bauen. Das hätten wir in der zur Verfügung stehenden Zeit wahrscheinlich nur halb geschafft. Schließlich ist nach einem intensiven Arbeitstag Abends dann doch nicht mehr so viel Energie übrig. Wir haben uns auch überlegt, ob wir unsere Lösung vielleicht auf LEXolution.FLOW, STPs no-code-Platform für Legal Apps, bauen sollten. Wichtig war uns eine Lösung, die uns die größtmögliche Flexibilität bietet. Nach Gartner werden vor allem Rechtsabteilungen zunehmend die Business Application Platforms nutzen wollen, die ihre Unternehmen bereits schon im Einsatz haben.

Specialist #legaltech vendors will increasingly build legal applications on top of business application platforms from Microsoft, SAP, Salesforce and ServiceNow, among others. These will appeal to big enterprises looking to leverage existing investments, and ensure easier integration.

https://www.gartner.com/smarterwithgartner/5-legal-technology-trends-changing-in-house-legal-departments/

KPMG betont die Notwendigkeit der offenen Systeme und Lösungen, die sich aus unterschiedlichen Komponenten des breiteren technologischen Ökosystems zusammensetzen lassen.

Enterprise technology continues to broaden out into legal functions, blurring the line between legal tech providers and just tech. As 2025 gets closer and digitalization of legal functions continues, organizations may increasingly eschew high-cost, stand-alone technologies that serve specific legal niches. Instead, they’ll look to larger providers for solutions that mesh holistically with their broader technology ecosystem. Like medical tech and fintech providers, legal tech providers will likely either cease to exist or be subsumed by bigger players with broader offerings.

https://home.kpmg/xx/en/home/insights/2020/12/future-of-legal-article-series.html

Der Gedanke ein System aus einzelnen Bausteinen zusammenzusetzen, statt auf einer Platform eine proprietäre Lösung zu bauen, gefiel uns und schien auch ganz dem Microservices-Trend zu entsprechen. Das erinnerte uns auch an Rube Goldberg. Herr Goldberg war ein Experte darin aus kleinen und einfachen Komponenten einen umfangreichen Prozess zu bauen.

Rube Goldberg - Illustration History
Rube Goldberg – Illustration History

Statt ein neues System zu bauen, wollten wir also bestehende Komponenten verwenden und diese geschickt und gewinnbringend kombinieren. Zur Orchestrierung der einzelnen Prozessschritte wählten wir Microsoft PowerAutomate, da Kanzleien und Rechtsabteilungen Office 365 einsetzen werden wollen, so Gartner. Die beste Signaturkomponente erschien uns Adobe Sign, da Microsoft sie aktiv präferiert.

Adobe Sign, the market-leading e-signature service in Adobe Document Cloud, is now Microsoft’s preferred e-signature solution.

https://news.microsoft.com/2017/09/07/adobe-and-microsoft-expand-strategic-partnership-to-drive-e-signatures-and-collaboration-among-teams-in-the-cloud

In Verbindung mit LEXolution.DMS pro, der besten Dokumentenverwaltung für Kanzleien, hatten wir nun alle wichtigen Komponenten indentifiziert um den besten automatisierten Dokument-Signierungs-Prozess bauen zu können. Adobe Sign hat bereits PowerAutomate-Konnektoren, sodass wir nur einen neuen Connector für LEXolution.DMS pro bauen brauchten. PowerAutomate Connectors sind im Wesentlichen Web APIs und ihre Funktionen unterscheiden sich in Actions (“mach das”) und Triggers (“wenn das passiert, dann…”). Die DMS API konnten wir über eine Azure Relay Hybrid Connection in der Cloud erreichbar machen. Dadurch hatten wir eine direkte und Cloud-fähige HTTP API zu LEXolution.DMS pro. Diese HTTP API konnten wir anschließend zu einem PowerAutomate Connector definieren, der uns die folgenden drei Operationen bereitstellt:

  • Trigger: Document imported
  • Action: Get Document
  • Action: Store Document (a new one or merely a new version of an existing document)

Damit konnten wir dann folgenden automatisierten Prozess bauen.

1. Der Klient fordert über ein öffentliches Formular ein Dokument an und erhält eine bereits ausgefüllte Dokument-Vorlage, die er nur noch unterschreiben braucht.

Der erste Ablauf erzeugt ein neues Dokument aus der Vorlage mit den Benutzereingaben und legt es in LEXolution.DMS pro ab.
Der zweite Ablauf wird gestartet sobald ein neues Dokumnet dieser Art in LEXolution.DMS pro abgelegt wurde und sendet es mithilfe von Adobe Sign zur Unterschrift an den Klienten.
Der Klient unterschreibt das Dokument mit Adobe Sign.

2. Das ausgefüllte und unterschriebene Dokument wir automatisch in LEXolution.DMS pro zum Klienten abgelegt und der Anwalt benachrichtigt.

3. Der Anwalt kann auf seinem Handy entscheiden, ob er das ausgefüllte und unterschriebene Dokument akzeptieren oder ablehnen möchte.

Der Anwalt sieht die Anfrage auf seinem Handy in der Microsoft Teams App.
Je nach Entscheidung des Anwalts werden unterschiedliche weitere Abläufe durchgeführt. Im Falle der Ablehnung leiten wir das Dokument zu einer von uns gehosteten Azure Function “Stamp”, die mithilfe von Aspose.PDF ein einfaches Overlay in das PDF einbettet und zurückgibt, bevor wir die neue Version wieder in LEXolution.DMS pro ablegen.
Das abgelehnte Dokument erscheint gestempelt in LEXolution.DMS pro. Prozessende.

Natürlich könnte dieser Prozess noch um mehr Schritte erweitert und verbessert werden. Für unseren Proof-of-Value reicht der Prozess in diesem Umfang allerdings bereits aus.

Nach unserer Ergebnispräsentation wurden wir gefragt, ob die Adobe Sign Signaturen tatsächlich rechtlich bindend sind und in Deutschland den händischen Unterschriften gleichstehen. Die kurze Antwort ist “Ja”. In Europa gibt es seit einigen Jahren die Verordnung Nr. 910/2014 des Europäischen Parlaments und des Rates über elektronische Identifizierung und Vertrauensdienste für elektronische Transaktionen im Binnenmarkt, kurz eIDAS (electronic IDentification, Authentication and trust Services). Innerhalb dieser Verordnung werden drei Stufen der elektronischen Signatur unterschieden:

  • Einfache elektronische Signaturen sind nur Unterschriften in digitaler Form, zum Beispiel in Form eines Bildes der händischen Unterschrift.
  • Fortgeschrittene elektronische Signaturen müssen dem Unterzeichner eindeutig zugeordnet sein und nicht gefälscht werden können. Hier kommen digitale Signaturen und Public-Key Cryptography zum Einsatz.
  • Qualifizierte elektronische Signaturen erfordern eine durch einen akkreditierten EU-Vertrauensdienst (beispielsweise D-Trust und Deutsche Post) herausgegebene zertifikatbasierte digitale ID (Public-Key Cryptography). Dadurch haben sie denselben rechtlichen Status hat wie händische Unterschriften.

[Adobe Sign] unterstützt als einzige [Lösung für elektronische Unterschriften] alle akkreditierten EU-Vertrauensdienste und lässt euch die freie Wahl zwischen fortgeschrittenen und qualifizierten elektronischen Signaturen.

https://acrobat.adobe.com/de/de/sign/compliance/eidas.html

Meine Mission bei STP ist es, unseren Partnern, Kunden und Kollegen die Technologien und Bausteine zur Verfügung zu stellen, damit sie in ihren Umfeldern (Kanzleien, Büros, on-the-go) erfolgreich die besten Prozesse etablieren können.

No more old school signatures.

Am Ende war unser Projekt ein ganzer Erfolg. Unser Prozess hat sehr gut funktioniert und unsere Präsentation hat einen guten Eindruck hinterlassen. Wir haben für unseren Proof-of-Value den Kundenpreis gewonnen. Der Vorstandspreis ging dieses Jahr an ein Projekt, dass konkrete Möglichkeiten zur Verwendung von GAIA-X erarbeitet hat.

Auch wenn nicht alle Teams einen Preis gewonnen haben, haben wir alle viel dazugelernt. Alle Projekte haben uns merklich motiviert und inspiriert. Wie jedes Jahr war der #iil21 ein echtes Highlight. Um 17 Uhr hatten wir uns das Wochenende dann auch redlich verdient. Ich freue mich jetzt schon auf nächstes Jahr. Ein großartiges Event!

Ontologische oder teleologische Gruppierung?

Vor einigen Monaten habe ich bereits erklärt, warum dienstspezifische Artefakte bei dem jeweiligen Dienst abgelegt werden sollten (Zentrale Service-Einstellungen?) und in welchem Verhältnis Dienst- und Umgebung zueinander stehen (Dienst- oder Umgebung-Orientierung?).

Dabei geht die Frage nach dem Fokus der Gruppierung weit über die beschrieben Einstellungen, Geheimnisse und vergleichbaren Artefakte einer Microservices-Architektur hinaus. Das Thema der Gruppierung betrifft alle Ebenen und beginnt bereits im Quelltext, innerhalb einer Methode.

Schauen wir uns einmal einen einfachen Programmcode an.

Es wird eine Datei eingelesen, verarbeitet, gespeichert und abschließend protokolliert. So einfach so gut. Jetzt soll der gleiche Vorgang mit zwei anderen Dateien ebenfalls durchgeführt werden. Und jetzt wird es spannend. Gruppieren wir den Quelltext so?

Gruppierungsalternative A

Oder so?

Gruppierungsalternative B

Jemand könnte anmerken, dass beide Varianten schlecht sind und für die Gemeinsamkeit eine eigene Methode extrahiert werden sollte.

Gruppierungsalternative A’

Das ist auf jeden Fall besser, da von konkreten Implementierungsdetails abstrahiert wurde und es nur noch eine Stelle gibt um beispielsweise die Protokollierung weiterzuentwickeln. Allerdings hat dieses kleine Refactoring nur das Abstraktionslevel erhöht, aber nicht unser Gruppierungsproblem gelöst. Tatsächlich entspricht es weiterhin der Gruppierungsalternative A. Die alternative Gruppierung würde folgendermaßen aussehen.

Gruppierungsalternative B’

Jetzt stellt sich die Frage, wie der Quelltext denn jetzt gruppiert werden sollte. Und vorallem warum so, denn schließlich haben beide Alternativen Vor- und Nachteile.

Aristoteles’ vier Gründe

Zunächst müssen die Unterschiede beider Alternativen beschrieben werden. Dazu können wir den Grund analysieren, warum der Code überhaupt in einer der beiden Alternativen geschrieben wurde. Es treffen hier nämlich mehrere Gründe aufeinander. Nach Aristoteles können Gründe in vier Kategorien eingeteilt werden (Four Causes). Auf die Frage nach dem WARUM gibt es also vier Arten von Antworten. Im Folgenden will ich die vier Gründe vorstellen und direkt auf Quelltext anwenden.

  • Matter. Die materielle Art, aus der das Objekt besteht. Für die Frage nach dem WARUM eines Stuhls, wäre die Antwort “weil die Holz-Atome und -Moleküle in ihrer Art existieren”. Auf den Programmcode bezogen wären es Daten, Variablen, Operatoren, Anweisungen, Einstellungen, etc.
  • Form. Die Darstellung und Struktur des Objekts. Für den Stuhl wären das die vier Beine, der Sitz und die Lehne. Auf den Programmcode bezogen wäre es die Syntax und das Design der Klassen und Methoden in Entwurfsmustern.
  • Agent. Die Entität, die für die Existenz des Objekts verantwortlich ist. Der Stuhl existiert, weil der Tischler ihn gefertigt hat. Auf den Programmcode bezogen wäre das die Person, die ihn programmiert hat.
  • Purpose. Der Sinn oder das Ziel, dass das Objekt erreichen soll. Der Stuhl existiert, weil sich der Tischler darauf setzen will. Auf den Programmcode bezogen wäre das der Zweck, die fachliche Komponente, das Feature, der Use Case, die Anforderung.

Durch diese Unterscheidung wird deutlich, das Gruppierungsalternative A/A’ den Purpose-Grund in den Vordergrund stellt. Die Anforderung ist “Verarbeite Datei X”, also wird der Quellcode demenstrechend gruppiert.

Gruppierungsalternative B/B’ stellt den Matter-Grund in den Vordergrund. Es geht um Dateien, Variablen, Verarbeitungen und Protokollierungen. Also wird primär nach diesen ‘Atomen’ gruppiert.

Eine Gruppierung nach syntaktischer Darstellung und Entwurfsmustern (Form) ist dem sehr ähnlich und würde JSON-Dateien, Visitors und Adapters in den Vordergrund stellen. Das könnte als Gruppierungsalternative C bezeichnet werden.

Auch die Gruppierungsalternative D ist vorstellbar, die primär nach Agent, also Entwickler gruppiert. Jeder Kollege programmiert seinen Quelltext in seiner Klasse oder Assembly. Schwierig wird es dann allerdings mit der Interoperabilität.

Matter oder Purpose?

Mit dem Wissen über die verschiedenen Gründe der Gruppierung ergeben sich nun neue Argumente für und gegen die oben beschriebenen Alternativen. Sollten wir nach Purpose (Gruppierungsalternative A/A’) oder nach Matter (Gruppierungsalternative B/B’) gruppieren?

Es macht Sinn, ein Softwaresystem primär anhand seiner Features, UseCases und Anforderungen in Dienste und Komponenten aufzuteilen, weil dies die primären Einheiten/Verantwortlichkeiten sind, die ein Team gemeinsam bearbeitet und die sich zusammen ändern. Es macht keinen Sinn, ein System anhand seiner Entitäten oder ‘Atome’ (Startup.cs-Dateien, Controller, DBs, Configs, Secrets, ID-Configs, Dokus, …) aufzuteilen, weil das Details eines Features und damit sekundär sind. Eine solche Aufteilung würde es erschweren Funktionen weiterzuentwickeln und neue hinzuzufügen. Außerdem widerspricht es sämtlichen Design-Prinzipien wie zum Beispiel Kohäsion, SRP, SOC und OCP (siehe oben referenzierte vorherige Blogposts zum Thema).

Es würde auch keiner Menschen eines Unternehmens so aufteilen, dass alle Köpfe hier, alle Hände dort, alle Füße wieder hier und alle Herzen wieder dort zusammengefasst werden. Stattdessen macht es Sinn ein Unternehmen anhand der Produkte aufzuteilen, an denen gearbeitet wird.

Es würde auch keiner das Inventar eines Unternehmens so aufteilen, dass alle Menschen in den ersten Raum, alle Tische in den zweiten Raum und alle Computer in den dritten Raum zusammengefasst werden. Stattdessen macht es Sinn, in jedem Raum eine Person mit Tisch und Computer auszustatten.

Es macht nur eine teleologische Aufteilung (gemeinsamer Sinn) Sinn, keine ontologische (gemeinsame Art). Zumindest solange wir kein Ersatzteillager, sondern einen lebenden und funktionsfähigen Organismus erreichen wollen.

Zentralität oder Dezentralität?

Das Diskussion von Zentralität und Dezentralität von Einstellungen ging am eigentlichen Thema vorbei. Da es bei Einstellungen, zum Beispiel K8S-ConfigMaps und -Secrets, von vornherein um ‘Atome’ (Matter) geht, macht eine dementsprechende primäre Gruppierung oder Zentralisierung keinen Sinn. Die erstrebenswerte Alternative ist aber nicht die Dezentralisierung von Matter, sondern die Zentralisierung von Purpose. Es gibt einen zentralen Bereich für jede fachliche Anforderung, jeden Use Case und jedes Feature. Und nur innerhalb dieses Bereichs können sämtliche Objekte, die einen gemeinsamen Sinn haben, erneut hierarchisch rekursiv gruppiert werden.

Dienst- oder Umgebung-Orientierung?

Vor einigen Monaten habe ich bereits erklärt, warum dienstspezifische Artefakte, wie beispielsweise Einstellungen, nicht zentral, sondern bei dem jeweiligen Dienst abgelegt werden sollten (Zentrale Service-Einstellungen?). Solange unsere Teams nach Diensten und nicht nach Umgebungen aufgeteilt sind, sollten auch unsere Artefakte nach Diensten partitioniert werden. Dienst-Orientierung ist die einzig sinnvolle Struktur für Microservices.

Personen die primär an der Infrastruktur arbeiten, sehen das eventuell anders. Aus ihrer Sicht ist die Umgebung das primäre Produkt. Das schnelle und automatisierte Erstellen neuer und sogar kurzlebiger Umgebungen ist ein Feature, das ihnen wichtig erscheint. Es stellt sich diesemal also ganz allgemein die Frage, welche Rollen Service Ownership und Environment Ownership einnehmen sollten.

Service Ownership oder Environment Ownership?

Alle Aspekte, die einen Dienst betreffen, fallen primär in den Bereich der Service Ownership. DevOps passiert hier aus dem Team heraus, welches für diesen Dienst verantwortlich zeichnet. Andernfalls würden wir eine neue künstliche und zusätzliche Barriere einführen, die zwischen den Personen, die wissen wie der Dienst läuft, und den Personen, die ihn lauffähig machen müssen, trennen würde. Diese neue Barriere müssten wir dann erstmal wieder mit viel Schnittstellen, Kommunikation und organisatorischer Kopplung überbrücken.

Natürlich muss es auch Environment Owner geben, aber nur für Dienst-übergreifende und Dienst-unabhängige Infrastruktur-Aspekte. Die Dienste bestimmen wie die Infrastruktur aussehen muss. Die Infrastruktur muss sich nach den Diensten richten, nicht andersrum.

Services are King, Infrastructures are Servers.

Damit sind die Rollen definiert. Es bleibt noch eine Frage zu beantworten.

Wie kann ich technisch eine neue Umgebung ausrollen?

Das System besteht aus vielen autarken Diensten, die alle durch ihr eigenes Team entwickelt und betrieben werden. Wenn jetzt eine neue Umgebug in einem anderen Land oder in einer speziellen Teststellung entstehen soll, stellt sich die Frage nach der technischen Umsetzung.

Zunächst müssen zwei Arten von Umgebungen unterschieden werden. Es gibt die permanenten Umgebungen und die kurzlebigen Umgebungen. Permanente Umgebungen sind meist prominent, selten und müssen betreut und auf dem aktuellen Stand gehalten werden. Kurzlebige Umgebungen sind häufig, weniger wichtig und müssen daher einfach nur erstellt werden können.

Beide Arten von Umgebungen müssen mit dem selben Mechanismus erstellt werden können. Eine Automatisierung würde also folgendermaßen vorgehen:

  1. Die Umgebung und allgemeine Dinge werden eingerichtet (zentral).
  2. Alle Services werden aufgefordert, ihre Einrichtung vorzunehmen, indem der richtige Branch (master) ausgecheckt und ein beim Service liegendes Script aufgerufen wird (dezentral).

Die automatisierte Erstellung der Umgebung (zentral) gibt also für die Einrichtung des Dienstes in dieser neuen Umgebung die Kontrolle an den Dienst weiter (dezentral), weil dieser die Hoheit und Verantwortung über die Subdomäne hat.

Ein Dienst richtet sich in einer neuen Umgebung zunächst Default-Einstellungen ein, die er definiert und dafür vorgesehen hat. Wenn es sich bei der neuen Umgebung um eine permanente Umgebung handelt, müssen die Dienste noch zusätzliche Dinge einrichten. Damit der Dienst in der neuen Umgebung auch auf dem akteuellen Stand bleibt, müssen neue Deployment Targets und Release Pipelines erstellt werden. Zusätzlich werden die Dienst-Einstellungen für die neue Umgebung angepasst und separat archiviert.

Auf diese Art und Weise bleiben die Dienste autark und autonom. Sie bilden technische und organisatorische Bounded Contexts und können ihre Einstellungen, Interna und Implementierungsdetails eigenständig und unabhängig voneinander weiterentwickeln und verwalten. Services are King. 👑

Ist Überstunden-machen Betrug?

Geistige und körperliche Arbeit ist anstrengend. Wenn wir über einen Erschöpfungszustand hinaus weiter arbeiten, nimmt die Qualität unserer Arbeit und damit auch die Qualität der Arbeitsergebnisse ab. Je länger wir arbeiten, desto unkonzentrierter, fehleranfälliger und langsamer werden wir.

Wenn wir also 8 Stunden konzentriert arbeiten und danach noch weitere 4 Überstunden arbeiten, arbeiten wir in diesen 4 Überstunden nicht nur langsamer, sondern machen auch mehr Fehler. Diese Fehler müssen wir wieder korrigieren und das macht uns nochmal langsamer. Das vergleichbare Arbeitsergebnis dieser 4 Überstunden kann sehr wahrscheinlich am nächsten Tag, nach einer nächtlichen Erholung mit viel Schlaf, innerhalb von 1 Stunde erreicht werden. Das bedeutet, dass das gleiche Ergebnis entweder in 12 Stunden (8h + 4h Überstunden) oder in 9 Stunden (8h + 1h vom Folgetag) erreicht werden kann.

Natürlich ist es aus Sicht des Leistungserbringers besser 12 Arbeitsstunden in Rechnung zu stellen als nur 9 Stunden. Aber ist das nicht Betrug? Stellen Sie sich vor Sie fahren mit dem Zug in eine fremde Stadt. Dort steigen Sie in ein Taxi und sagen dem Taxifahrer, dass Sie zum Theater wollen. Der Taxifahrer weiß, dass es auf dem schnellsten Weg zum Theater 10 Minuten dauert. Da er aber ahnt, dass Sie sich nicht auskennen, fährt er Sie einen Umweg von 20 Minuten. Würden Sie sagen der Taxifahrer hat Sie betrogen?

Um eine Deadline einhalten zu können, ist es manchmal notwendig Überstunden zu machen. In diesen Fällen können wir eine ausreichende Erholungsphase nicht abwarten, sondern müssen die Zeit aus der Zukunft vorziehen. Das hat natürlich die oben erwähnten negativen Konsequenzen. Das Ergebnis wird früher erreicht, aber mit mehr Stunden. Ein solches Vorgehen ist nicht nur ineffizient, nicht nachhaltig und ungesund, sondern kostet den Leistungsempfänger unnötig Geld, das er sparen oder in neue Features hätte investieren können. Das sollte uns stets bewusst sein, wenn wir wieder Überstunden machen wollen.

“Wenn jemand zehn Minuten deines Lebens verschwendet, dann sind acht davon deine Schuld.” Markus Frank

 

 

Zentrale Service Einstellungen?

Dienstspezifische Einstellungen sollten bei dem jeweiligen Dienst abgelegt werden.

Kohäsion

Es ist eine Frage der Kohäsion. Dinge, die fachlich zusammengehören, sollten auch zusammen und in enger Nähe platziert werden. Es gibt wenig schlimmeres als ein Feature so aufzuteilen, dass es im ganzen System verteilt ist (hier ein bisschen Code, hier ein bisschen Config, hier wieder ein bisschen Code, da ein bisschen Doku, usw.). Dienste sollten möglichst autark sein und bestenfalls eigenständig existieren können. Je mehr Kopplung im System besteht, desto schwieriger wird die Weiterentwicklung. Deswegen sind zentrale Aspekte besonders gefährlich. Manche Funktionen müssen zentral realisiert werden, wie zum Beispiel Authentifizierung, weil es nicht anders geht. Alle Dinge, die nicht zwingend zentralisiert werden müssen, sollten es auch nicht. Für den Anwenderkomfort können zentrale Darstellung mit Hilfe von konsolidierenden Oberflächen und Backends For Frontends geschaffen werden.
Im weiteren zeige ich zusätzlich noch drei eindeutige Vorteile der dezentralen Konfiguration.

Atomare Änderungen

Änderungen und Weiterentwicklungen eines Dienstes müssen nicht mehr an zwei entfernten Stellen (Code und Config) nachgezogen werden und in zwei Phasen committed werden. Diese zwei Stellen haben in der Regel eine zeitliche Kopplung, die zu einer fest vorgegebenen Reihenfolge der Aktualisierung führt, die eingehalten werden muss.
Wenn Code und Config an der gleichen Stelle liegen, kann der Code weiterentwickelt und neue Einstellungen direkt mit angepasst werden. Beides kann mit einem einzigen Commit in der richtigen Reihenfolge atomar deployt werden.

Prepare and Forget

Eine Einstellung kann dann auch nicht fälschlicherweise zu früh deployt werden, was zu Fehlern in der aktuellen Version führen kann, sondern wird erst unmittelbar mit dem Code deployt. Ein Entwickler muss nach seinem Commit nicht erst darauf warten, dass sein Code in Test und schließlich nach Production deployt wird, damit er endlich die Einstellung für die jeweilige Umgebung einstellen kann. Die Einstellung wird automatisch angewendet, wenn der Code in die jeweilige Umgebung freigegeben und deployt wird. Der Entwickler brauch sich nicht mehr kümmern (wenn alles nach Plan läuft). Natürlich muss er die Einstellung für Test, Production und alle anderen Umgebungen kontrolliert vorbereiten, aber das tatsächliche Anwenden passiert transparent im Hintergrund, zur richtigen Zeit automatisiert.
Eventuelle Geheimnisse, die der Entwickler nicht kennen darf, müssen ihm verschlüsselt von der jeweils zuständigen Person mitgeteilt oder in Kooperation vorbereitet werden.
Auch das Wiederherstellen einer früheren Version ist aus der Perspektive der Einstellungen problemlos möglich, da die Einstellungen mit dem selben Commit assoziiert sind.

Verantwortung des Service beim Team

Solange das Team, das den Service entwickelt, auch die Verantwortung für den Betrieb des Services übernehmen soll, müssen alle relevanten Artefakte mit dem Service verwaltet werden. Das Repository repräsentiert auch eine organisatorische Klammer. Durch das Klonen des Repositories bekommen Entwickler nicht nur vollständigen Zugriff auf den Quelltext, sondern auch auf tatsächliche Einstellungen, Build Skripte und Deployment Ressourcen. Ein Entwickler kann sich also jederzeit eine funktionsfähige und sinnvoll konfigurierte Umgebung auf seinem Computer erstellen und für Test- und Entwicklungszwecke betreiben. Isolierte Weiterentwicklungen können dabei sogar problemlos in eigenen Branches erfolgen. Ein Entwickler hat jederzeit alle nötigen Ressourcen zur Verfügung, um die Anwendung eigenständig weiterzuentwickeln.

 

Einwände

Und wenn sich nur die Einstellung ändert?

Wenn Einstellung und Service in der selben Pipeline deployt werden, ist das erstmal nicht schlimm. Nachteilig ist lediglich, dass es vielleicht etwas länger dauert, bis die Einstellung aktiv wird. Soll die Änderungen sofort gelten, kann sie manuell oder über das K8S Dashboard vorgenommen werden, und wenn sie endgültig sein soll, kann diese Änderung durch commit dokumentiert werden. Durch das anschließende Deployment wird der Wert dann nicht nochmal geändert, weil er bereits auf dem Zielwert steht.

Und wenn sich eine Einstellung auf viele Dienste bezieht?

Einstellungen, die keinem Dienst zugeordnet werden können (Logging, Message Bus,…), können in der Regel der Umgebung zugeordnet werden. Daher sollten sie an einem dafür vorgesehehen Ort für Infrastruktur Konfiguration abgelegt werden.
Einstellungen, die von einem Dienst für andere Dienste bereitgestellt werden, sollten bei dem bereitstellenden Dienst abgelegt werden. Eine Änderung dieser Einstellungen sollte einen automatisierten Neustart der Konsumeten verursachen.

Und wenn sich alle Einstellungen ändern?

Generell sollten Einstellungen so platziert werden, dass wahrscheinliche und häufige Änderungen mit wenig Aufwand vorgenommen werden können, während für unwahrscheinliche und seltene Änderungen höhere Aufwände akzeptiert werden können. Es macht mehr Sinn für Weiterentwicklung einzelner Dienste zu optimieren als für das Umziehen des ganzen Systems in neue Umgebungen. Sollten sich dienstübergreifende Dinge, wie zum Beispiel die Domain, ändern, dann müssen im schlimmsten Fall viele Commits vorgenommen werden. Auch hier kann eine sofortige Änderung manuell oder im K8S Dashboard erfolgen, die dann anschließend noch committed werden muss. Sollten sich dienstübergreifende Dinge häufig ändern, sollten diese hoffentlich wenigen Einstellungen besser an dem Ort für Infrastruktur Konfiguration abgelegt werden.

Empfangsbekenntnis 3.0 (STP LabsDay 2019)

Am vergangenen Donnerstag und Freitag (14.-15. November 2019) habe ich wieder am STP LabsDay teilgenommen. Diesen internen 24h-Hackathon veranstaltet STP jedes Jahr. Die Idee des LabsDays ist es, in kleinen Gruppen an einer eigenen Idee zu arbeiten. Wer kennt es nicht? Man wollte schon immer einmal Framework X oder Bibliothek Y ausprobieren, aber irgendwie ist man nie dazu gekommen. Genau dafür ist der LabsDay der perfekte Rahmen. Außerdem übernimmt STP an diesen beiden Tagen komplett die Verpflegung.

Insgesamt haben sechs Teams teilgenommen. Mein Kollege und ich bildeten eines dieser Teams. Während die anderen Teams sich primär mit künstlichen Intelligenzen beschäftigten, haben mein Kollege und ich uns einem Thema gewidmet, über das ich schon länger nachgedacht hatte: das Empfangsbekenntnis. Nach der §174 Zivilprozessordnung sind Anwälte, Gerichte und alle Personen und Institutionen, deren Arbeit besonders zuverlässig sein muss, dazu verpflichtet, den Erhalt von entsprechenden Dokumenten zu bestätigen. Auf die klassische Art und Weise passiert das mit der Post. Das Empfangsbekenntnis 1.0 ist ein spezielles Dokument, welches vom Anwalt unterzeichnet und dann an den Sender des ursprünglichen Dokuments zurückgeschickt werden muss. Der Hauptnachteil dieser Lösung liegt auf der Hand. Die Anwälte und Gerichte versinken in einer immer größer werdenden Papierflut. Deswegen wurde vor einigen Jahren das Empfangsbekenntnis 2.0 eingeführt. Mit beA- und EGVP-Postfächern wird eine digitale Empfangsbekenntnis automatisiert erstellt und verschickt, sobald der Anwalt das Dokument in seinem Software Client erhalten hat. Wenn ein digitales Empfangsbekenntnis auf einem zentralen Server oder einem Client gespeichert ist, besteht die große Gefahr eines Datenverlusts. Im Falle eines Brandes im Datenzentrum oder einer Sicherheitspanne bei den Betreibern sind die Daten gefährdet.

Wir wollten diese Situation verbessern. Meine Mission bei STP ist es, unseren Partnern, Kunden und Kollegen die Vorteile der modernen Technologien zu ermöglichen. Moderne Technologien sind zum Beispiel Cloud, Mobile, Artificial Intelligence und die Blockchain. Beim STP LabsDay haben wir deswegen das Empfangsbekenntnis 3.0 als Decentralized Application (DAPP) in Form eines Smart Contracts auf der Ethereum Blockchain realisiert. Mein Kollege hatte zu dem Thema Blockchain bereits seine Bachelor Thesis geschrieben und auch mir waren einige theoretische Konzepte bereits bekannt. Erwähnenswerte praktische Erfahrung hatte ich aber bisher noch keine. Also haben wir uns ein Tutorial gesucht und uns diesem Projekt spielerisch genährt. Schließlich wollten wir am Ende des Hackathons eine funktionsfähige Lösung präsentieren.

Der Prozess ist eigentlich ziemlich einfach. Ein Sender registriert sein Dokument und gibt es danach an den Empfänger weiter, welcher den Erhalt bestätigt. Diesen Prozess konnten wir problemlos in Form einer Abstract State Maschine in Solidity, der Programmiersprache der Ethereum Virtual Machine (EVM), implementieren. Dabei wollten wir nicht nur digitale Dokumente in unserer Lösung verwalten, sondern auch physikalische. Wir brauchten also eine Abstraktion von physikalischen und digitalen Dokumenten, um für diese Abstraktion ein Empfangsbekenntnis zu speichern. Unsere Abstraktion nennen wir Document Link. Wenn das Dokument bereits ein digitaler Datensatz ist, können wir den Document Link ganz einfach als Hash des digitalen Datensatzes erzeugen. Ist das Dokument allerdings ein physikalisches Dokument, können wir eine Zufallszahl generieren und diese in Form eines QR-Codes auf den Brief drucken. Natürlich können wir auch eine URL als Document Link verwenden. Damit haben wir die Möglichkeit geschaffen, um in einer vereinheitlichten Form sowohl digitale als auch physikalische Dokumente zu verwalten.

Ein Sender ermittelt den Document Link aus seinem Dokument und persistiert diesen in der Blockchain. Ein Empfänger des Dokuments kann dann den Document Link mit dem Empfangsbekenntnis ebenfalls in der Blockchain persistieren. Um sicherzustellen, dass nur die Person, die das Dokument tatsächlich erhalten hat und jetzt besitzt, das Empfangsbekenntnis ausstellen kann, nutzen wir eine Hashfunktion. Der Sender ermittelt den Hash des Document Links und persistiert diesen auf der Blockchain. Der Empfänger muss jetzt genau den Document Link auf der Blockchain speichern, der zu dem vom Sender persistierten Hash passt. Versucht er einen Document Link zu persistieren, dessen Hash nicht bereits vorher registriert wurde, wird die Transaktion abgelehnt.

Wenn das Dokument von einer zweiten Person gelesen wird, wird auch eine zweite Empfangsbekenntnis in der Blockchain gespeichert. Wenn ein Empfänger das gleiche Dokument, also mit dem selben Document Link, an eine weitere Person sendet, tritt der Empfänger jetzt als Sender auf und persistiert den Hash des Document Links. In diesem Fall wurde das gleiche Dokument von zwei unterschiedlichen Sendern registriert. Das ist auch für alle Beobachter erkennbar. Wenn jetzt eine dritte Person dieses Dokument empfängt, werden zwei Empfangsbekenntnisse ausgestellt, die jeweils einem Sender zugeordnet werden. Ein Sender kann also jederzeit feststellen, 1) wer sein Dokument wann empfangen hat und 2) wer es ebenfalls verschickt oder weitergeleitet hat.

Diese Prozesslogik lief nun in einem Smart Contract auf der Blockchain. Dazu haben wir noch ein Frontend mit React und Web3 gebaut und auf Azure gehostet. Unser Frontend listet alle getrackten Dokumente mit sämtlichen Empfangsbekenntnissen auf. Den Smart Contract selbst haben wir dann in das Ethereum Testnetzwerk Kovan deployt. Anschließend haben wir uns Szenarien für die Präsentation unserer Ergebnisse überlegt. Um die ganze Sache einfach demonstrieren zu können, hatten wir uns überlegt, dass wir auf ein Papier zwei QR-Codes drucken. Den einen QR-Code scannen wir um dieses Dokument zu registrieren und den anderen QR-Code scannen wir um das Dokument zu empfangen. Genauso haben wir es auch im Rahmen der Ergebnispräsentation demonstriert. Dazu öffneten wir die URLs hinter den QR-Codes jeweils mit MetaMask for iOS und konnten so die Transaktionen mit unseren Mobiltelefonen signieren. Natürlich würden Software Clients diesen Vorgang automatisiert im Namen des Anwalts durchführen.

Die Vorteile von Empfangsbekenntnis 3.0 verdanken wir der Blockchain. Das Empfangsbekenntnis ist unveränderlich, unabstreitbar und für alle sichtbar für immer persistiert. Dass wir uns bei unserem Prototypen für das öffentliche Ethereum Testnetz entschieden haben, hat die Konsequenz, dass Transaktionen nicht kostenlos sind. Wir müssen die Miner incentivieren, damit sie unsere Transaktionen in Blocks verpacken und der Blockchain hinzufügen. Dafür müssen wir bei jedem Schreibvorgang etwas Geld in der Ethereum-Kryptowährung namens Ether bezahlen (Gas). Wenn viele Transaktionen in die Blockchain gespeichert werden sollen, steigt außerdem die Latenz. Das bedeutet, dass wir ein paar Sekunden bis Minuten warten müssen, bis unsere Transaktion bestätigt und tatsächlich persistiert ist. Diese beiden Nachteile haben Consortium Blockchains nicht. Deswegen würden wir für einen real life Einsatz unserer Lösung eine Consortium Blockchain der Public Ethereum Blockchain vorziehen.
Ein weiterer Nachteil ist die komplizierte Weiterentwicklung von Smart Contracts. Genau wie Daten, ist auch der Code unveränderlich auf der Blockchain gespeichert. Das bedeutet, dass wir einen Fehler nicht einfach korrigieren können. Mit jeder Fehlerkorrektur müssen wir das Programm neu auf der Blockchain installieren und allen Verwendern mitteilen, dass sie jetzt diese neue Version verwenden sollen. Zusätzlich müssen natürlich die Daten aus der alten in die neue Version migriert werden. Idealerweise würde die alte Version abschließend auch deaktiviert werden, allerdings müssten wir den Smart Contract von Begin an dementsprechend fehlerfrei programmieren. Das macht das Weiterentwickeln von Smart Contracts umständlich. Im Rahmen des 24h-Projekts haben wir zwei Versionen deployen müssen.

Am Ende war unser Projekt ein ganzer Erfolg. Unser Smart Contract hat sehr gut funktioniert und unsere Präsentation hat einen guten Eindruck hinterlassen. Wir haben für unsere Arbeit den Vorstandspreis gewonnen. Der Kundenpreis und der Zuschauerpreis gingen an das Projekt unseres anderen geschätzten Kollegen, dessen Modell automatisiert Fristen in Dokumenten erkennen konnte.

Auch wenn nicht alle Teams einen Preis gewonnen haben, haben wir alle viel dazugelernt. Alle Projekte haben die Firma merklich motiviert und inspiriert. Wie jedes Jahr war der STP LabsDay ein echtes Highlight. Um 16 Uhr hatten wir uns das Wochenende dann auch redlich verdient. Ich freue mich jetzt schon auf den nächsten STP LabsDay. Ein großartiges Event!

 

Weiterentwicklung?

Unser Prototyp funktioniert. Doch bevor wir unseren Code produktiv einsetzen würden, müssten wir noch eine Sicherheitserweiterung einbauen. Damit die Miner unsere Daten in Form von Transaktionen in Blöcke verpacken können, müssen wir ihnen den Input für unsere Smart Contract Funktionen schicken. Aktuell muss ein Empfänger den Document Link im Klartext an den Miner schicken, damit der Smart Contract den Hash bilden und mit dem vom Sender gespeicherten Hash vergleichen und persistieren kann. Diesen Klartext des ersten Empfängers könnte eine andere Partei mitlesen und ebenfalls persistieren. Dadurch können nach einem ersten Empfangen weitere Parteien ein Empfangsbekenntnis für ein Dokument ausstellen, obwohl sie es gar nicht tatsächlich besitzen. Durch die Signatur der Transaktion ist jederzeit erkennbar, wer die Anfrage gestellt hat, sodass das System nicht gespooft werden kann. Dennoch schwächt dies die Sicherheit des Empfangsbekenntnis. Das Problem ist die Verwendung der Hashfunktion. Nachdem der entsprechende Klartext einmal bekannt ist, kann ihn jeder nutzen um den Hash zu berechnen. Um diesem Verhalten entgegen zu wirken, dürfte der Document Link niemals im Klartext an die Miner geschickt werden. Ihn einfach zu signieren oder mit der Adresse des Empfängers zu prefixen und anschließend zu hashen reicht leider nicht, da der Smart Contract den Klartext nicht kennt und die Signatur oder den Hash deswegen nicht validieren kann.

Die Idee ist, den Document Link wie einen Private Key zu verwenden. Mit diesem Private Key müsste ein Empfänger seine durch die Blockchain eindeutige Adresse signieren und diese anstelle des Klartexts an den Miner schicken. Nur die Parteien, die das Dokument tatsächlich besitzen und deswegen den Private Key kennen, können dies tun. Würde eine signierte Adresse von einer anderen Partei wiederverwendet werden, würde die Signatur nicht zur tatsächlichen Adresse des vermeintlichen Empfängers passen. In diesem Fall ist der Smart Contract nämlich in der Lage die Signatur mit dem vom Sender persistierten Public Key zum Private Key aka Document Link zu überprüfen.

Den Code unseres Prototypen finden Sie im Kovan Testnetz (0xf41930b233137f37b7cd770c3b36eaa51d38c8e2) oder auf Github.

Trends, Gesetze, Verschlüsselung

Es gibt aktuell drei große Trends in der Softwareindustrie. Der erste große Trend ist IOT. Das Internet der Dinge vernetzt alle Geräte und Maschinen, die Daten an Server oder sich gegenseitig senden. Das zweite große Trendthema ist die Blockchain. Ein Netzwerk, in dem kein Teilnehmer einer zentralen Organisation vertrauen muss, sondern sich auf das Netzwerk verlassen kann. Der dritte Megatrend ist die künstliche Intelligenz. Maschinen sind immer mehr in der Lage, Dinge zu erkennen, Korrelationen zu finden und Entscheidungen zu treffen.

Alle diese Trends haben eine Sache gemeinsam: Daten. Ohne Daten spielen IOT, Blockchain und KI keine Rolle. Manche behaupten sogar, dass Daten der wichtigste Rohstoff unserer Zeit ist. Jedenfalls sind Daten die Grundlage der Wortschöpfung unseres Jahrhunderts. Daten waren schon immer wichtig, aber zwei Dinge sind relativ neu. Zum einen wächst der Datenbestand weiterhin exponentiell. Zum anderen werden die Daten, die bis vor kurzem primär on-premise gespeichert wurden, in die Cloud migriert. Unternehmensdaten werden ohne großen Aufwand erfolgreich in der Cloud persistiert. Das Problem dabei ist, dass das Unternehmen dann nicht mehr alleiniger Besitzer der Daten ist. Die Daten werden einem Cloud Service Provider treuhänderisch anvertraut, der nun auch auf diese zugreifen kann.

Um die Daten in der Cloud zu schützen, hat die Regierung besondere Gesetze erlassen. Das wohl bekannteste Gesetz ist die Datenschutzgrundverordnung (DSGVO) und damit das Bundesdatenschutzgesetz (neu). Darüber wurde letztes Jahr viel berichtet. Dieses Gesetz reguliert, wie mit personenbezogene Daten umzugehen ist. Das betrifft alle Unternehmen, die europäische Kunden haben.

Es gibt allerdings auch Branchen, die mit Daten noch vorsichtiger umgehen müssen. Damit meine ich Berufsgeheimnisträger. Darunter fallen zum Beispiel Ärzte und Rechtsanwälte. Daten, die Rechtsanwälten anvertraut wurden und die von Rechtsanwälten generiert werden, müssen besonders gut geschützt werden. Dazu gibt es das “Gesetz zur Neuregelung des Schutzes von Geheimnissen bei der Mitwirkung Dritter an der Berufsausübung schweigepflichtiger Personen“. Seit November 2017 gilt dieses Gesetz und seitdem dürfen Anwälte überhaupt erst Cloud-Dienstleistungen in Anspruch nehmen. Eine Vorgabe aus diesem Gesetz ist zum Beispiel, dass Daten nur dann im Ausland verarbeitet oder gespeichert werden dürfen, wenn in diesem Land der Schutz des Geheimnisses vergleichbar ist mit dem Schutz des Geheimnisses in Deutschland.

Es gibt noch ein Gesetz, das in diesem Zusammenhang sehr wichtig ist: Der C.L.O.U.D. Act. Der C.L.O.U.D. Act ist ein Gesetz der Amerikaner. Er erlaubt es der amerikanischen Regierung jeden amerikanischen Cloud Service Provider dazu zu verpflichten, Kundendaten herauszugeben, egal wo auf der Welt diese gespeichert sind. Das hat natürlich eine dramatische Konsequenz für Daten, die besonders geschützt werden müssen. Rechtsanwälte können ihre Daten nicht einfach in ein beliebiges Rechenzentrum eines amerikanischen Betreibers in Frankfurt laden, weil die amerikanische Regierung den amerikanischen Konzern, dazu verpflichten kann, die Daten herauszugeben, obwohl die Daten in Deutschland gespeichert sind. Das ist ein echtes Problem und würde Lösungen auf Cloud-Angebote deutscher Konzerne reduzieren.

Es gibt noch eine andere Lösung: Verschlüsselung. Daten können verschlüsselt werden, bevor sie in die Cloud hochgeladen werden. Solange der Schlüssel nicht auch in der Cloud liegt, können die Daten gefahrlos weitergegeben werden. Jeder Empfänger, der den geheimen Schlüssel nicht hat, kann sie nicht lesen. Jetzt müssen nur noch die Schlüssel gut geschützt werden. Bei einer echten Ende-Zu-Ende Verschlüsselung, wie sie beispielsweise von WhatsApp oder Skype genutzt wird, kann ein Datensatz nur genau von der Person entschlüsselt werden, an die der Datensatz adressiert ist. Keine andere Person, Admin oder Regierung kann die Daten entschlüsseln, weil sie die nötigen Schlüssel nicht haben. In den letzten Jahren sind die dafür nötigen kryptographischen Routinen sogar nativ in unsere Browser eingebaut worden. Das W3C hat mit der Web Crypto API jede Web-App dazu befähigt, Daten zu verschlüsseln und wieder zu entschlüsseln. Es ist nicht mehr nötig, dazu eine eigene Software zu installieren.

Und dank dieser Verschlüsselung können wir unseren Kunden einen Sicherheitsstandard implementieren, der erstens die Gesetze berücksichtigt und zweitens Daten mit maximaler kryptographischer Sicherheit schützt.

Demo

Hier ist ein Beispiel für eine verschlüsselte Nachricht:

pzelMxzbY7p5x3OnU+7Lq0gzvSK3HV4LTBYwvtyqlpSNFtwKaXhyit3q0g8qu+QMtjD3pH4MDxzDuO0WXhrXv8E/nAYXV39b+L8OVZekxa/zszL+4sMBM2YlOt/BiMt/CA5ct8vh0b6kUDiv5pfv0kckfmiY7fq6S7dRWoP+4fCBbeNzcC2sI2HdjdcYYB9tv/yahlr+9GZ9Z3OYbaWaXX/4Lf3Q/rN9bCTmHNES//76ZjVnko2RC9cyRPKeRKnIRVC8OnGewFzPqMvBkkL6D3nRBd+f1FeyO1LkE1E2AAvqjWTvShASpnGkem5VXyoQzO4WgJQXJdx30SbNr0xMvRj7fzsK2F6Jl4MWqZAud+CjIUzqtkFWbBtBdojsek2LuM+D+EiA4lqwMXa64xZ5SWAFS6EEt4ZOkE9CcNGdDAmELj4IugSlea9/wDP3UsDx+4QX+FuV125wyigFkz+JFnbYg93LbqyvoPBP0Quay2IWno8lDo9NdM+1PCKRDHB++9kjT7t468qrdRqgKwuNlOb3W8WrJMLbAd8B3npHmHlIBxVUXrHZicACiAkcv8JAreguh47Bkp9a0OixYnShfeCi+aCo/oeA3XiddZANkO7oGHHPhAaguWaG3VHZ0spPO80FK6o4OUpvkaOF9QYf+rURUMxh96E9Z/aQwFyoVJw5/TcbUMJQdggiu2osszFFYCfWd3gOnVpe2LVZVM8bvQssH9k9AlRyH4j+jabzdYqrDDK8l4NQR3yRIcYbCoJyMbuWiPlSBy0jnLU5HOV8WfgnKxJKvtQdC+ykN3qXHM/uGYPmcp4fkVJwF1a3wkqkg7G610OAVTE0D0AK5a7pdOKWDuk78M6Hd+1+b6brMDhTyuB+LUD9dC4WnmGGi74TVvTQ2I8Oaa+TFDqreV2e+8eJCSgvZjSszKvOZ/vbXKhvJh0+7JNZuZQMyuvloiyjuS8m553RDgrgm5LRkp7xUFEXcXIkxmPUtWaOOVpcggtCm0o78iP2KLHNUz28EP/sAPWluucxCjCjggaJ9bJ7eOD56jBnlORYFQSTeVQXWlqIJta6rIVyW1WpY7mhhfNnOr5qFfa6uYOubBgwzs3knof88codUMe0lor/NQIKUkxIB5FNWEjbeNvnczJtsEfP86Bask1X35O/6I3Nwl0xKDctBQ834YWJk4+TLtFMf3Gaf3C4dYVGJPhoK7XWLZf0YbRaxcZ876bADQNH13aiK8TD6cWJ93Q45DFPQMDL0LyRgEWQjvIWHPc29QGXyyOZhDnQdTCOMjLGV7mdijnuKvCkc644yr3IANNWNb7D0lBuJC6wxbdeQ3lJgrilvTlzLvc14kIN48IvNAn9wxiXR1OIp9yeW7mXd158YDoTkW8S+PxCa4k/9qLW933LM9gTxpXqwKOnpby27sUCGrgb0Gu7NdN9NYtYQfS9ZDCWa1Oy39n9I7XIl8X0KaLI9MGCsrfTDZ7KTD1Zk9rWsRXIB+W11ftKzG8GN9ezO9u0RzHBA/5cCyyrs8i1nmgM4jLGKDwH5od6BHL8VbXgk8FPlF6zz8C1liN8RmHdrJ3edqtEA/rgcrXEOfkB2O9cqzJVm9ZwrVvQLalLQvLQcqG5Vhes28FGPSJH+kb/4XZ7Blx1sdsHEKBHc9IHNd8coUEgfgADSsez/ftww8OEPdrLeo1Lwipv6fUiMwJ31jaYDA2sthV6clEtQ4X9iWeprjEfQr1hWSqgyj6YKojZno1OuBwKGS+rqXbDqO97CpsyiXE+jbqYPw+uxCPBeiRf3cmh0BYoKJH83y19SUgqOqtkEjrho8Eme3OL0GcQDoflWG8DjzTZjp3xlwqOoVTa9zKeDWqYSBoMI73uxAe8kjgnIYRXhroh9j9gVKXGkdhN3ZLXJCUQt5d+ebKYJ8aFbfykE9WtSTbb8cmh8XNAbfI1i+vdQNvCHAVyWqNMT6y0KSUOR3uxQTRvXFXTvONNBqPJOb8hN/Io1iqGaBbADjUlu2xhcaZV4yApMDa02kzuslNfxY1hNu0lXlsJ4dJr4TidyCx5Io0jzUq9krxY3BmQ8asm/QElcGWEYkgroyvNvCZUYYriyCGORynXQOktgWdO0i/Z0N8JN3pm3WhTCOrh

Diese Nachricht ist mit den Verfahren Salsa20 (stream cipher developed by Daniel J. Bernstein) und Poly1305 (cryptographic message authentication code (MAC) created by Daniel J. Bernstein.) verschlüsselt worden. Diese Verfahren sind nicht Teil der Web Crypto API sondern können über die NACL-Bibliothek eingesetzt werden. Um die obige Nachricht zu entschlüsseln, kann die Beispielseite https://tweetnacl.js.org/#/secretbox verwendet werden. Dort dann der Cipher-Text in das Box-Feld kopiert werden. Gleichzeitig müssen auch noch folgende Nonce und folgender Schlüssel kopiert werden. Der Schlüssel müsste natürlich geheim gehalten werden.

Nonce
BjPvjG2ibzqnTayXhNCtxxo5J7t72Qfi

Schlüssel
8qsjT9mNMwXUEpkthvPP3JZPhwEuwg077sJV+IikwSo=

Kaufen oder selber machen?

Entwicklungsteams stehen regelmäßig vor der Frage, ob ein Stück Software eingekauft oder selbst gemacht werden sollte. Diese Frage stellt sich sogar nicht nur Softwareentwicklern sondern jedem Menschen. Mache ich etwas selbst oder lasse ich es einen Experten machen? Bin ich der Experte oder ist der andere der Experte? Investiere ich Zeit und spare Geld oder investiere ich Geld und spare Zeit? Soziologie und die eigene Weltanschauung spielen bei der Beantwortung dieser Fragen und bei Entscheidungen eine große Rolle.

Um in der Welt der Softwareentwicklung zu bleiben, ist hier ein kleines Beispiel. Es geht um ein Web-Template. Es kann entweder ein fertiges Template gekauft werden oder man kann das Template selber bauen. Zunächst können einmal die Vor- und Nachteile beider Alternativen gegenübergestellt werden.

Kaufen

Vorteile

  • Das Template ist bereits fertig und kann sofort verwendet werden. Bei Bedarf kann es noch ein wenig angepasst werden, aber es ist bereits vollständig und umfangreich.
  • Das Template ist professionell gestaltet. Design, Layout und Look & Feel sind konsequent und kongruent.

Nachteile

  • Manche Komponenten sind nicht gut genug. Es gibt bessere Lösungen für Inputs, Tabellen und Charts.
  • Das Template ist schwergewichtig. Es enthält viele Komponenten und Funktionen, die gar nicht gebraucht werden.

Selber bauen

Vorteile

  • Ein eigenes Template ist maximal flexibel. Es können beliebige Komponenten verwendet werden.
  • Ein eigenes Template ist leichtgewichtig. Es enthält nur genau die Funktionen und Komponenten, die benötigt werden.

Nachteile

  • Ein eigenes Template muss erstmal entwickelt werden. Es entsteht Basisaufwand, der leicht unterschätzt wird.
  • Ein eigenes Template ist lange unvollständig. Vor allem wenn die Lösung in Design, Layout, Responsiveness und Look & Feel vergleichbar sein soll.

In dieser Gegenüberstellung kann der Begriff “Template” durch “Lösung” ersetzen werden. Das Schema bleibt gleich.

Eigene Meinung

Um maximal produktiv zu sein, würde ich jederzeit Geld in Zeit eintauschen. Um Zeit zu sparen bin ich bereit Geld zu investieren. Natürlich muss der Preis verhältnismäßig sein, aber darum geht es hier nicht. Die Nachteile einer gekauften Lösung sind schnell kompensiert. Unzulängliche Komponenten können durch bessere ersetzt werden. Nicht verwendete Funktionen können entfernt und das Template somit leichtgewichtiger gemacht werden. Diese Anpassungen sind unkompliziert und schnell. Es war schon immer leichter Dinge wegzulassen, als sie neu zu schreiben. Dadurch werden die Vorteile der Eigenentwicklung relativiert.

Wir sollten anfangen, an unseren USPs zu arbeiten statt uns an 0815-Basisentwicklung aufzuhalten. Wir neigen schnell dazu alles selber machen zu wollen. Manche Dinge müssen leider aus technischen, fachlichen und rechtlichen Gründen selbst gemacht werden. Da können dann keine fertigen Lösungen verwendet werden. Aber es gibt auch viele andere Dinge, bei denen von fertigen Lösungen profitiert werden könnte. Oft wird dort dann allerdings auch gerne auf den Produktivitäts-Boost verzichtet und die Lösung ebenfalls selbst gebaut.
Das ist das klassische Not Invented Here Syndrome. Man glaubt, dass die Eigenentwicklung besser, kontrollierter und schneller erfolgt als die bestehende. Verhaltensforscher führen viele Gründe für die Abneigung gegenüber Bestehendem an. Die prominentesten Gründe sind Mangel an Verständnis der bestehende Lösung und die Unwilligkeit, die Arbeit anderer anzuerkennen oder zu schätzen. Leslie Hannah führt dieses soziale Phänomen sogar auf eine Form des Tribalismus zurück.

Entscheidung

Am Ende des Tages steht eine Entscheidung. Entscheidungen müssen uns in die Lage versetzen, schnell und gut handeln zu können. Natürlich können wir alles mögliche entscheiden, aber wenn wir das Entschiedene nicht umsetzen können, ist die Entscheidung hinderlich und lähmend. Die Entscheidung “Kaufen” oder “Selber bauen” kann also nicht sinnvoll von oben entschieden werden. Deswegen müssen diejenigen, die viel mit dem Ergebnis arbeiten werden, auch aktiv mitentscheiden. Diejenigen, die wenig oder gar nicht mit dem Ergebnis arbeiten, dürfen auch nur wenig mitentscheiden. Was aber sehr wohl vorgegeben werden kann, sind Anforderungen und Budget. In diesem Kontext ist es dann die Verantwortung der Entwickler, die Ressourcen nicht zu verschwenden und die beste technische Lösung zu finden.

STP LabsDay 2018

Innovation wird heutzutage sehr groß geschrieben und deswegen veranstaltet STP regelmäßg den STP LabsDay. Am vergangenen Donnerstag und Freitag (26. und 27. April 2018) habe ich wieder an diesem internen 24h-Hackathon teilgenommen. Während der Arbeitszeit haben wir an diesen zwei Tagen die Gelegenheit, eine neue Idee auszuprobieren. STP übernimmt an beiden Tagen komplett die Verpflegung und Marketing hat uns wieder mit einem stylischen Geschenk überrascht. Beste Voraussetzungen für zwei Tage Innovationsarbeit.

Aktuell beschäftigt mich das Thema “Intelligent Cloud & Intelligent Edge”, sodass ich in diesem Jahr unbedingt etwas mit Cloud und Web machen wollte. Aber nicht einfach nur das nächste Angular oder Aurelia Projekt. Ich wollte Bleeding Edge Web Technologien ausprobieren. Es musste also unbedingt eine Progressive Web App sein, am besten in Verbindung mit Push Notifications. Ein Use Case ist mir auch sofort eingefallen: Kundenbenachrichtigung, egal ob der Kunde ein Gläubiger oder ein anderer Mandant ist. Das Projekt Mandate Updates hatte begonnen. Glücklicherweise konnte ich einen meiner Kollegen für dieses Szenario und die erwähnten Technologien begeistern und somit einen Partner für mein LabsDay-Projekt gewinnen. Es gibt nämlich nur eine einzige LabsDay-Regel: man muss mindestens zu zweit sein.

Am Donnerstag um 11 Uhr ging es endlich los. Nachdem wir uns über den Umfang des Projekts im Klaren waren, haben wir uns aufgeteilt. Mein Kollege hat sich auf das mit Azure Active Directory gesicherte Backend in Form einer ASP.NET Core 2 Web API gestürtzt, während ich versuchte, den PushManager mit dem ServerWorker zu verbinden. Der Anfang fiel uns beiden leicht und wir kamen gut voran. Nachmittags konnte unsere PWA sich bereits auf Datenänderungen im Backend registrieren und wurde asychron benachrichtigt, wenn eine solche Datenänderung stattgefunden hatte. Die erste angezeigte Toast Push Notification war etwas ganz besonderes für mich. Wir brauchten nichts installieren und die Seite musste noch nicht einmal offen sein und wir wurden trotzdem asynchron informiert. Super. Jetzt hatten wir allerdings die ersten Schwierigkeiten. Solange die Seite offen ist, wollten wir keine Toast Notification sehen, sondern die Seite soll sich einfach aktualisieren. Ungefähr drei Stunden und 20 Zeilen ServiceWorker-JavaScript-Code später hatten wir das Problem gelöst. Danach wollten wir das bis jetzt noch unabhängige System in unser ERP-System LEXolution.KMS integrieren. Glücklicherweise hatte ich vor ein paar Monaten LEXolution.KMS bereits in die Cloud portiert und als KMSX mit Azure Active Directory Authentication gehostet. Mit Azure Active Directory konnten wir uns also an KMSX anmelden und ebenfalls ein JWT Access Token für unsere Mandate Updates API erhalten. Bis spät in die Nacht haben wir KMSX um die Mandate Updates Funktion erweitert. Sobald der Sachbearbeiter jetzt in LEXolution.KMS bei der Akte einen Text hinterlegt, wird dieser automatisch in alle Browser gepusht, die sich im Vorfeld für Benachrichtigungen bei dieser Akte registriert hatten. Dafür kann der Sachbearbeiter zu jeder Akte eine eindeutige URL ermitteln, die der Mandant im Browser besuchen und dort sämtliche Benachrichtigungen zu dieser Akte einsehen kann. Kommen neue Benachrichtigungen hinzu, wird die Seite automatisch aktualisiert oder es wird eine Toast Notification gezeigt. Nach einem Klick auf diese Notification kann der Mandant wieder direkt alle Akten-Benachrichtigungen sehen. Wir hatten es geschafft, unser Szenario war implementiert.

Am nächsten Morgen habe ich meinen Kollegen bereits in der Bahn getroffen. Dort konnten wir uns im Rahmen eines Daily Scrums direkt abstimmen, ohne wertvolle Präsentationsvorbereitungszeit zu verlieren. Wieder im Büro angekommen hatten wir noch vier Stunden Zeit, bis wir unser Projekt präsentieren würden. Zuallererst haben wir nochmal unsere Push Notifications getestet und zwar mit dem Handy meines Kollegen. Es funktionierte alles hervorragend. Obwohl alle Anwendungen auf seinem Smartphone geschlossen waren, wurde meine KMSX-Aktenänderung direkt in Form einer Push Notification auf seinem Handy anzeigt. Anschließend widmete sich mein Kollege der Integration von Mandate Updates in ein weiteres Software System der STP. Ich fing an die Präsentation vorzubereiten und die Demo zu planen. Plötzlich funktionierten meine Push Notifications nicht mehr. Sie wurden einfach nicht mehr angezeigt, sobald ich den Browser geschlossen hatte. Nach einiger Zeit habe ich dann bei einer Internet Recherche herausgefunden, dass Push Notifications nicht mehr dispatched werden können, wenn alle Browser-Fenster geschlossen sind. Wahrscheinlich hatte ich bei allen vorherigen Versuchen irgendwo noch ein Chrome-Fenster im Hintergrund offen, sodass die Notifications verarbeitet werden konnten. Dieser Unterschied zwischen Desktop und Mobile ist wirklich bemerkenswert. Irgendwie haben wir es dann noch geschafft unsere Präsentation vorzubereiten und auch noch etwas Essen zu gehen.

Anschließend haben alle Teams ihre Ergebnisse präsentiert. STP hatte zu dieser Präsentation wieder einen Kunden und alle Vorstände eingeladen. Während der Präsentation gingen unsere Push Notifications anfänglich wieder nicht, wurden dann aber mit etwas Verspätung doch noch angezeigt. Mandate Updates war ein voller Erfolg und wurde sogar mit dem Kundenpreis ausgezeichnet. Natürlich wird Mandate Updates mit asynchronen Push Notifications die Kommunikation mit Telefon und E-Mail nicht ablösen, aber es erweitert diese. Mit Mandate Updates bekommen Sie einen neuen Kanal zu Ihren Mandanten.

Mein Kollege und ich hatten viel Spaß bei der Umsetzung und wir haben beide eine Menge gelernt. Ich bin mir sicher, dass alle Teams eine Menge gelernt haben. Herzlichen Glückwunsch auch an 1nicerUploader und Time Rocket, die den “leider geil”- und den Vorstands-Preis gewonnen haben. Sieben Teams sind insgesamt gestartet und auch wenn nur drei Teams mit einem Preis ausgezeichnet werden konnten, alle STP-LabsDay-2018-Projekte haben die gesamte Firma deutlich motiviert und inspiriert. Ein großartiges Event!

Pair Programming Compatibility

Vor einiger Zeit habe ich über einige nachteilige Effekte beim Pair Programming geschrieben. Dabei habe ich verschiedene Symptome, Personas und Verbesserungsmöglichkeiten vorgestellt.
Trotzdem hat mich Pair Programming weiterhin beschäftigt. Ich bin das Gefühl nicht losgeworden, noch nicht genug über diese Form der Zusammenarbeit gelernt zu haben. Also habe ich wieder viele Pairs beobachtet und meine Beobachtungen mit Kollegen und Freunden diskutiert. Ich habe versucht echte Indikatoren für erfolgreiche oder problematische Pair Programming Konstellationen zu finden. Im Laufe des Jahres sind mir einige zusammenhängende Faktoren und Muster immer wieder aufgefallen, die ich im folgenden beschreiben möchte. Das hier ist das Pair Programming Compatibility-Modell.

Manchmal läuft Pair Programming richtig gut und manchmal klappt es überhaupt nicht. Das eine Mal ist es sehr hilfreich zu zweit zu arbeiten und man ist richtig produktiv. Ein anderes Mal ist es ganz anders und sehr anstrengend. Jeder, der öfters im Pair arbeitet, kennt das. Doch warum kommt uns Pair Programming in manchen Situationen effektiver vor als in anderen?
Meines Erachtens kann das auf drei Aspekte reduziert werden, die ich im folgenden Schaubild als Dimensionen dargestellt habe: Leicht-Schwer, Homogen-Heterogen, Monoton-Kreativ. Nach meiner Erfahrung ist Pair Programming sehr effektiv, wenn sich Aufgabe, Team und Vorgehen jeweils in der Mitte dieser Spektren, also in Balance, befinden (grüne Zonen). Sobald sich eine Dimension einem Extrempunkt annähert, merken die Beteiligten recht schnell, dass etwas nicht ganz stimmig ist und Pair Programming irgendwie nicht funktioniert (rote Zonen). Natürlich kann man dann auch Pair Programming machen, aber meiner Meinung nach überwiegen dann die negativen Effekte, die dem Unternehmen schaden.

Die erste Dimension bezieht sich auf die Aufgabe oder Anforderung. Ist diese sehr leicht, könnte ein einzelner Entwickler die Aufgabe wegen geringer Fehleranfälligkeit genauso gut aber wesentlich schneller lösen. Ist die Aufgabe auf der anderen Seite sehr schwer, ist erhöhte Konzentration und Ruhe nötig, die Entwickler meistens nur alleine finden.

Die zweite Dimension bezieht sich auf das Team, also die zwei Entwickler, die zusammen Pair Programming machen. In einem sehr homogenen Team bleiben hilfreiche Ideen und Impulse eines Andersdenkenden aus und soziales Faulenzen entsteht. In einem sehr heterogenen Team besteht viel Erklärungsbedarf und es entstehen viele Diskussionen, die Zeit und Energie kosten.

Die dritte Dimension bezieht sich auf die Umsetzung der Aufgabe durch das Team. Wenn es sich dabei um eine sehr monotone Tätigkeit handelt, gibt es wenig Potential für Verbesserung. Die Tätigkeit kann dann schneller alleine realisiert werden. Wird auf der anderen Seite sehr kreativ gearbeitet, müssen oft viele verschiedene Dinge überlegt, recherchiert und ausprobiert werden, was zu zweit eher hinderlich ist.

Wenn Aufgabe, Team und Vorgehen sich um die Mittelpunkte der erwähnten Aspekte bewegen, ist Pair Programming meiner Meinung nach optimal geeignet. Im oberen Schaubild wäre das die Überlagerung der grünen Zonen, die im dreidimensionalen Raum eine Kugel bilden. In diesem Bereich wollen wir arbeiten. Wenn die Aufgabe aber sehr einfach, das Team sehr homogen und das Vorgehen sehr monoton ist, ist Pair Programming meines Erachtens Verschwendung von Entwicklungsenergie. Willkommen in der Zone der Verschwendung.
Wenn die Aufgabe sehr schwer, das Team sehr heterogen und das Vorgehen sehr kreativ ist, dann ist Pair Programming nach meiner Erfahrung hinderlich, störend und bremst Lösungsfindungen zu stark aus. Willkommen in der Zone der gegenseitigen Behinderung.

Man rechnet ja gerne mit der doppelten Bearbeitungszeit im Worst Case, wenn man eine Aufgabe zu zweit bearbeitet. In der Zone der Verschwendung ist das auch so. In der Zone der gegenseitigen Behinderung kommt zu der doppelten Zeit durch zwei Bearbeiter noch der Effekt dazu, dass die Arbeit durch gegenseitige Behinderung ja auch noch langsamer erfolgt. Und wenn die Bearbeitung dann nur noch halb so schnell erfolgt, dann dauert sie doppelt so lange. Es wird also im Durchschnitt die vierfache Zeit gebraucht. Die Implementierung wird aber nur marginal besser. Das danach eine vergleichbare Aufgabe bearbeitet werden muss, die auch parallel hätte bearbeitet werden können, verdoppelt die Durchlaufzeit nochmal.

Nachteile vs. Vorteile

Es gibt natürlich viele Gründe, warum man Pair Programming macht. Mehr Qualität, man lernt dazu, man fühlt sich nicht so einsam bei der Arbeit oder weiß nicht an was man arbeiten soll. Alle diese Gründe sind gut und wichtig, aber nicht alle sind in einem professionellen Umfeld auch angemessen. Um das Ziel, das hinter diesen Gründen steht, zu erreichen, müssen bestimmte Voraussetzungen erfüllt sein. Qualität ist wichtig, aber nach meiner Erfahrung arbeitet nicht jedes Pair qualitativer. Nur Pairs, die sich gegenseitig ergänzen und ersetzen können, also nicht zu homogen und nicht zu heterogen sind, erreichen gemeinsam mehr. Zu ungleiche oder zu gleiche Pairs erreichen sogar eher das Gegenteil. Genau wie die Leistungsfähigkeit nimmt auch die Konzentrationsbereitschaft im Team durch Social Loafing ab, sodass komplizierte Aufgaben nicht geeignet umgesetzt werden können. Lernen ist auch sehr wichtig und wenn es nur um Know-How-Transfer gehen würde, wäre das auch kein Problem. Aber es geht ja noch um viel mehr: Guten Code, Inhalte, Funktionen und Termine einhalten. Know-How-Transfer durch Pair Programming ist möglich aber nach meiner Erfahrung ineffizient und uneffektiv. Es gibt didaktisch sinnvollere Methoden um zu lernen, wie beispielsweise Coding Dojos und Supervised Learning. Wenn man dennoch mit Pair Programming lernen will, müsste man konsequenterweise Themen-spezifisch pairen: Für Domänen-Know-How mit Domänen-Experten, für Architektur-Know-How Pairing mit den Architekten und für Coding-Know-How mit den Entwicklern. Je ungleicher die Wissensstände der Personen sind, desto mehr lernt die Person beim Pair Programming auf Kosten der anderen Vorteile von Pair Programming, was die Umsetzung hindert und in der Regel zu schlechteren Lösungen und längerer Bearbeitung führt.

Die negativen Effekte von Pair Programming in den roten Zonen, wie beispielsweise wenig Konzentration, anstrengende Diskussionen, soziales Faulenzen und vierfache Bearbeitungszeiten, sind nicht zu unterschätzen. Deswegen müssen wir lernen zu erkennen, ob wir uns gerade in der Zone der Verschwendung oder in der Zone der gegenseitigen Behinderung befinden. Wenn wir uns in einer dieser roten Zonen wiederfinden, ist es unsere Verantwortung als professionelle Entwickler gegenzusteuern und Pair Programming vielleicht sogar abzubrechen. Weiterhin ist es eine große Gefahr, sich an Pair Programming zu gewöhnen, da uns die beschriebenen Zonen nicht mehr auffallen oder, noch schlimmer, egal werden. Abhängig von Aufgabe, Team und Vorgehen macht manchmal Pair Programming und manchmal alleine arbeiten Sinn. Wenn wir dann zu zweit arbeiten hilft uns das Wissen über die Zonen des Pair Programming Compatibility-Modells um Effizienz- und Effektivitätsverluste rechtzeitig zu erkennen und auszugleichen.