Digitale Transformation: Praktische Tipps eines Software Engineers

AvatarRoman Wünsche·· 12 min

Eine digitale Transformation kann herausfordernd sein. In diesem Artikel möchte ich dir mein Wissen als Software Engineer weitergeben und dir einige Techniken und Tools aufzeigen, damit du deine Daten digitalisieren, bereitstellen und in deine Abläufe integrieren kannst.

Was ist digitale Transformation?

Kurz gesagt, es geht darum, analoge Informationen in digitale Formate umzuwandeln, Geschäftsprozesse aller Art zu digitalisieren und dein Unternehmen vollumfänglich auf die neuen, digitale Technologien auszurichten.

Hierdurch kannst du beispielsweise deine Systeme miteinander verknüpfen, Abläufe und Prozesse automatisieren und deinen Kunden gewisse Aktionen im Self-Service anbieten, ohne das du händisch eingreifen musst.

Warum ist digitale Transformation wichtig?

Durch die digitale Transformation kannst du deine Effizienz steigern, deine Kosten senken und deinen Kunden einen besseren Service bieten.

Daten und Technologie helfen dir, dein Produkt noch besser zu machen und ggfs. gar neue Märkte zu erschliessen, welche du zuvor gar nicht im Auge hattest. Und sind wir ehrlich: Machst du es nicht, wirst du und dein Unternehmen über kurz oder lang von einem Konkurrenten überholt.

Wie geht digitale Transformation?

Es ist ein kultureller Wandel notwendig, welcher alle Bereiche deines Unternehmens betrifft. Neue Arbeitsweisen, neue Prozesse und Denkweisen. Als Solution Architect und Software Engineer ist man von Anfang an bei diesem Prozess beteiligt und baut Lösungen, die einen beim Weg zur digitalen Transformation unterstützen.

Nachfolgend möchte ich dir einige Schritte aufzeigen, wie du deine Daten digitalisierst, weiteren Systemen bereitstellst, die Datenintegrität sicherstellst und die Software-Anwendungen so aufbaust, dass diese auch mit grossen Datenmengen umgehen können und immer erreichbar sind. Bereit? Dann fangen wir an.

Schritt 1: Digitalisierung der Daten

Vor der digitalen Transformation steht die Digitalisierung: Sind deine Daten in Papierform vorhanden, müssen diese erst einmal in ein Format umgewandelt werden, womit eine Software umgehen kann.

Ein Dokument wird also erst einmal eingescannt und in ein Bild oder PDF überführt. Obwohl nun digital, kann man damit noch nicht wirklich viel anfangen. Die Daten müssen erst aus dem Bild extrahiert werden.

Hierzu eignet sich die OCR-Erkennung (Optical Character Recognition). OCR ist gut bei gescannten Dokumenten, welche zuvor mit dem Computer erzeugt wurden. Eine bewährte Software-Bibliothek hierfür ist tesseract - eine Open Source Lösung von Google (Link). Bei handschriftlich verfassten Texten oder Layoutelementen (Skizzen, Tabellen usw.) wird es allerdings schwierig. Hier kann Machine-Learning (ML) abhilfe schaffen. Die Cloud-Lösung von AWS genannt Textract wär ein gutes Beispiel, welches sehr gute Ergebnisse liefert (Link). Nachteil: Du gibst deine Daten hier nach Aussen weiter, was aus regulatorischen und Datenschutzgründen problematisch sein kann.

Beispiel: Aus Bild wird Text

Willst du tiefer in die Materie eintauchen und verstehen, wie man mittels Software hier genau vorgeht? Dann habe ich dir nachfolgend ein einfaches Beispiel mit tesseract und Textract angefügt.

Machen wir ein einfaches Beispiel mit dem Titel und ein paar Metadaten dieses Artikels: Beispielbild eines eingescannten DokumentesBeispielbild eines eingescannten Dokumentes

Installation (Homebrew; Mac)

sh
$ brew install tesseract $ brew install tesseract-lang

Umwandlung

sh
$ tesseract /path/to/image.jpeg output -l deu

Ergebnis

sh
$ cat output.txt Artikel No. 1 So gelingt digitale Transformation: Experten Tipps eines Software Engineers von Roman Wünsche Am 04.11.2023

oder mit dem Argument tsv für weitere Details

sh
$ tesseract /path/to/image.jpeg output -l deu tsv $ cat output.tsv level page_num block_num par_num line_num word_num left top width height conf text 1 1 0 0 0 0 0 0 1784 758 -1 2 1 1 0 0 0 20 44 225 31 -1 3 1 1 1 0 0 20 44 225 31 -1 4 1 1 1 1 0 20 44 225 31 -1 5 1 1 1 1 1 20 44 117 31 96.779533 Artikel 5 1 1 1 1 2 154 44 61 31 96.467613 No. 5 1 1 1 1 3 233 44 12 31 96.713226 1 2 1 2 0 0 0 64 176 1616 333 -1 3 1 2 1 0 0 64 176 1616 333 -1 4 1 2 1 1 0 64 176 1616 92 -1 5 1 2 1 1 1 64 176 120 75 96.492661 So 5 1 2 1 1 2 219 178 318 90 96.039734 gelingt 5 1 2 1 1 3 569 178 340 90 96.670525 digitale 5 1 2 1 1 4 941 178 739 72 96.658165 Transformation: 4 1 2 1 2 0 159 297 1434 91 -1 5 1 2 1 2 1 159 299 413 89 96.172516 Experten 5 1 2 1 2 2 605 299 257 89 95.738785 Tipps 5 1 2 1 2 3 895 299 247 72 96.478409 eines 5 1 2 1 2 4 1173 297 420 75 96.198662 Software 4 1 2 1 3 0 644 419 465 90 -1 5 1 2 1 3 1 644 419 465 90 96.183083 Engineers 2 1 3 0 0 0 689 601 370 71 -1 3 1 3 1 0 0 689 601 370 71 -1 4 1 3 1 1 0 689 601 370 28 -1 5 1 3 1 1 1 689 608 60 21 96.241890 von 5 1 3 1 1 2 765 601 119 28 96.603874 Roman 5 1 3 1 1 3 898 601 161 28 96.008430 Wünsche 4 1 3 1 2 0 742 644 262 28 -1 5 1 3 1 2 1 742 644 56 28 96.711449 Am 5 1 3 1 2 2 812 644 192 28 96.473007 04.11.2023
js
import {DetectDocumentTextCommand, TextractClient} from "@aws-sdk/client-textract"; const image = '/path/to/image.jpg'; const client = new TextractClient({ region: '<AWS_REGION>', credentials: { accessKeyId: '<AWS_ACCESS_KEY>', secretAccessKey: '<AWS_SECRET_KEY>', }, }); const blob = Buffer.from(image.split(',')[1], 'base64'); const params = { Document: { Bytes: blob, }, FeatureTypes: [], }; const command = new DetectDocumentTextCommand(params); const data = await client.send(command); if (data?.Blocks) { console.log(data.Blocks); let text = '' data.Blocks.map((block) => { if (block.BlockType === 'WORD') { text += ' ' + block.Text } }) console.log(text); }

Ergebnis Wörter als JSON mit Metadaten wie dem Confidence-Level:

json
{ "BlockType": "WORD", "Confidence": 99.81639099121094, // ... "Text": "Artikel", }, { "BlockType": "WORD", "Confidence": 99.81639099121094, // ... "Text": "Artikel", } Confidence: 99.96634674072266

Oder gefiltert nach Text und BlockType:

text
Artikel No. 1 So gelingt digitale Transformation: Experten Tipps eines Software Engineers von Roman Wünsche Am 04.11.2023

Schritt 2: Semantische- und strukturierte Daten

OCR- oder ML-Algorithmen liefern uns nun also die Text-Daten in Rohform. Doch wie kann die Software wissen, worum es sich bei den ermittelten Texten genau handelt? Aus einem Bild semantische Daten zu generieren, d.h. die Daten um Kontext und Bedeutung anzureichern ist für Software sehr schwierig.

Klassische OCR-Technik stösst hierbei an seine Grenzen. Der moderne Weg auch hier: Machine-Learning. Mithilfe grosser Datenmengen kann eine Software dafür trainiert werden. Man könnte beispielsweise eine bereits trainierte KI wie ChatGPT bitten, die Daten zu strukturieren. Das geht, weil ChatGPT auf einem riesigen Sprachmodell (Large Language Model, LLM) basiert. Für kleinere Lösungen reicht aber auch ein klassischer Parser. Ein Parser ist ein Stück Software, mit welchem Text oder andere Daten in ein strukturiertes Format umgewandelt werden können.

Der ermittelte Text aus obigem Beispiel wird nun anhand einer RegEx-Regel in seine Einzelteile zerlegt, von Hand mit Kontext angereichert und in ein strukturiertes Format überführt (JSON).

js
const text = 'Artikel No.1 So gelingt digitale Transformation: Experten Tipps eines Software Engineers von Roman Wünsche Am 04.11.2023'; const regex = /(?:No.)(\d)(.*)(?:von\s)(.*)(?:Am\s)(\d{2}.\d{2}.\d{4})/gim; const match = regex.exec(text); const json = JSON.stringify({ number: match[1], title: match[2].trim(), author: match[3], date: match[4] })

Das Ergebnis:

json
{ "number": "1", "title": "So gelingt digitale Transformation: Experten Tipps eines Software Engineers", "author": "Roman Wünsche", "date": "04.11.2023" }

Schritt 3: Prüfen und Normalisieren der Daten

Bevor digitalisierte Daten flächendeckend genutzt werden, sollten diese plausibilisiert und normalisiert werden.

Besonders ersteres ist nicht immer einfach. OCR oder ML-Algorithmen machen Fehler. Je schlechter das Ausgangsmaterial, desto wahrscheinlicher schleichen sich Ungereimtheiten ein. Glücklicherweise liefern obige Lösungen zu jedem umgewandelten Wort einen internen Zuversichtswert in Prozent. Je niedriger, desto fehlerbehafteter das Ergebnis.

Neben diesen Werten kann ein Software Engineer aber noch weitere Massnahmen treffen: Ist einem bekannt, was die Daten genau beinhalten dürfen, können diese gefiltert und ungewollten Zeichen entfernt oder umgewandelt werden. Wir können auch noch tiefer gehen und einen Datenabgleich mit einem anderen System durchführen. Beispielsweise ein Adressabgleich über die API der Schweizer Post. Hier sind uns keine Grenzen gesetzt.

Zum Schluss erfolgt die Normalisierung: Hierdurch bringen wir die Daten auf eine gemeinsame Basis und machen diese miteinander vergleichbar.

Nehmen wir nochmals das Ergebnis von vorhin zur Hand:

json
{ "number": "1", "title": "So gelingt digitale Transformation: Experten Tipps eines Software Engineers", "author": "Roman Wünsche", "date": "04.11.2023" }

Schaut soweit gut aus, doch die Daten sind alle reiner Text - in der Software spricht man von String's. Damit uns bei der weiteren Verarbeitung vertiefte Möglichkeiten zur Verfügung stehen, müssen wir diese Daten in den korrekten Datentyp umwandeln. Erst mit den richtigen Datentypen ist es möglich, mathematische Formeln zu nutzen und Daten beispielsweise zu filtern, zu sortieren oder anderweitige Funktionen und Algorithmen anzuwenden.

Wandeln wir diese nun also um:

js
let data = { "number": "1", "title": "So gelingt digitale Transformation: Experten Tipps eines Software Engineers", "author": "Roman Wünsche", "date": "04.11.2023" } const dateParts = data.date.split('.') const dateFormatted = dateParts[2] + '-' + dateParts[1] + '-' + dateParts[0] data.number = new Number(data.number) data.date = new Date(dateFormatted)

Das Ergebnis:

json
{ "number": 1, "title": "So gelingt digitale Transformation: Experten Tipps eines Software Engineers", "author": "Roman Wünsche", "date": "2023-11-04T00:00:00.000Z" }

Auf den ersten Blick hat sich nicht viel getan. Für die Software allerdings schon. Die Nummer ist nun ein Integer und das Datum ein String im UTC-Datumsformat. Hiermit können wir mathematischen Formeln nutzen um mit den Daten zu arbeiten. Einer möglicher Use-Case wäre beispielsweise die Filterung nach Datum: article.date >= '2023-11-01' && article.date <= '2023-11-10'.

Die strukturierten, bereinigten und normalisierten Daten können nun in einer Datenbank gespeichert und unseren Umsystemen zur Verfügung gestellt werden.

Schritt 4: Bereitstellen der Daten

Sind die Daten einmal digital verfügbar, müssen wir diese den Umsystemen bereitstellen. Hierzu eigenen sich APIs (Application Programming Interface).

Eine API regelt die Kommunikation zwischen unterschiedlichen Systemen. Ähnlich wie wir Menschen uns zwischen den Kulturen auf eine Sprache zur Kommunikation einigen, so können wir mittels APIs regeln, wie Systeme sich austauschen. Eine API definiert dabei, wie und in welchem Format Daten erstellt, abgerufen, manipuliert oder gelöscht werden können.

Dabei gibt es gute und schlechte APIs. Gute APIs halten sich an Standards, womit Sie sich gut in andere Systeme integrieren lassen. Sehr gute APIs reichern die Daten zudem um weitere Metadaten an, womit Filterung, Paginierung und die Verlinkung vereinfacht und sicher vor Veränderungen gemacht wird.

Im nächsten Teil dieser Artikelserie, zeige ich dir an einem praktischen Beispiel, wie eine API im Detail funktioniert und was man hierbei beachten sollte.

Problemfall: Legacy-Systeme

Oftmals liegen die Daten bereits in einem veralteten System in digitaler Form vor. Doch es fehlt eine Anbindungsmöglichkeit wie eine API. Hier gilt es zu klären, ob man das Legacy-System auf eine neuere Version upgraden oder auf ein anderes System migrieren kann, welches eine modernere Anbindungsmöglichkeit anbietet. Falls nicht, kann eine Middleware weiterhelfen.

Eine Middleware ist ein Stück Software das zwischen der Alten Lösung und der neuen Umgebung läuft. Innerhalb dieser Software wird die bestehende Datenquelle direkt angebunden, die Daten ausgelesen und den anderen Systemen angeboten oder in diese überführt.

Hierdurch kannst du deine Legacy-Anwendung weiterhin nutzen, ohne gleich alles migrieren zu müssen. Der Aufwand ist nicht zu unterschätzen - oftmals muss viel Reverse-Engineering betrieben werden. Alte Systeme sind zudem nicht auf dem Sicherheitsstandard, welcher heute verlangt und benötigt wird. Dies führt oft zu technischen Schulden, welche Innovation bremsen oder gar verhindern können.

Schritt 5: Bereitstellen der APIs

Ist die API bereit, muss diese den Umsystemen zur Verfügung gestellt werden.

Ich empfehle immer, Software als Container bereitzustellen. Einen Container kannst du dir wie eine Zip-Datei vorstellen, in welcher sämtliche Dinge enthalten sind, die zum Ausführen der Software benötigt werden. Du kannst somit sicher sein, dass die Software sich auf der Produktion genau gleich verhält, wie zuvor bei der Entwicklung. Daneben ist ein Container portierbar: Reicht das System nicht mehr aus, kann in wenigen Minuten auf ein Anderes gewechselt werden. Es gibt noch unzählige weitere Vorteile, weshalb die Containerisierung heute essenziell ist. In einem Folgebeitrag wirst du bald mehr dazu erfahren.

Ist die API einmal als Container paketiert, wird diese auf eine Container-Registry hochgeladen und mittels Orchestrator (bspw. Kubernetes) auf einem Server mit Container-Runtime bereitgestellt und ausgeführt. Dieser Prozess kann man mittels DevOps-Prinzipien automatisieren und den Betrieb über die Cloud abhandeln.

Letzteres ist natürlich kein Muss. Insbesondere im Hinblick auf Datenhoheit und Sicherheit muss man Ganz genau hinschauen. Man kann Container auch klassisch auf einem eigenen Server im eigenen Netzwerk betreiben. Wenn du aber dutzende von Anwendungen hast, wirst du feststellen, dass du einiges an zusätzlicher Infrastruktur benötigen wirst, um diese zu betreiben und die Datenintegrität sicherzustellen.

Profi-Tipps

Nun hast du bereits einiges gehört, wie man Daten digitalisiert und bereitstellt. Die digitale Transformation hat aber noch einige Stolpersteine zu bieten. Insbesondere wenn du deine Daten in all deinen Abläufen nutzen willst, wirst du diesen irgendwann in verschiedenen Systemen haben wollen. Auch wird das Thema "Verfügbarkeit" plötzlich sehr wichtig.

Datenintegrität sicherstellen

Hast du die gleichen Daten an mehreren Orten verteilt vorliegen, musst du dir Gedanken über die Datenintegrität machen. Die Informatik kennt hier zwei Konzepte:

  • Replizierung: Bei der Replizierung hast du ein Master-System als "Source-of-Truth". Nur dort werden die Daten gepflegt und die Änderung in die Umsysteme gepusht. Alle Daten in den Umsystemen werden dabei durch den Master überschieben. Der Datenaustausch ist hierbei unidirektional, d.h. nur in eine Richtung von Master zu Child.
  • Synchronisierung: Bei der Synchronisierung werden die Daten bidirektional zwischen den Systemen ausgetauscht. Es gibt somit kein klares Master-System. Hierbei sind Daten-Konflikte vorprogrammiert. Um das Risiko von inkonsistenten Daten zu minimieren, erfolgt der Austausch immer sehr zeitnah oder gar in Echtzeit. Dennoch braucht es hier eine Strategie zur Bewältigung dieser Konflikte.

Für beide Strategien brauchst du Software. Es ist daher naheliegend, dies insbesondere bei Eigenentwicklungen bereits bei der Planung zu berücksichtigen. Um Anwendungen zu synchronisieren, nutzt man heute Webhooks und/oder Events.

Hast du nun beispielsweise eine API geschrieben, kannst du auf alle modifizierenden Aktionen (POST, UPDATE, PATCH oder DELETE bei einer REST-API) reagieren und das geänderte Datenobjekt weitergeben. In einem zukünftigen Artikel über APIs, werde ich dir aufzeigen, wie du das sehr elegant in einer Middleware-Pipeline mittels Laminas/Mezzio abhandelst.

Skalierung

Irgendwann kommt der Punkt, wo dein Unternehmen noch grösser geworden ist. Die einzelnen Systeme sind am Anschlag und können mit der gestiegenen Nachfrage nicht mehr zeitnah umgehen. Auch hier kennt die Informatik zwei Grundkonzepte:

  • Systeme aufrüsten (sprich: vertikal zu skalieren)
  • Systeme mehrfach betreiben (sprich: horizontal zu skalieren)

Vertikale Skalierung bringt nicht immer den gewünschten Erfolg und hat seine Grenzen. Insbesondere dann, wenn der Flaschenhals nicht die Leistung des Systems, sondern die Software selbst ist.

Heute werden Anwendungen daher oft nach Themengebiet aufgebaut. Der Sinn dahinter ist einfach erklärt: Statt alles in eine grosse Anwendung (Monolith) zu packen, werden diese in Einzelteile (Microservices) aufgeteilt und separat betrieben. Diejenigen Komponenten, die an den Anschlag geraten, können so mehrfach betrieben werden.

Sobald Workloads horizontal skaliert betrieben werden, müssen weitere Dinge beachtet werden. Microservices sollten zustandslos sein und untereinander asynchron kommunizieren. Und damit wir nicht plötzlich Duplikate im System haben, sollten die Aktionen idempotent sei, d.h. ein mehrmaliges Ausführen liefert das gleiche Ergebnis zurück und führt nicht zu einer doppelten Transaktion. Eine Microservice-Architektur nutzt dazu das Konzept von Events. Man redet auch von einer event-basierten Architektur (Event-driven Architecture).

Für die wenigsten Firmen lohnt es sich, alles auf Microservices umzustellen. Denn die Komplexität steigt enorm, da nun diverse weitere Systeme benötigt werden, welche obiges Verhalten sicherstellt. Dennoch kann es sinnig sein, gewisse Anwendungen aufzutrennen. Die eine Architektur schliesst die andere nicht aus. In einem Folgeartikel werde ich dir beide Architekturen näher bringen und dir die Vor- und Nachteile genauer aufzeigen.

Fazit

Dieser Artikel hat dir hoffentlich einen Einblick und einige praktische Tipps für die digitale Transformation aufgezeigt. Mit dem richtigen Plan und den richtigen Technologien ist es heute einfacher denn je. Und dank zahlreichen Software-Bibliotheken, Tools und der Cloud kann sich das heute auch ein KMU leisten.

Falls du mehr erfahren willst, bist du herzlich eingeladen in einigen Wochen wieder hereinzuschauen. Dann zeige ich dir praktische Tipps rund um die Themen APIs, Container, Microservices und die Cloud.

Avatar

Geschrieben von Roman Wünsche

Senior Software Engineer, Full Stack Web Developer, Solution- und Software-Architect mit einem Flair für DevOps und die Cloud.

Seit über 20 Jahren entwickle ich Software in der Schweiz nahe Zürich und begleite meine Kunden bei der Konzeption, Umsetzung und Vermarktung digitaler Lösungen im Web und der Cloud.

Ich liebe es, einfach zu bedienende Anwendungen zu bauen, welche echten Nutzen generiert - Landingpages, SPAs, Webseiten mit kombiniertem oder separiertem Front- und Backend, APIs oder auch ganze Architekturen mittels vernetzten, event-basierten und interoperablen Microservices als Container in der Cloud - jedes Projekt hat seinen individuellen Reiz.