Working from home has many advantages but also numerous risks
During the global pandemic in 2020 the German government has decided to restrict social contacts as much as possible. Companies increasingly allowed their employees to work from home.
According to the statista website, only 4% of all those surveyed have been working from home before 2020. This value increased to 27% during the first lockdown in April 2020, which is almost a quarter of all respondents who worked exclusively or mainly from home. The value fell over the year but increased to 24% in January 2021. This shows a clear trend towards more people working from home.
(statista 2021)
This blogpost pursues two central questions:
What factors influence performance, commitment and job-satisfaction of employees working from home
What are the risks for employers and how can these risks be reduced?
The magazine “Spiegel” published an article with the headline “Homeoffice mit drei Kindern Zu Hause im Versuchslabor” (Der Spiegel 2020). This article clearly shows the challenge of balancing work and childcare. A challenge that many people had to overcome during last year. But what are the advantages, and what are the disadvantages of working from home?
Not every job is suitable for remote work. A surgeon can hardly operate on his patients at home. Also a baker can not sell his rolls to his customers at home. A software developer, on the other hand, can easily program his application at home or anywhere else in the world. Industries that are most suitable for working at home include jobs in the IT industry, marketing, services such as travel agencies, and jobs in the service sector such as call centres. But also areas of public administration, such as the citizens’ office, increasingly worked from home last year. As schools were closed, teachers also had to restructure their teaching and offered online classes or provided teaching material while the students had to work independently from home.
In unserem Leben, egal ob im Privaten oder Beruf, müssen wir Entscheidungen treffen. Diese Entscheidungen haben so gut wie immer eine Konsequenz. Bei alltäglichen Entscheidungen ist uns das oft nicht bewusst. Erst bei großen und schweren Entscheidungen sind wir Menschen uns darüber im Klaren, dass das was wir vorhaben zu tun unser Leben in Zukunft beeinflussen wird. Wir erwarten häufig von uns selbst Entscheidungen schnell zu treffen, da wir uns nur selbst als nützlich erachten, wenn wir etwas tun. Daher kommt es, dass wir uns oft nicht die Zeit nehmen über Entscheidungen nachzudenken und herauszufinden was gerade wirklich passiert. Wir fokussieren uns darauf so schnell wie möglich weiterzukommen und verlieren das große Ganze – the Big Picture – aus den Augen, in welchem sich alle unserer Entscheidungen und unser Handeln zusammenfinden.
Die Welt, in der wir leben ist immer mehr vernetzt und durch die wachsende Globalisierung wächst auch die Komplexität sozialer Systeme. Der internationale Handel zum Beispiel verknüpft Nationen auf der ganzen Welt zu einem mächtigen wirtschaftlichen Feedbackloop. Was genau ein solcher Feedbackloop ist werden wir später noch genauer betrachten. Einzelne Systeme (falls diese überhaupt je getrennt voneinander funktioniert haben) wachsen und kommen immer näher zusammen. Verwachsen einige dieser Systeme miteinander, erzeuget dies komplexe und unvorhersagbare Effekte. Es ist also kaum noch möglich, einen Überblick über das gesamte System zu haben. Aber dieser Tatsache sind wir uns nicht immer bewusst. Je nachdem welche Perspektive wir hierbei einnehmen, bekommen wir ganz unterschiedliche Eindrücke wie die Realität aussieht. Hier passt das bekanntes Gleichnis „Die blinden Männer und der Elefant“ sehr gut.
In dieser Erzählung untersuchen fünf Blinde, die noch nie zuvor einem Elefanten begegnet sind, einen echten Elefanten mit ihren Händen. Sie sollen dadurch einen Eindruck bekommen, was ein Elefant ist. Jeder von ihnen steht an einer anderen Stelle und betastet so eine andere Stelle des Elefanten. Einer untersucht den Rüssel, einer ein Ohr usw.. Am Ende sprechen sie darüber wie ein Elefant aussieht und fangen heftig an zu streiten, weil jeder sein Bild für richtig hält, aber alle völlig unterschiedlich sind. Schließlich kommt der Elefantenführer dazu und sagt ihnen, dass sie alle richtig und alle falsch liegen, denn jeder von ihnen kennt nur einen Teil des wirklichen Elefanten. Wenn sie all ihre Erfahrungen zusammennehmen, dann würden sie einen Eindruck bekommen, wie der tatsächliche Elefant aussieht. Jeder von ihnen ist also aufgrund seiner individuellen Erfahrung zu einer eigenen, unvollständigen, aber logischen Schlussfolgerung gekommen.
Genau mit diesen Problemen – der Komplexität von Systemen, dem Hang überstürzte Entscheidungen zu treffen und die Realität nur aus einer Perspektive zu betrachten – befasst sich System Thinking.
Was ist System Thinking?
Beim System Denken wird davon ausgegangen, dass sich all unsere Handlungen und Entscheidungen mehr oder weniger in Verbindung zueinanderstehen und voneinander abhängig sind. System Thinking soll Menschen und auch Organisationen, wie Teams, Abteilungen oder Firmen dabei helfen, die Konsequenzen ihres Handelns besser zu verstehen und sich an die Umwelt, in welcher wir uns befinden anzupassen. System Thinking ist ein Skillset, um die Komplexität des Verhaltens besser vorherzubestimmen und zu verstehen und letzten Endes auch den Ausgang anzupassen. System Thinking bietet uns Menschen eine Möglichkeit die Realität zu sehen so wie sie ist und über diese zu Sprechen.
Bevor wir uns genauer damit beschäftigen und dieses Skillset genauer betrachten, wie man tatsächlich im System denkt, werden wir uns erst noch genauer mit dem Begriff System Thinking auseinandersetzen und diesen genauer einordnen. Außerdem wollen wir uns noch genauer mit den psychologischen Aspekten befassen, die die Denkweise des Menschen beeinflussen und was hierbei besonders wichtig wird, wenn wir im System denken wollen. Zu guter Letzt werden noch einige methodische Ansätze kurz erläutert, um ein paar praktische Methoden des System Thinkings mit auf den Weg zu geben.
Sind wir nur schick angezogene Höhlenmenschen?
Versetzen wir uns in folgende Situation: Bei einem Projekt laufen wir in ein Problem. Wir können nicht weitermachen, weil weitere Arbeitsschritte von dem Problem abhängig sind. Was tust du? Findest du schnell eine Lösung, um das Problem zu lösen oder nimmst du dir die Zeit, um die Ursache des Problems zu finden?
Die meisten Menschen würden hierbei wahrscheinlich antworten, dass sie sich die Zeit nehmen würden, die verschiedenen Möglichkeiten für die Ursache des Problems abzuwägen, und dann nach dem sie alle Pros und Cons für die unterschiedlichen Lösungen verglichen haben, treffen sie eine rationale Entscheidung.
Dieses rationale Entscheidungsmuster wird von uns Menschen jedoch gar nicht so oft genutzt, wie wir uns das gerne einreden. Oft verlassen wir uns bei der Lösung komplexer Probleme auf unsere sogenannte Intuition und treffen eine emotionsgetriebene Entscheidung. Der rational denkende Mensch, das was uns vom Tier unterscheidet, ist vielmehr ein Bild, welches wir Menschen gerne von uns selbst haben, aber meist nicht immer der Realität entspricht.
Der Grund dafür liegt aber schon Jahrtausende zurück. Und zwar tragen wir Menschen immer noch unser evolutionäres Erbe von vor 10 000 Jahren mit uns herum. Denn seit her hat sich bei der Entwicklung unseres Gehirns nicht mehr viel getan. Unsere Umwelt hat sich hingegen in den letzten 10 000 Jahren rapide geändert. War es bei unseren Vorfahren vor 20 Generationen noch wichtig im Bruchteil einer Sekunde über Leben oder Tod zu entscheiden, weil hinter jedem Baum ein Raubtier lauern konnte, welches einen fressen wollte, leben wir heutzutage in einer vollkommen industrialisierten und digitalisierten Welt.
Die Welt, in der wir aktuell leben ist so komplex, dass emotional Entscheidungen oft nicht zielführend sind. In einer so vernetzen Welt ist es wichtig, sich erst ein Bild und Überblick über dieses Komplexe zu verschaffen und das direkte Tun und Handeln einen Moment zurückzustellen und stattdessen zu denken. Und genau hier kommt System Thinking ins Spiel.
Das Seerosen-Modell
Es steckt oft mehr dahinter als das, was wir im ersten Moment sehen. Beim System Thinking geht es darum unter die Oberfläche zu blicken oder wie man gerne sagt über den Tellerrand hinauszuschauen. Es geht darum die Muster in unserem Alltag oder bei der Arbeit zu erkennen und Situationen besser einzuschätzen und zu bewältigen.
Bei der Recherche für diesen Artikel sind wir immer wieder auf die Metapher des Seerosenteichs gestoßen, um den Grundgedanken des System Thinkings zu veranschaulichen. So ist bei einer Seerose der größte Teil verborgen und liegt unter der Wasseroberfläche. Unsere Aufmerksamkeit gilt auf den ersten Blick aber nur den wunderschönen Blüten und Blättern der Seerose. Diese wunderschöne Blüte kann jedoch nur existieren und wachsen, weil sie durch ein enormes Wurzelsystem mit Nährstoffen aus dem Wasser und dem Boden versorgt wird. Es bringt also nichts nur die Seerosen an der Oberfläche zu betrachten und diese zu pflegen. Um einen gedeihenden Seerosenteich zu haben, reicht es nicht nur die verwelkten Blüten und Blätter zu stutzen. Wir müssen auch unter die Wasseroberfläche schauen und an der Wurzel arbeiten, denn nur dann kann die Seerose weiterwachsen. Wenn wir nun unsere Welt mit einer Seerose gleichsetzen, bedeutet das, dass wenn wir bei einem System strukturelle Änderungen vornehmen und die Wurzel des Problems anpacken wollen, um nicht nur Symptome zu behandeln, sondern die Ursache, wir tiefer schauen und einen Blick unter die Oberfläche wagen müssen. Je tiefer wir also in den Teich hinabschauen, desto effektiver sind unsere Maßnahmen.
Nachdem wir das Seerosen-Modell nun im Kontext des System Thinking betrachtet haben, lässt sich sagen, dass es beim System Thinking in erster Linie darum geht das große Ganze – the Big Picture – zu betrachten.
Wo sind die Ursprünge des System Thinking? Was sind die Grundannahmen?
Die Ursprünge des System Thinking liegen in der System Theorie. Die Wurzeln finden sich in so unterschiedlichen Disziplinen wie Biologie, Kybernetik und Ökologie. Systemdenken bietet einen Einblick in die Funktionsweise der Welt, die sich deutlich von der traditionellen reduktionistischen, analytischen Sicht unterscheidet. Kognitive Prozesse des Erkennens und Problemlösens, die auf Konzepte der Systemtheorie Bezug nehmen, werden oft unter dem Begriff System Thinking oder Systemdenken zusammengefasst.
Wie bereits erwähnt leben wir in einer immer komplexer werdenden Welt. Um in dieser Welt vernünftig zu überstehen, fordern Experten, welche sich mit System Thinking befassen, mehr Systemdenker. Menschen mit solch einem Skillset werden nicht nur in wissenschaftlichen oder Disziplinen oder dem Ingenieurwesen benötigt, sondern in allen Bereichen unseres Lebens. Entscheidungen am anderen Ende der Welt, wie zum Beispiel die Rodung des Regenwaldes haben Auswirkungen auf den gesamten Globus. Auf Grundlage dieser Überlegung könnte man gar argumentieren, dass alle Menschen in Entscheidungspositionen ein solides Verständnis für das System Thinking haben sollten.
Wenn nun System Thinking das Allheilmittel für die Probleme dieser Welt sind, was ist es überhaupt genau? Hierauf gibt es keine eindeutige Antwort.
In der Literatur gibt es eine Reihe verschiedener Definition für den Begriff des System Thinking, jedoch unterscheiden sich diese oftmals und es gibt keine eindeutige allgemeingültige Definition. Das Problem bei der Begrifflichkeit ist, bzw. was sie so schwer macht zu definieren, dass dieser Begriff schon so oft definiert und redefiniert wurde. Wenn man die verschiedenen Definitionen und Erklärungen betrachtet, weißen sie dennoch eine Vielzahl an Gemeinsamkeiten auf. Diese wollen wir im Folgenden genauer betrachten und damit den Oberbegriff, um den es in diesem Blogbeitrag geht eingrenzen.
Prägend für das System Thinking an sich ist der Begriff System für sich selbst. Schon das Wort System hat je nach dem in welchem Kontext und welcher Disziplin es verwendet wird unterschiedliche Bedeutungen. In dem Fall des System Thinking macht die naturwissenschaftliche Definition wohl am meisten Sinn. So ist ein System laut Duden in einem naturwissenschaftlichen Kontext eine „Gesamtheit von Objekten, die sich in einem ganzheitlichen Zusammenhang befinden und durch die Wechselbeziehungen untereinander gegenüber ihrer Umgebung abzugrenzen sind“. Ein Grundprinzip eines Systems ist also, dass es mehr ist als eine bloße Ansammlung seiner Teile. Dies können wir auch für das System Thinking annehmen. So finden sich einige Grundannahmen, die für das bloße System gelten auch beim System Thinking wieder. Wenn wir System Thinking genau betrachten, besteht es in erster Linie zunächst einmal aus drei Dingen. Den einzelnen Elementen, die Beziehung der einzelnen Elemente zueinander und dem Zweck oder auch dem Ziel. Aus diesen Grundannahmen lassen sich wiederum Charakteristiken für ein System ableiten.
Charakteristik von Systemen
Zweck: Systeme haben immer einen Zweck. Der Zweck oder auch das Ziel eines Systems ist eine Eigenschaft des Systems als Ganzes und nicht eines der Elemente. So ist das System Flugzeug in seiner Gesamtheit dafür verantwortlich Passagiere von A nach B zu fliegen. Dieser Zweck ist eine Eigenschaft des gesamten Systems und nicht das einer einzelnen Turbine oder eines Flügels und wird erst durch das Zusammenspiel der einzelnen Flugzeugteile erreicht.
Gesamtheit: Es müssen alle Teile vorhanden sein, damit ein System seinen Zweck optimal erfüllen kann. Wenn wir einem System ein Element wegnehmen oder auch hinzufügen können, ohne dass es die Funktion des Systems beeinflusst, dann haben wir kein System, sondern eine bloße Ansammlung von Elementen, die nicht in Abhängigkeit zueinanderstehen. Wenn wir zum Beispiel aus einem Werkzeugkasten ein Werkzeug herausnehmen, bleibt die Funktion des Kastens erhalten. Wir haben lediglich den Inhalt geändert.
Reihenfolge: Die Reihenfolge, in der die Elemente unseres Systems angeordnet sind, beeinflussen dessen Leistung. Wenn wir die Elemente beliebig anordnen können, dann ist es kein System. So spielt es bei unserem Werkzeugkasten keine Rolle, ob der Schraubenzieher über oder unter dem Hammer liegt. Bei unserem Flugzeug hingegen ist die richtige Anordnung der einzelnen Elemente für einen sicheren Flug überlebenswichtig. Daraus können wir schließen, dass die Anordnung der einzelnen Elemente in einem System sehr wichtig ist.
Feedback: Beim Feedback oder auch zu Deutsch der Rückkopplung werden Informationen übermittelt und zurückgegeben. Das wichtigste Merkmal des Feedbacks ist, dass es Informationen an das System liefert, die es wissen lassen, wie es sich in Bezug auf einen bestimmten Zustand verhält.
Dies sind wichtige Charakteristika, die für die Definition eine prägende Rolle spielen.
So definiert Barry Richmond, System Thinking als die Kunst und Wissenschaft, zuverlässige Rückschlüsse auf das Verhalten zu ziehen, indem man ein immer tieferes Verständnis der zugrunde liegenden Struktur entwickelt. Er betont, dass Menschen, die Systemdenken praktizieren, sich so positionieren, dass sie sowohl den Wald als auch die Bäume sehen können.
Auf Richmonds Definition berufen sich die meisten anderen Definitionen, jedoch werden diese noch erweitert.
Eine Definition, welche sich aus der Auswertung umfassender Literatur ergab, ist die von Megan Hopper und Krystyna Stave. Hopper und Syave bekräftigen die Notwendigkeit einer allgemein akzeptierten Definition. Sie warnen auch davor, dass der Begriff System Thinking auf verschiedene und manchmal auch widersprüchliche Weise verwendet wird, was bei der Findung für eine allgemeingültige Definition nicht gerade hilfreich ist.
Aus der Arbeit von Hopper und Stave ergeben sich folgende Grundannahmen für das System Thinking, welche auch die bereits erwähnten Charakteristiken von Systemen ergänzen:
Erkennen von Zusammenhängen
Erkennen von Rückkopplungen
Dynamisches Verhalten verstehen
Unterscheidung der Arten von Flüssen und Variablen
Konzeptuelle Modelle verwenden
Erstellen von Simulationsmodellen
Erprobung von Politiken
Was alle Definitionen berücksichtigen und worunter sich die meisten einig sind ist, dass Elemente und die Charakteristiken, die ein System ausmachen, die Zusammenhänge, das Verständnis von dynamischen Verhalten, die Systemstrukturen als Ursache für dieses Verhalten und die Idee, Systeme als Ganzes und nicht als Teile zu betrachten, sind.
Einblick in unsere Psyche
Jetzt haben wir einen Eindruck was unter System Thinking eigentlich zu verstehen ist. Bevor wir nun mit den Methoden des System Thinking beschäftigen, sollten wir nochmal einen Schritt zurücktreten und uns anschauen, wie das menschliche Denken überhaupt funktioniert. Wie fällen wir Urteile und kommen zu Entscheidungen? Zuerst einmal müssen wir uns von dem Gedanken verabschieden, dass wir in der Lage sind rein objektive Entscheidungen aufgrund der Kenntnis aller relevanter Fakten zu treffen. Der Mensch ist weder in der Lage völlig objektiv zu sein noch die Wirklichkeit zu 100% exakt zu erfassen.
Wir konstruieren uns unsere Wirklichkeit
Unser Gehirn ist ein Meister darin Lücken zu schließen, um ein vollständiges Bild zu formen. Ohne dass wir bewusst etwas davon mitbekommen, ergänzt unser Gehirn fehlende Informationen oder übergeht Unpassende (zumindest bis zu einem gewissen Grad). Und diese Eigenschaft ist essenziell wichtig, damit wir uns in der Welt überhaupt orientieren können.
Unsere Wahrnehmung ist durch mehrere Faktoren beschränkt. Zum einen sind unsere Sinnesorgane nicht in der Lage alle möglichen Informationen auch aufzunehmen. Beispielsweise können Licht nur in im Spektrum zwischen 380 nm und etwa 780 nm wahrnehmen. Ein anderer Faktor ist die beschränkte Verarbeitungskapazität unseres Gehirns. Pro Sekunde sind wir in der Lage 15.000.000 Bits an Daten über unsere Sinnesorgane wahrzunehmen. Von all diesen Informationen können wir aber nur ca. 0,0004% bewusst verarbeiten. Unser Gehirn hat sich also im Laufe der Evolution so entwickelt, dass es sich auf ein Minimum der notwendigen Informationen beschränkt und den Rest ergänzt. Auf diese Weise konstruiert das Gehirn ein Abbild unserer Realität. Dieses Konstrukt hat Einfluss darauf, was wir fühlen und wie wir handeln.
Neben den biologischen Faktoren wird die Wahrnehmung auch von psychologischen und soziokulturellen Faktoren beeinflusst. Das bedeutet, dass unsere aktuelle Stimmung, unsere Erwartungen und Erfahrungen mitbeeinflussen was wir wahrnehmen und wie wir es verarbeiten. Somit ist der Wahrnehmungsprozess keine reine Abbildung der physiologischen Realität, sondern vielmehr eine Konstruktion der individuellen Wirklichkeit. Das unser Gehirn auf diese Weise alle Informationen zusammenfügt, sorgt dafür, dass wir uns relativ problemlos in der Welt orientieren und in ihr agieren können.
Wir sind in der Lage innerhalb von Sekundenbruchteilen eine Situation einzuschätzen, indem die gesammelten Informationen in unser mentales Model – unseren Bezugsrahmen – gesetzt werden und fehlende Informationen ergänzt werden. Welche Teile des Gesamtbildes in unserem Kopf nun aber auch tatsächlich wahrgenommenen Reizen beruhen und welche ergänzt wurden, ist für uns nicht mehr nachvollziehbar. Das ist mitunter einer der Gründe warum Augenzeugenberichte sich teilweise stark voneinander unterscheiden können. Je nachdem was die Zeugen für Vorerfahrungen hatten und wo ihre Aufmerksamkeit in dem Moment lag unterscheiden sich die Bilder, welche sie von der Situation im Gedächtnis behalten.
Diese Funktionsweise unseres Gehirns hat sich über viele Jahre entwickelt und unseren Vorfahren das Überleben gesichert. Das Problem ist aber, dass sich unsere Umwelt seitdem dramatisch verändert hat. Unsere heutige Umwelt ist deutlich komplexer und erfordert viel mehr Vorausdenken, um Veränderungen zu antizipieren.
Denken wir immer gleich?
In der modernen Psychologie wird davon ausgegangen, dass wir zwei voneinander abhängige Systeme des Denkens haben. Ein System (System 1) für das unbewusste, automatische und schnelle Denken und ein System (System 2) für das bewusste und langsame Denken. Welches System gerade aktiv ist, ist uns oft gar nicht bewusst. Doch in den meisten Fällen ist System 1 aktiv. Die Aktivitäten von System 1 geschehen automatisch und nahezu mühelos, während System 2 Aufmerksamkeit und mehr kognitive Ressourcen erfordert.
In den meisten alltäglichen Situationen ist der Hauptakteur System 1, da dieses deutlich weniger mentale Ressourcen benötigt und viel schneller ist. In den meisten Situationen ist System 1 auch völlig ausreichend beziehungsweise notwendig. Wir wären kaum lebensfähig, wenn wir über jeden Schritt, jeden Atemzug und jede unserer Handlungen bewusst nachdenken müssten. System 1 geht dabei nach dem What you see is all there is (WATASI) Prinzip vor und ist auch in der Lage Informationen parallel zu verarbeiten. Es geht davon aus, dass wir alle notwendigen Informationen besitzen, um die richtige Entscheidung zu treffen. Unser Gehirn ignoriert in diesem Fall, dass es Informationen gibt, auf die es keinen Zugriff hat. System 1 ist auch völlig unempfindlich gegenüber Qualität und Quantität von Informationen. Das oberste Ziel ist es ein konsistentes Gesamtbild aus den vorhandenen Informationen zu schaffen, um handlungsfähig zu bleiben. Das ist auch der Grund warum wir dazu neigen überall kausale Zusammenhänge herzustellen und bereits aus einem Minimum an Informationen einen Kontext abzuleiten. System 1 beurteilt alle Ereignisse danach, ob sie in unser mentales Muster passen. Da wir unbewusst danach streben, ein möglichst konsistentes Gesamtbild zu erhalten, akzeptieren wir oftmals auch wenig stichhaltige Argumente, solange diese in unser mentales Modell passen.
Wollen wir nun im Zuge des System Thinking das Gesamtsystem versuchen zu erfassen und das im Bewusstsein, dass wir niemals alle Informationen besitzen, müssen wir aktiv das System 2 nutzen. System 2 ist für das bewusste Denken und unsere Selbstbeherrschung zuständig. Dieses Denksystem ist in der Lage zu zweifeln und Dinge zu überdenken, indem wir bewusst nach neuen Informationen suchen oder die gegebenen Informationen neu strukturieren. Es ist das Kontrollsystem, welches die Aktivitäten von System 1 überwacht und dann aktiv wird, wenn System 1 an seine Grenzen stößt. Bei der Lösung komplexer Denkaufgaben greifen wir auf dieses System zu. Allerdings schöpft dieses System auch deutlich stärker unsere mentale Arbeitskraft aus, was dazu führt, dass wir schneller ermüden. System 2 kann sich auch nur auf eine Aufgabe konzentrieren es arbeitet Informationen sequentiell ab. Das heißt, wenn wir mental gerade sehr mit einer Aufgabe beschäftigt sind, werden wir in allen anderen Bereichen leichtgläubig, da System 1 keine Zweifel kennt und System 2 beschäftigt ist.
System 2 wird also nur in bestimmten Situationen und für eine bestimmte Zeit lang aktiv. Es akzeptiert auch eine gewisse Fehleranfälligkeit von System 1. Der Grund ist, dass voreilige Schlussfolgerungen dann effizient sind, wenn sie mit hoher Wahrscheinlichkeit zutreffen, wenn die Kosten eines gelegentlichen Fehlers akzeptabel sind und wenn dadurch Mühe und Zeit gespart werden können. Dieses Vorgehen hat uns im Laufe unserer Evolution vor dem Aussterben bewahrt. Wir mussten oft innerhalb von Sekunden auf Basis der aktuell vorhandenen Informationen entscheiden, ob wir fliehen oder kämpfen sollten.
Das System Thinking hingegen erfordert, dass wir uns ganz bewusst mit allen Möglichkeiten auseinandersetzen und damit gezielt das System 2 nutzen ohne dass wir den Vereinfachungen von System 1 zu sehr vertrauen. Dies erfordert ein hohes Maß an Selbstbeherrschung und bewusstem Denken. Aber allein das Bewusstsein, über die beiden Systeme und ihre Funktionsweise kann dabei hilfreich sein, das eigene mentale Modell häufiger infrage zu stellen, um Unstimmigkeiten aufzudecken.
Wie lösen wir eigentlich Probleme?
Nachdem wir uns jetzt mit den beiden Systemen beschäftigt haben, ist die nächste Frage: Wie lösen wir eigentlich Probleme und was macht ein Problem für uns kompliziert? Und was ist für uns überhaupt ein Problem?
Ein Problem entsteht dann, wenn man in irgendeiner Form ein Ziel hat und dieses erreichen will, aber dabei auf ein oder mehrere Hindernisse stößt. Wenn wir für die Überwindung dieser Hindernisse keine Routine verfügbar haben, haben wir ein Problem. Das problemlösende Denken ist eine der Fähigkeiten, welche uns gegenüber vielen anderen Spezies besonders auszeichnet. Problemlösendes Denken erfolgt immer zu dem Zweck, ein oder mehrere Handlungsziele zu erreichen. Dabei bedarf es zielgerichteter Entscheidungen und weiterer Komponenten wie z.B. Problemidentifikation, strategisches Planen, Reflexion und Abstraktion.
Auch wir als Informatiker werden oft mit dem Thema Problemlösen konfrontiert.
Wie kann ich den Wunsch meines Kunden am besten umsetzten? Wie setzte ich es überhaupt um? Warum funktioniert das schon wieder nicht? Warum habe ich plötzlich mehr Fehlermeldungen als vorher?
Egal welche der Fragen wir lösen müssen eins haben alle gemeinsam. Idealerweise sollten wir zuerst das zugrundeliegende Problem identifizieren, bevor wir es lösen können. Klingt logisch, ist aber in der Praxis oft ein Problem für sich. Wir neigen gerade bei komplexen Problemen dazu lieber eine schnelle sofort verfügbare Lösung zu probieren, als erst mal zu warten und das Problem in seinem gesamten Umfang zu erfassen. Vor allem wenn wir unter Druck stehen, nehmen wir öfter mal die erstbeste Lösung, ohne sie richtig zu prüfen.
Aber: „There is no use of running, if you’re on the wrong road.”
Oftmals liegt dem Offensichtlichen ein größeres komplexeres Problem zugrunde, welches tiefer im System verankert ist. Um eine Lösung zu finden, die das Problem wirklich langfristig und vollständig löst, ist es notwendig das gesamte System oder zumindest einen deutlich größeren Kontext im System zu betrachten. Wie umfangreich die Veränderungen dann sein müssen, um das Problem zu beheben, kann dann wieder ganz unterschiedlich sein. In Bezug auf Software bedeutet das, dass die Lösung, die der Kunde sich wünscht, nicht immer die ist, die er braucht.
Bei der Erfassung eines Problems bekommen wir es wieder mit einigen Fallstricken unseres Denkens zu tun. Denn wir überschätzen systematisch unser eigenes Wissen und Fokussieren und eher auf das was wir wissen und ignorieren das wir etwas nicht wissen. Es ist leichter davon auszugehen, dass man alle relevanten Informationen zur Lösung eines Problems schon hat, als zu überlegen was man nicht weiß, was aber wichtig sein könnte. Haben wir dann eine These, welche für uns schlüssig ist, gebildet, tendieren wir dazu vor allem den Fakten Beachtung zu schenken, die diese These stützen. Wir verbiegen ganz unbewusst die hinzukommenden Informationen so, dass sie möglichst nicht mit unserer gefassten Meinung kollidieren. Also aufpassen, wenn eine Lösung zu leicht erscheint und alles wunderbar zu passen scheint. Lieber noch einmal bewusst kritisch auf die Lösung schauen.
Aber um ein Problem lösen zu können, sollten wir auch anschauen, unter welchen Umständen ein Problem für uns komplex erscheint.
In unserem Alltag werden wir ständig mit unterschiedlichen Problemen konfrontiert, manche davon sind leicht zu lösen und manche schwer. Verbrennt uns beispielsweise das Abendessen und wir brauchen schnell eine Alternative, wenn wir nicht hungern wollen, ist das für die Meisten von uns kein allzu großes Problem. Die Frage wie wir die Klimaerwärmung noch aufhalten können, ist hingegen ein deutlich komplexeres Problem.
Aber was macht die Komplexität eines Problems eigentlich aus? Was mach ein Problem zu einem schweren Problem? Dazu tragen mehrere Faktoren bei. Einige dieser Faktoren sind:
Intransparenz: Wenn wir nicht alle relevanten Informationen besitzen und damit zu viele Variablen oder vielleicht sogar ein ganzes System außerhalb unseres Horizontes liegen, ist es schwierig ein Problem zu lösen. In der Realität ist es sogar meisten so, dass wir nicht alle Variablen eines Problems kennen.
Vielschichtigkeit: Wir verfolgen gleichzeitig zu viele Ziele und haben nicht genügend Ressourcen, um sie alle zu erreichen. Wenn wir an zu vielen Stellen gleichzeitig aktiv werden müssen, wird es schwer mit den vorhandenen Ressourcen zum Ziel zu kommen.
Komplexität: Sind an einem Problem eine Vielzahl von Variablen beteiligt, welche alle miteinander in Abhängigkeit stehen, macht dies die Lösung des Problems um einiges schwieriger. Um das Problem lösen zu können, müssen wir dann ein hochkomplexes Geflecht aus Variablen durchschauen, um die Lösung zu finden.
Konnektivität der Variablen: Nicht nur die Anzahl der Variablen macht ein Problem schwer. Vor allen die Abhängigkeiten zwischen den Variablen machen es schwer Vorhersagen zu den Konsequenzen von Handlungen zu treffen. Wenn die Veränderung einer Variablen viele andere in mehr oder weniger bekannter Weise beeinflusst, wird es sehr schwer die Resultate abzuschätzen.
Dynamische Entwicklung: Ein weiterer Faktor ist Zeitdruck. Wenn es sich um ein Problem handelt, welches sich mit der Zeit weiterentwickelt oder sogar verschlimmert, erhöht auch dies die Problemkomplexität.
Zeitliche Trennung: Es fällt uns sehr schwer ein Problem nachzuvollziehen, wenn Ursache und Wirkung zeitlich voneinander getrennt sind. Wenn Einwirkungen auf Variablen des Problems erst zeitlich versetzt zu einem Effekt führen, wird es sehr schwer abzuschätzen, was genau welchen Effekt hatte oder haben wird.
Während viele der kleinen Alltagsprobleme mit wenig Aufwand und oftmals ohne bewusstes Nachdenken gelöst werden können, erfordern komplexe Probleme unsere volle Aufmerksamkeit. Unser Gehirn versucht darum öfter schwere Fragen durch leichtere zu ersetzen, um unser System 2 nicht zu sehr zu belasten. Wenn wir beispielsweise gefragt werden, wie zufrieden wir mit unserem Leben sind, ersetzt unser Gehirn diese Frage gerne durch eine leichter zu beantwortende. Beispielsweise wie unsere Stimmung gerade ist. Das passiert unbewusst und ist in vielen Fällen ausreichend zielführend. Aber eben nicht immer.
Im Vergleich zu der Zeit, in der sich unser Gehirn hauptsächlich entwickelt hat, haben wir es heute vermehrt mit komplexen Problemen zu tun, welche unsere volle Aufmerksamkeit benötigen. Wir müssen zum Teil ein großes Geflecht zusammenhängender Variablen beachten, um ein Problem wirklich verstehen zu können. Um alles zu erfassen und entsprechende Lösungsmaßnahmen antizipieren zu können, brauchen wir vor allem mehr Zeit. Wir können oft nicht innerhalb kürzester Zeit alle relevanten Informationen herausfiltern und ihre Zusammenhänge erfassen. Wir müssen lernen stillzustehen und erst alle Informationen und Möglichkeiten zu betrachten, bevor wir aktiv werden. Was so einfach klingt, ist oft enorm schwer umzusetzen. Wir sind darauf programmiert schnell zu agieren. Wenn wir ein Problem vor uns haben wollen wir so schnell wie möglich etwas dagegen tun. Auch wenn wir dabei riskieren etwas Falsches oder wenig Wirkungsvolles zu machen.
“Getting it right or getting it right now”
Auch wenn wir in der Regel ziemlich gut darin sind Probleme zu lösen, kommen wir in einer immer komplexer werdenden Welt auch öfter an unsere Grenzen und müssen vermehrt mentale Stolpersteine umgehen. Um dem gegenüberstehen zu können, sollten wir uns bewusst werden, wie unser Gehirn arbeitet und uns auch die Zeit nehmen, uns von mental anstrengenden Aufgaben zu erholen. Dass sich auch mentale Anstrengung körperlich auswirken kann, zeigt sich beispielsweise darin, dass unser Blutzuckerspiegel sinkt, wenn wir über ein schwieriges Problem nachdenken oder große Selbstkontrolle aufbringen müssen.
Methodische Ansätze
System Thinking in der Theorie klingt ja schön und gut, aber wie kann ich diese Denkweise nun praktisch anwenden.
“To Enlarge first, To Shrink then.”
Ein wichtiger Ansatz ist das Big Picture zusehen. Dies erreichen wir am besten in dem wir zuerst auf den Kontext erweitern, bevor man dann wieder einschränkt. Das bedeutet wir nehmen zusätzliche Faktoren, wie z.B. Zeit und das Umfeld in welchem sich unser System befindet mit auf und können dadurch mögliche Einflüsse auf unser System erkennen und diese mit einfließen lassen und mögliche Störungen und Probleme schneller erkennen oder diese sogar komplett verhindern. Wenn wir also beispielsweise Dinge clustern wollen, macht es Sinn, erst den Kontext der einzelnen Elemente zu erweitern, um herauszufinden, wie sie wirklich sinnvoll geclustert werden können. Nach diesem Ansatz sollte immer zuerst vorgegangen werden, um die anderen Methoden richtig einsetzen zu können.
Ein weiterer methodischer Ansatz sind hierbei die sogenannten Feedbackloops.
Um Systeme richtig zu verstehen, müssen wir uns im Klaren sein, dass beim System Thinking alles miteinander verbunden ist und wir davon ausgehen, dass diese Denkweise eine Organisation als lebendes System betrachtet. Die Teile eines Systems stehen in einem Ursache-Wirkungs-Zusammenhang und formen sogenannte dynamische Feedbackloops. Es gibt nur zwei Arten von solchen Feedbackloops, positives (Reinforcing) Feedback und negatives (Balancing) Feedback. In einem Feedbackloop gibt es außerdem auch nur zwei Arten von Beziehungen in welcher die einzelnen Elemente zueinanderstehen können. Elemente können entweder in einer kausalen Beziehung „+/s“ (gleich) oder „-/o“ (gegenteilig) verbunden sein. Eine solche visuelle Repräsentation, wie die Teile miteinander interagieren, hilft uns zu verstehen, wie zum Beispiel eine Intervention unser System beeinflussen würde.
Reinforcing-Feedbackloop
Ein Reinforcing oder auch positiver Feedbackloop ist die Basis von allen Veränderungen und der Motor für Wachstum aber auch Abschwung. Als Beispiele für solche Feedbackloops wären hier zum einen der Schneeball-Effekt, Pygmalion-Effekt oder auch das Phänomen „Die Reichen werden reicher, die Armen werden ärmer“ aufzuführen. Hierbei kann der Trend entweder rauf oder runter gehen.
Eine Eigenschaft ist, welche auch schon im Namen dieser Feedbackschleife steckt, dass sie selbstverstärkend ist. Sie verbindet Veränderungen in eine Richtung mit noch mehr Veränderungen, was zu exponentiellem Wachstum, aber auch zu einem Kollaps führen kann.
Wie kann ich einen solchen Reinforcing-Feedbackloop erkennen?
Eine schnelle Methode, um festzustellen, ob eine Schleife verstärkend oder ausgleichend ist, besteht darin, die Anzahl der „-/o“ zu zählen. Ist die Anzahl von „-/o“ gerade (oder Null) ist die Schleife verstärkend, bei einer ungeraden Anzahl ist sie ausgleichend. Obwohl dies eine effiziente Methode ist, sollten wir den Feedbackloop immer noch einmal genau überprüfen und checken, ob die Verbindungen richtig beschriftet sind.
Wann immer wir ein exponentielles Wachstum oder einen Niedergang erleben, steckt mindestens ein verstärkender Prozess dahinter. Reinforcing-Feedbackloops neigen dazu, Systeme aufgrund ihres Schneeballeffekts zu destabilisieren und so werden kleine Veränderungen schnell zu großen Veränderungen. Deswegen macht es Sinn diesen Prozess so früh wie möglich zu identifizieren, um die Ursache für das Wachstum oder auch dem Abschwung zu finden und gegebenenfalls rechtzeitig eingreifen zu können.
Balancing-Feedbackloop
Balancing-Feedbackloops sind die Grundlage aller Stabilität in unserer Umwelt und die Natur ist voll von solchen Ausgleichsprozessen. So besteht zum Beispiel der menschliche Körper aus tausenden von stabilisierten Prozessen, die dafür sorgen, dass unser Bedarf an Nahrung durch Hunger und Wasser gedeckt wird oder unsere Temperatur konstant bleibt. Auch im Arbeitsumfeld finden sich solche Feedbackloops. Zum Beispiel die, die dafür sorgen, dass Angebot und Nachfrage übereinstimmen. In solch einem Prozess wird auf ein Ziel hingearbeitet, ob es nun sichtbar ist oder nicht. Dieses Ziel oder auch Normwert wird Set Point genannt. Beim Ausgang eines solchen Feedbackloops besteht immer eine Lücke zwischen dem gewünschten Niveau (Ziel oder Norm) und dem tatsächlichen Niveau. Das tatsächliche Niveau wird bei einer zu großen Diskrepanz zwischen beiden so lange durch korrekturmaßnahmen angepasst, bis die Lücke kleiner wird. Ein Balancing-Feedbackloop versucht also immer die Bedingungen ins Gleichgewicht zu bringen.
Was bei einem Balancing-Feedbackloop eine große Rolle spielt ist die Verzögerung. Zwischen einer Aktion und dessen Ergebnis gibt es fast immer eine Verzögerung. Wenn solche Schleifen in Verbindung mit Verzögerungen stehen, können diese ein komplexes Verhalten hervorrufen. Dies liegt dran, dass es so viele verschiedene Quellen und Größen von Verzögerungen gibt. Wenn wir nun vermuten, dass es sich um einen Balancing-Feedbackloop mit Verzögerung handelt, macht es Sinn die beteiligten Verzögerungen zu identifizieren und zu beschreiben. Wenn uns das gelingt, können wir die Verzögerungen gegebenenfalls verkürzen oder zumindest besser damit umgehen und unser System damit zu einer größeren Stabilität verhelfen.
Das gute beim Systemdenken ist, dass es diesen Effekt der Zeit mit aufnimmt, da wir den Kontext erst erweitern bevor wir ihn dann schließlich wieder verkleinern.
In der folgenden Darstellung sehen wir noch jeweils ein Beispiel für einen Reinforcing- und einen Balancing-Feedbackloop.
Wir müssen uns darüber im Klaren sein, dass die Systeme, mit denen wir im Alltag oder Beruf zu tun haben, selten ein einzelner kleiner Feedbackloop ist, sondern aus vielen zusammenhängenden Feedbackloops besteht.
Kausale Zusammenhänge
Wie bereits erwähnt stehen die Elemente unseres Systems in sogenannten Ursache-Wirkungs-Zusammenhängen. Die einzelnen Teile unseres Systems können unterschiedlich in Verbindung miteinander stehen. Wir unterscheiden im Folgenden zwischen drei verschiedenen Verbindungen:
Mediator Junction: A → B → C
Hierbei handelt es um eine vermittelnde Verbindung. Wenn wir folgendes Beispiel betrachten, dann sehen wir, wenn „Rauch“ gefixt wurde, dann stehen „Feuer“ und „Alarm“ nicht länger in einer kausalen Verbindung zueinander. „Rauch“ nimmt hierbei die Rolle des Mediators (dt. Vermittler) ein.
Feuer → Rauch → Alarm
Fork Junction: A ← B → C
Bei einer Gabelverbindung hat eine Ursache mehrere Wirkungen. Die beidem Wirkungen haben eine gemeinsame Ursache und es besteht eine Scheinkorrelation zwischen A und C. So könnte man im folgenden Beispiel schließen, dass Kinder mit größeren Schuhen tendenziell besser lesen. Da zwischen der „Schuhgröße“ und der „Leserfertigkeit“ aber kein kausaler Zusammenhang besteht, ist die Schlussfolgerung wahrscheinlich falsch.
Schuhgröße ← Alter der Kinder → Lesefertigkeit
Collider Junction: A → B ← C
Bei einer Kollisionsverbindung beeinflussen mehrere Ursachen ein Ergebnis. In dem folgenden Beispiel beeinflussen die Ursachen „Talent“ und „Schönheit“ das Ergebnis „Prominente“.
Talent → Prominente ← Schönheit
So ist für Prominente nur eines von Beiden relevant, um prominent zu sein. Wenn eine bekannte Persönlichkeit ein guter Sänger wäre, müsse er weniger gut aussehen. Und umgekehrt müsste ein Sänger mit weniger Talent besser aussehen.
Wir haben nun einige wichtige methodische Ansätze kennen gelernt haben, um Systemdenken praktisch umzusetzen. Was wir aus den oben genannten methodischen Ansätzen mitnehmen sollten ist, dass wir zuerst den Kontext vergrößern, dann wieder verkleinern, die Zusammenhänge verstehen und die Hintergründe prüfen bevor wir handeln.
Was offen bleibt
Wir haben jetzt ausführlich betrachtet was die Grundannahmen des System Thinking sind, welche Methoden es gibt und was die psychologischen Grundlagen sind, aber es bleiben dennoch einige Fragen für uns offen. Denn so wie wir es verstehen basiert das System Thinking vollständig auf Prozessen von System 2 und es scheint eher so zu sein, dass versucht wird gegen System 1 zu kämpfen. Das ist aber auf Dauer nicht nur extrem anstrengend, es ist auch wenig sinnvoll, wenn man so ausgereifte und leistungsstarke Prozesse einfach ignoriert. Es ist natürlich sinnvoll, die Schwächen unseres Gehirns zu kennen, aber ebenso sinnvoll wäre es, wenn wir lernen, wie wir die Stärken besser nutzen. Zum Beispiel könnte es wirkliches Potential haben, wenn wir die Fähigkeit unseres Gehirns Zusammenhänge herzustellen und auf Basis von wenig Informationen ein mentales Modell zu schaffen nutzen würden. Mit der falschen Auswahl an Informationen wird unser mentales Modell fehlerhaft, aber wenn wir optimieren welche Informationen wir aufnehmen, dann würde auch das mentale Modell besser werden. Strategien wie wir die „richtigen“ Informationen herausfiltern, sollten deswegen besser herausgearbeitet werden. Es wäre also interessant, wenn das System Thinking sich noch gezielter die Stärken unseres Gehirns zunutze macht.
Auch bei der Problemlösung sollten wir keine Energie darauf verwenden, unseren angeborenen Drang schnell handeln zu wollen immer zu unterdrücken. Stattdessen wäre eine mögliche Strategie dem Ganzen eine produktivere Richtung zu geben. Welche Handlungen, die man schnell machen kann, helfen dabei dem Verständnis des eigentlichen Problems und damit einer langfristigen Lösung näher zu kommen? Denn wenn wir unser Verlangen immer unterdrücken bei einem für uns schwerwiegenden Problem nach etwas zu suchen, dass wir sofort tun können, setzt uns das unter Stress und gerade unter Stress treffen wir oft unreflektierte Entscheidungen oder fallen sogar in ein unproduktives „ich gegen die“ Denken.
Alles in allem bietet das System Thinking aber tolle Ansätze, um unser alltägliches Denken und Handeln ins Positive zu lenken. Es zeigt einige relativ einfache aber sinnvolle Methoden auf, wie wir komplexe Vorgänge besser verstehen können und die Zusammenhänge überblicken können. Es gibt einigen bekannten Methoden wie dem Clustern eine neue Richtung. Aber es verlangt auch ein hohes Maß an Selbstreflexion und Selbstkontrolle und ist demnach nicht für jede Situation im Alltag anwendbar. Um die Art des Denkens wie es im System Thinking vermittelt wird, besser zu verbreiten, sollten wir uns fragen, ob es nicht etwas sein sollte, was bereits in unser Bildungssystem einfließen sollte. Nicht nur Inhalte, sondern auch Konzepte und Strategien wie wir mit unserer komplexen Welt umgehen und zielführend Denken lehren.
Gerade im Management ist das System Thinking ein sehr wichtiges Konzept. Instinktive Entscheidungen stehen gutem Management oft im Weg und es wird selten über den Tellerrand des eigenen Teams oder der eigenen Abteilung hinausgeschaut. Aber genau das ist wichtig. Es ist notwendig über die alltäglichen Probleme hinauszudenken und wenn nötig in einem großen Kontext nach Lösungen zu suchen. Dazu ist ein interdisziplinärer Ansatz oft der richtige. Egal wie gut jemand ist, er kann nie ein Experte für alles sein und nie alle Blickwinkel annehmen. Das fliegt häufig noch unter dem Radar, obwohl es in unserer heutigen Zeit ein mächtiges Werkzeug sein kann, um gute Entscheidungen zu treffen.
Ein wichtiger Aspekt, über den man sich bewusst sein sollte, wenn man versucht tiefer in das System Thinking einzusteigen und die Konzepte auch anzuwenden ist, dass es uns nicht leicht fällt. Zum einen ist das System Thinking sehr umfangreich in seiner Theorie und zum anderen ist es sehr schwer die eigenen Denkmuster und Gewohnheiten abzulegen. Jede Veränderung, die zu einer neuen Sichtweise auf die Welt, unsere Arbeit und unsere Beziehungen und wie wir uns zu anderen verhalten führt, kann Widerstand hervorrufen. Es braucht Zeit, etwas Neues zu lernen und wenn wir mit dem Anspruch herangehen, von Anfang an alles wissen zu wollen und alles „richtig“ zu machen, blockieren wir uns im Endeffekt nur selbst.
Aber ist System Thinking jetzt das Schlüsselkonzept des 21. Jahrhundert?
Wir würden sagen ja und nein. System Thinking ist ein wichtiges Konzept und mehr Menschen sollten darauf zurückgreifen, aber es ist nur ein Werkzeug unter vielen. Auch der analytische Ansatz hat beispielsweise seine Berechtigung und kann für manche Probleme die essenzielle Schlüsselrolle spielen. Es sollte also eher so sein, dass wir uns mit einer Reihe von Denkkonzepten und Strategien dem 21. Jahrhundert gegenüberstellen. Würden wir uns zu sehr auf ein Konzept versteifen, würden wir uns ja wieder einschränken und uns weiteren Verbesserungen und Neuerungen verschließen.
Ob wir wollen oder nicht, die Welt wird immer komplexer und es ist immer mehr voneinander abhängig. System Thinking sieht dabei die Individuen und Organisationen als Bestandteile, die auf einer multidisziplinären Ebene in einem großen System arbeiten und nicht als einzelne unabhängige Elemente. Die Akzeptanz, dass alles miteinander in Verbindung steht, hilft uns unsere Interessen, Ziele, Probleme und Lösungen klarer zu kommunizieren und in unserer Realität zu verorten.
Quellen
Making better decisions using systems thinking. 2017. New York, NY: Springer Berlin Heidelberg.
Müsseler, Jochen, und Martina Rieger, Hrsg. 2017. Allgemeine Psychologie. 3. Auflage. Lehrbuch. Berlin Heidelberg: Springer.
Myers, David G., und Siegfried Hoppe-Graff. 2014. Psychologie. 3., Vollst. überarb. und erw. Aufl. Springer-Lehrbuch. Berlin: Springer.
Kahneman, Daniel, 1934- author. Thinking, Fast and Slow. New York :Farrar, Straus and Giroux, 2011.
Systemic thinking. 2014. New York, NY: Springer Berlin Heidelberg.
Arnold, Ross D., und Jon P. Wade. „A Definition of Systems Thinking: A Systems Approach“. Procedia Computer Science 44 (2015): 669–78. https://doi.org/10.1016/j.procs.2015.03.050.
Han Kai. Introduction of System[s] Thinking – Seeing “forest” from “tree”. Präsentation.
Über Social Engineering und wie man sich schützen kann.
Jeder kennt E-Mails mit Titeln wie diesem. Eine wildfremde Person verspricht Gewinne in Millionenhöhe. Und alles, was dafür benötigt wird, sind ein paar persönliche Daten. Ein Traum vieler Menschen wird wahr und man will dem Titel glauben. Doch was passiert, wenn man der E-Mail nachgeht? Ist es so leicht, Millionen zu kassieren? Und was gibt es noch für Möglichkeiten meine Daten gegen fantastische Träume einzutauschen?
Dieser Artikel soll die Gefahren des Alltags aufdecken und einfache Wege zeigen sich zu schützen.
Im Rahmen der Vorlesung “Software Development for Cloud Computing” habe ich im vergangenen Semester eine Einführung in die Welt des Cloud Computings incl. der relevanten Konzepte und Technologien erhalten. Einige dieser Konzepte habe ich versucht in meinem Abschlussprojekt umzusetzen, das ich im Nachfolgenden vorstellen möchte.
Idee/Projekt
Die Idee war es eine Webanwendung zu konzipieren und zu entwickeln, welche dem Nutzer beim persönlichen Wissensmanagement unterstützt. Die Applikation hilft dem Lernenden sich jeden Tag mit seinen Wissensgebieten auseinander zu setzen, indem diese ihm täglich eine Email mit einem Link zu seiner personalisierten Wissensabfrage sendet.
Mit einem Klick auf den Link landet der Nutzer bei einer zufälligen Auswahl von bis zu 25 Fragen seiner bisher erfassten Lerninhalte. Die Anwendung zeigt nun eine Frage und einen Timer an. Der Nutzer soll nun innerhalb von 10 Sekunden sich die Antwort ins Gedächtnis rufen. Wenn er eine Antwort im Kopf hat, klickt er den Button „Reveal“, welcher die korrekte Antwort aufdeckt. Nun muss der Nutzer angeben, ob seine Antwort im Kopf mit der tatsächlichen Antwort übereinstimmt. Schaft der Nutzer es nicht innerhalb von 10 Sekunden zu antworten wird automatisch eine neue Frage angezeigt.
Das Ziel ist es das Gedächtnis zu trainieren. Die jeweiligen Fragen werden so lange per Zufallsauswahl wiederholt, bis der User alle Fragen einmal richtig mental abgerufen hat.
Konzept Skizze
Ziele für die Umsetzung
Mein Ziel war es eine derartige fachliche Problemstellung als Serverless Architektur zu realisieren. Zugleich wollte ich erste Erfahrungen mit der AWS Infrastruktur sammeln. Um eine zentrale und automatisierte Verwaltung aller Ressourcen sicherzustellen, die Lösung skalierbar zu gestalten und um Cloud Ressourcen zu minimieren sowie das Risiko von versteckten Kosten zu reduzieren, war das Ziel das Projekt als Infrastructure as Code zu implementieren.
Implementierung
Architektur
Als Infrastructure as Code -Tool wurde AWS Sam (AWS Serverless Application Model) verwendet. Dieses baut auf Amazon’s Cloudformation Infrastructure as Code Syntax auf und liefert zusätzlich noch ein Command Line Interface, welches das Deployment und lokale Testing von Lambda Funktionen ermöglicht.
Die Frontend-Applikation wurde mit Hilfe des Frontend-Frameworks Angular erstellt, in welchem ich im Rahmen dieses Projektes erste Erfahrungen sammeln konnte. Deployed wird das Frontend mithilfe einer AWS Amplify Build Pipeline, welche durch Commits auf den in SAM spezifizierten Branch ausgelöst wird.
Signup Page
Signup Page
Question Page
Question Page
Eine besondere Herausforderung hierbei war es, dass der Link, den die Angular Anwendung nutzt um auf das Backend zuzugreifen dem aktuellen Link des API Gateways entsprechen muss. Dazu wird dieser durch SAM der Amplify Ressource als Environmental Variablen übergeben. Diese wird dann in der Build Pipeline verwendet um den Link in der Index.js des Angular Builds mit der Variablen zu substituieren.
SAM Template
Amplify Build File
Das Backend der Anwendung setzt basiert auf mehreren AWS Services.
Der Zugriff des Frontends auf das Backend erfolgt über API Gateway mit 2 Routen.
post /subscribe: Leitet den Request an SubscribeEndpoint Lambda weiter
get /daily-prompt: Leitet den Request an DailyPromptsEnpoint Lambda weiter
Die Funktionalität der App ist über 3 Lambda Funktionen realisiert.
DailyEMailGenerator: Wird täglich von einer CloudWatch Schedule aufgerufen und generiert für jeden registrierten Nutzer eine Selektion an täglichen Fragen aus der Menge aller hinterlegten Fragen.
DailyPromptsEndpoint: Liefert die in der Datenbank hinterlegte Menge an täglichen Fragen für einen Nutzer
SubscribeEndpoint: Fügt den Nutzer der Subscriber Tabelle hinzu und speichert das mitgelieferte Fragen / Antwort Paar
Die Datenbank ist als DynamoDb mit den 3 Tabellen Subscribers, SubscriberData und DailyPrompts realisiert.
Alle Ressourcen und notwendigen Rollen und Policies sind in einem SAM Template File erfasst und können bequem per SAM CLI deployt werden. Dabei wurde Wert darauf gelegt sensible Daten wie den GitHub Access Token, den Amplify benötigt, als Environment Variables abzufragen, anstelle diese hart zu coden.
Probleme
Als Hauptproblem hat sich für mich der riesige Umfang von AWS herausgestellt, da es eine Vielzahl an Dokumentationen zu lesen gibt, so dass es für einen Einsteiger schwierig ist, sich direkt zurecht zu finden. Das Angebot an Informationen zu Cloud (Patterns, Best Practices, etc.) und Cloud Services ist gefühlt unendlich. Es ist deshalb schwierig das für die Problemstellung wirklich relevante Wissen zu finden und die Qualität der verfügbaren Informationen ist stark unterschiedlich. Da das User Interface von AWS-Diensten von Service zu Service variiert, ist auch die Navigation innerhalb der Dienste nicht immer einfach.
Ursprünglich war geplant Terraform als plattformunabhängiges Infrastructure as Code-Tool einzusetzen. Jedoch stellte sich dessen Dokumentation bezüglich spezieller AWS Services teilweise als unvollständig heraus und hat somit nach vielen erfolglosen Versuchen dazu geführt, dass AWS SAM als Infrastructure as Code-Tool adaptiert wurde.
Des Weiteren gestaltet sich das Debugging schwieriger wie auf dem eigenen Rechner. Dies hängt mit dem komplexen Zusammenspiel der vielen AWS Services zusammen und macht eine Fehlersuche oft sehr schwierig. AWS bietet hierfür CloudWatch als zentrale Logging-Plattform an. Es kann aber vorkommen, dass Fehler auftreten ohne dass diese erfasst werden. Ich hatte beispielsweise das Problem, dass eine Lambda-Funktion plötzlich nicht mehr in die Datenbank geschrieben hat, ohne Fehler zu loggen, obwohl andere Funktionen denselben Code ohne Probleme auf dieselbe Datenbank anwenden konnten. Der Fehler hat sich nach einigen Stunden von selbst erledigt, es blieb allerdings intransparent, wodurch die Lösung erfolgt ist.
Lessons Learned
Ich habe in diesem Projekt sehr viel spannendes über die Entwicklung für AWS und die Cloud gelernt, sodass ich durch diese Veranstaltung einiges an theoretischem als auch praktischem Wissen im Bereich Cloud Computing aufbauen konnte. Das Projekt war gezeichnet von sehr viel ausprobieren was sich häufig auch nicht in der finalen Lösung niedergeschlagen hat.
Darüber hinaus konnte ich praktische Erfahrungen in der Implementierung von Webanwendungen aufbauen. Ein weiteres Lessons Learned für mich ist, dass ich ein solches Projekt in einem komplexen Themengebiet, in welchem ich keinerlei Vorkenntnisse hatte zukünftig wohl nicht mehr alleine angehen würde da ich mir sicher bin das ich mir viele Stunden recherchieren und Trial und Error durch eine weitere Person hätte ersparen können.
Im Rahmen der Vorlesung “Software Development for Cloud Computing” haben wir uns hinsichtlich des dortigen Semesterprojektes zum Ziel gesetzt einen einfachen Instagram Klon zu entwerfen um uns die Grundkenntnisse des Cloud Computings anzueignen.
Grundkonzeption / Ziele des Projektes
Da wir bereits einige Erfahrung mit React aufgrund anderer studentischer Projekte sammeln konnten, wollten wir unseren Fokus weniger auf die Funktionalität und das Frontend der Applikation richten und ein größeres Augenmerk auf die Cloud spezifischen Funktionen und Vorgehensweisen legen.
Konkret planten wir die Umsetzung eines Instagram Klons mit den grundlegenden Funktionalitäten:
Bilder bzw. Beiträge hochladen
Titel & Beschreibung von Beiträgen anlegen
Liken von Beiträgen
Kommentieren von Beiträgen
Accountmanagement
Entwurfsentscheidung
Frontend
Aufgrund von bereits existierenden Vorkenntnissen und guter Erfahrungen entschieden wir uns für die Umsetzung des Frontends mit Hilfe des React Frameworks. Mit der Gestaltung als Web App ergibt sich zudem der Vorteil, dass “Ynstagram” Plattform übergreifend erreichbar ist.
Backend – von Firebase zu AWS
Zunächst starteten wir unser Projekt mit Firebase umzusetzen. Zum einen verlor dies jedoch seinen Reiz hinsichtlich des Lerneffekts, da wir parallel unser Softwareprojekt mit Firebase verwirklichten. Gleichzeitig wurde uns durch die Einblicke in den Vorlesungen ein Bewusstsein für den Funktionsumfang von AWS geschaffen.
Interessant war für uns hierbei beispielsweise die wesentlich umfangreicheren Einsatzmöglichkeiten von Lambda Funktionen. Während diese in Firebase nur durch Einträge / Trigger geschehen kann, konnten wir hier auf API Aufrufe zurückgreifen. Auch die umsetzbaren Funktionalitäten gestalteten sich als wesentlich umfangreicher. So bot sich uns unter anderem die Möglichkeit Bilder beim Upload automatisiert zu skalieren und perspektivisch ließe sich auch recht einfach eine Analyse von Inhalten mit Hilfe von Künstlicher Intelligenz umsetzen. Während man bei Firebase in all dem schnell an gewisse Grenzen kommt, gibt es bei AWS einen viel breiteren Horizont an Möglichkeiten.
Dennoch gestaltete sich dieser Umstieg keineswegs als einfach, denn Firebase bietet eine wesentlich bessere Übersichtlichkeit und Dokumentation.
Serverless
Da uns die AWS Web Oberfläche und die Online Erstellung von Lambda Funktionen keineswegs ansprachen suchten wir nach Lösungen um alle Konfigurationen wenn möglich auch auf Github hinterlegt zu haben und im Code Editor anlegen zu können.
Dabei sind wir letztlich auf Serverless gestoßen. Hier werden alle Buckets, Tabellen und API Aufrufe über ein serverless.yaml File verwaltet. So lassen sich neue Elemente viel übersichtlicher / schneller anlegen und Konfigurationen können einfach von bereits erstellten Elementen übernommen werden.
Postman
Um einen Überblick über die erstellten API Routen zu behalten und um diese einfach testen zu können, haben wir uns für Postman entschieden. Über ein in Github geteiltes File können so alle am Projekt beteiligten die aktuellen API Routen sehen und neue Aufrufe anlegen.
Umsetzung / Architektur
AWS Services
DynamoDB
Da wir bereits in Firebase auf die dortige NoSQL Datenbank “Firestore Database” zurückgegriffen hatten, entschieden wir uns hier für eine Beibehaltung dieser Datenbankstruktur. Der Vorteil liegt dabei gegenüber SQL Datenbanken in einfacheren Abfragen bedingt durch eine flachere Datenstruktur.
Wir verwenden DynamoDB Tabellen um die zu den Bildern gehörenden Informationen wie z.B. Titel, Beschreibung, Autor etc. zu speichern. Die Verknüpfung der Bilder mit den Datensätzen in den Tabellen erfolgt dabei durch eine einzigartige ID.
Es gibt dabei 2 Tabellen, eine in der zunächst die Eingaben gespeichert werden, und eine weitere in die verarbeitete Datensätze übertragen werden.
Beide Tabellen sind dabei strukturell gleich aufgebaut. Zentral sind hier eine eindeutige ID, Datum der Erstellung, Account Name des Erstellers, sowie Beschreibung und Titel des Beitrags. Kommentare und Likes werden über Arrays verwaltet.
S3
In S3 Buckets sind die zu den Beiträgen hinterlegten Bilder gespeichert. Dabei gibt es einen Bucket mit den Originaldateien, sowie einen mit verringerter Auflösung. Der Name der Bilder entspricht dabei stets der den Beiträgen zugehörigen einzigartigen ID.
Cognito
Mit AWS Cognito konnten wir in wenigen Schritten unser Account Management einrichten. Cognito bietet dabei die Unterstützung aktueller Identitäts und Zugriffsmanagement Standards wie zB. Oauth 2.0 und SAML 2.0 und bietet gleichzeitig auch die Möglichkeit Multifaktor Authentifizierung zu implementieren.
Amplify
Wir nutzen AWS Amplify um das Frontend unserer Applikation zu hosten und um hierfür eine CI/CD Pipeline mit Development und Master Umgebung zu realisieren. Eine genauere Erklärung hierzu findet sich im Abschnitt “CI/CD Pipeline”.
Lambda
API Gateway
Ein großteil unsere Lambda Funktionen wird über API Aufrufe genutzt. Eine Übersicht dieser haben wir wie eingangs erwähnt in einem Postman File hinterlegt.
API-Routen
POST /image-upload
Hochladen eines Bildes in den S3 Bucket. Wird sowohl mit Bilddaten als auch mit dazugehörigen Informationen wie Beschreibung und Titel aufgerufen (JSON-Format).
POST /image-info
Erstellt einen Eintrag in die DynamoDB Tabelle mit sämtlichen Informationen zu einem Beitrag, wird im Body als JSON übermittelt.
POST /create-file
Erstellt eine Datei im S3 Bucket. Der Dateiname entspricht dem URL Parameter.
GET /get-all-images
Gibt alle als “valid” markierten Beiträge als Array im JSON-Format zurück.
GET /get-file
Gibt eine Datei anhand des Dateinamens zurück.
GET /image-info
Gibt die Informationen zu einem einzelnen Beitrag im JSON-Format zurück.
PUT /update-image-info
Genutzt um Kommentare zu Beiträgen hinzuzufügen. Updated Einträge in der DynamoDB Tabelle.
PUT /update-likes
Verwendet um neue Likes hinzuzufügen.
DynamoDB / S3 Trigger
Neben direkten API Aufrufen verwenden wir auch Trigger auf DynamoDB Tabellen, sowie S3 Buckets.
Exemplarischer Ablauf eines Image Uploads
Dies lässt sich am Besten am Ablauf einer Beitragserstellung darstellen.
Per Post-Request wird zunächst die Lambda Funktion “imageUpload” aufgerufen, welche das Bild in dem S3 Bucket hinterlegt. Dann wird über einen Trigger automatisch die Lambda Funktion “imageResize” aufgerufen, welche die Bilder auf eine Auflösung von 400 x 400 Pixeln skaliert. Diese Bilder werden dann im Bucket für skalierte Bilder gespeichert. So können die Bilder im Feed gerade bei Mobilen Geräten schneller geladen werden.
Parallel dazu wird in der DynamoDB Tabelle ein Eintrag angelegt. Auch hier wird ein Trigger aufgerufen der seinerseits die Funktion “changeText” aufruft. Diese ersetzt in Anlehnung an den Namen “Ynstagram” alle “i” in Beschreibung und Titel durch “y”. Hierbei handelt es sich lediglich um eine Spielerei die aus unserem Interesse entstand verschiedenste Trigger und Einsatzmöglichkeiten von Lambda Funktionen auszuprobieren.
CI/CD Pipeline
Interessant war es für uns zudem erstmals wirklich Erfahrung mit einer CI/CD Pipeline zu sammeln. Wir planten dabei die strikte Unterteilung in eine Entwicklungsumgebung und einer dieser prinzipiell gleichen finalen Umgebung. So dass der aktuelle Stand schon unter realistischen Bedingungen getestet werden kann bevor er letztlich veröffentlicht wird.
Diese CI/CD Pipeline haben wir mit AWS Amplify und Github Actions umgesetzt. Dabei wird zunächst stets auf einen Development Branch gepusht, welcher dann automatisch auf eine Entwicklungsumgebung auf Amplify hochgeladen wird. So können zunächst alle Tests durchgeführt werden, bevor dann mit einem Pull request die Änderung auf den Master Branch übertragen werden. Wenn dies geschehen ist, werden diese ebenfalls automatisch in die Produktionsumgebung übernommen bzw. deployed.
Hier wird neben den durch Github Actions durchgeführten Tests auch überprüft ob die Web Anwendung auch auf verschiedenen Geräten richtig skaliert und damit überprüft ob die UI für den Nutzer funktionsfähig angezeigt wird. Der aktuelle Stand wird dabei selbstverständlich nur übernommen, wenn alle Tests erfolgreich abgeschlossen werden.
Serverless
Um der Unübersichtlichkeit der AWS Weboberflächen aus dem Weg zu gehen und um Elemente leichter und reproduzierbar, über Git verwaltet anlegen zu können haben wir uns für Serverless entschieden. Hier werden alle AWS Komponenten in einem “serverless.yaml” File angelegt.
Variablen
Es gibt dabei zum Beispiel auch die Möglichkeit unkompliziert Environment Variablen anzulegen:
Welche wir wiederum über eigene custom Variablen, welche an verschiedenen Stellen genutzt werden definiert haben:
Dies bringt den Vorteil mit sich, dass Namen flexibel verändert und direkt überall übernommen werden, sprich sowohl in AWS als auch im Code über die Environment Variablen.
Functions
Gleichermaßen einfach lassen sich auch die Lambda Functions anlegen. Diese werden jeweils über einen “handler” referenziert und werden dann durch ein “event” aufgerufen, was entweder API Aufrufe oder eben bspw. DynamoDB / S3 Trigger sein können.
Resources
Auch alle Buckets und Tabellen sind im .yaml File definiert. So können insbesondere neue Elemente sehr einfach angelegt werden, da man direkt auf zuvor definierte Konfigurationen zurückgreifen kann.
Testing
Beim Testen haben wir uns vor allem auf die API Aufrufe und die grundsätzlichen Funktionen fokussiert. Grundsätzlich werden unsere Tests über die im Abschnitt “CI/CD Pipeline” dargestellte Pipeline mit Github Actions ausgeführt. Diese sind auch Bestandteil des Amplify Deployment Prozesses. Zusätzlich dazu haben wir CircleCi implementiert um die Serverless Komponenten automatisch zu deployen. Für das Testing nutzen wir allgemein ein lokales Mock-Up unserer DynamoDB da wir hier schnell auf das Problem gestoßen sind, dass unsere freien AWS Kontigente aufgebraucht waren.
Ausblick / Fazit
Die größten Schwachstellen des Projektes liegen aktuell in nicht abgesicherten API Aufrufen, diese ließen sich über die Verwendung von API Keys schützen. Dabei sollten perspektivisch auch die Zugriffe auf DynamoDB sowie S3 über IAM Role verwaltet werden.
Für die Accountverwaltung wäre es sinnvoll die Multifaktor Authentifizierung einzurichten. Der Funktionsumfang ließe sich selbstverständlich noch deutlich ausbauen, wobei besonders die Nutzung von KI Komponenten für uns interessant wäre.
Insgesamt konnten wir, ausgehend von keinerlei Grundkenntnissen im Bereich Cloud Computing, uns mit Hilfe der Umsetzung des Projektes im Rahmen der Vorlesung einen Überblick und ein Grundverständnis für die Welt des Cloud Computings erarbeiten, welche eine solide Basis bieten um zukünftig die vorliegenden Ansätze noch wesentlich weiter zu vertiefen.
For the examination of the lecture “Software Development for Cloud Computing”, I want to build a simple Random Chat Application. The idea of this application is based on the famous chat application called Omegle. Omegle is where people can meet random people in the world and can have a one-on-one chat. With Omegle people can have a conversation with not only normal chat but also a video chat. Not like Omegle, my application has only a normal texting function.
2. Technologies for the development of application
a. Frontend
React
For Frontend Development there are a great number of open-source libraries. React is recently one of the most popular and widely used libraries. There are many reasons for a developer to choose and use React. It is one of the most popular front-end technologies in the market. Compared to other libraries out there React seems to be easier to learn. As it doesn’t take much time to learn this technology, the developers can rapidly practice and build their own very first project. React helps increase productivity by using reusable components and development tools. There are many development tools available for React that speech up the project. The most important reason is that it has very strong community support. There are thousands of free React tutorial videos and blog posts on the internet which is very helpful for the developer. Therefore, I decided to learn this library during previous semesters. This project gives me a chance to have real practice.
b. Backend
Node.js
Node.js has become one of the most popular JavaScript tools. Node.js is a JavaScript runtime environment, which allows companies to improve their efficiency of the web development process. The frontend and Backend teams can now work more easily together. Since Node.js is written in JavaScript and bases on Google V8 Engine, everything is done very quickly. Node.js can create an Event Loop, which can cover all asynchronous input-output operations. And the best part is that it can increase the speed of any other framework as well. By allowing developers to write JavaScript code for both the Frontend and the Backend, Node.js makes it easy to send data between the server and the client, which makes it easier to synchronize data immediately.
Socket.io
When I decided to develop a chat application, I already thought about Socket.io. I had a chance to know this JavaScript library during the course Web Development 2. To build a real-time application we should use Socket.io. Socket.io will help parties in different locations connect with each other, transmitting data instantly through an intermediary server. Socket.io can be used in many applications such as chat, online games, updating the results of an ongoing match, … It is used a lot by the developer community, because of its speed and convenience. Socket.io provides us with many methods as well as outstanding features such as security, auto-connect, disconnection detection, multiplexing, room creation, …
3. Application explanation
a. Client
As I mentioned, for the client-side I use React. Therefore, I have a chance to know the concept of a Single Page Application, whose content is loaded only once and updated dynamically. For the interaction with the page or with subsequent pages, we don’t need another server, which means that the page is not reloaded. To apply this concept of the web application, React offer a packet names “react-router-dom”. My application is very simple, so it only has two paths to be loaded. The root path is where the user inputs his name, and it will load the Join component. The other path is the Chat component, in which the user sends messages after getting a room.
Socket.io library for the client is imported because it is not provided by JavaScript. This will expose the ‘io’ namespace.
Endpoint URL will be given for ‘io’ to connect with the socket.io server.
Now users can send and receive messages from the server after the room is created.
b. Server
To setup server, some packets need to be imported:
The server is set up and listen on port 5000
The server can also save users temporally, so it will know which user’s name already existed. And then it can remove users after they terminate their chat. To execute all those actions, I write a users.js file, which will have some functions such as, addUser, removeUser, getUser, …
I want to create a chat application where users don’t have to have an already known friend and a Chat room will be automatically created for them. With this application, they can meet a new friend and the server will get them a chat room.
I created a variable queue, which is an array. It will save a user, who has not had any partner yet, temporarily. Every user, who already inputted their names, will be connected to the socket. Socket knows that he wants to join a room. In the callback function of the socket, the name and socket ID of the user will be saved by function ‘addUser’, which is in users.js. Then socket will check if any other user is waiting for a partner in a queue. If someone is waiting for a partner, he will be popped from the queue. His socket and partner’s socket will be connected. And their room ID will be a combination of the 2 socket IDs. If no one is waiting for a room, the current socket is pushed to a queue and wait for another user to join.
c. Problem
CORS:
It is an abbreviation for Cross-Origin Request Sharing, which means that all data should come from the same resource. They use it as a security measure because JavaScript can load content from other servers without the knowledge of the user. This problem can be solved when both websites are aware of the data exchange, then the process will be allowed.
I installed the CORS package on my server. Origin will configure the Access-Control-Allow-Origin CORS header. Now client and server can communicate without error.
4. Testing
Testing is very important during the development of the application. Testing helps developers to discover existing errors/bugs before releasing the application. Therefore, the quality of the application would be enhanced. I decided to test only the server-side because it is more complicated than the client-side. Two tests are being created.
A single user testing: tests if he can connect to a server and receive a welcome message from the server.
Two users testing: tests if a room can be created when there are two users and both of them can receive the same welcome message from the same room.
5. Deployment
a. Docker Swarm and Kubernetes
When deploying this project, I create a container for each of the client and server sites. Docker is the most popular solution for the container platform. I want to learn to write a DockerFile and a docker-compose to create a container.
For the cloud development environment, I choose Amazon Web Service. It is currently one of the most comprehensive platforms for cloud computing services. I use an EC2 virtual server to make my project online. I would like to work with Kubernetes to manage the containers. I choose EKS, which is a service from Amazon web service.
If you work with a lot of containers, you have to be able to manage them efficiently. An orchestration tool enables exactly that. With the orchestration tool, you can integrate containers that you created with Docker. Then you use orchestration to manage, scale, and move the containers.
Although Kubernetes and Docker can work well together, there is competition when it comes to Docker Swarm. I have considered some features of Docker Swarm and Kubernetes.
Scaling: The load on our application is too high, Kubernetes can add more nodes to our cluster. Of course, we have to configure Kubernetes correctly so that it can create a new virtual machine. Then a node is added to the cluster.
Installation: with Docker Swarm, it is easy to create a new node, then integrate it with Swarm. On the other hand, to configure Kubernetes you have to determine the size of the node, how many master nodes, and worker nodes.
Load balancing: Docker swarm offers application auto load balancing. However, Kubernetes gives the flexibility to configure load balancing manually.
Storage volume participation: since the docker swarm manages Docker containers, containers find it easy to share data. Not just data, as well as other things. Kubernetes puts the container in a pod so the container cannot simply communicate with another. You need other components from Kubernetes, e.g., Service to create the connection.
Monitoring: While Swarm requires additional resources for monitoring and keeping a log, these tasks are already provided for in Kubernetes.
b. Amazon EKS and Kops
When deploying Kubernetes on AWS, you can configure and manage the deployment yourself for full flexibility and control. There are a few options for self-management: Amazon Elastic Kubernetes Service and Kops.
EKS is a managed service offered by AWS. EKS uses automatically provided instances and offers a managed control plane for deployment.
Kops is an open-source tool that can be used to automate the deployment and management of clusters on AWS. It is officially supported by AWS.
c. Docker File
To work with Kubernetes, I need to create all necessary containers. Containers are created by writing docker files. These docker files contain all information about the container, e.g.: name of the image, directory store our application, port, … Docker will follow this information, then step by step, create containers. Besides, I use Docker Compose to start the process of creating containers.
d. Kubernetes architecture on AWS cloud
I choose Kubernetes, Amazon EC2, EKS, ECR for the deployment of my project. What is showed below is the architecture of Kubernetes on AWS cloud.
Kubernetes server is a control panel. It creates a cubic cluster. In the cluster, there are master nodes that create and manage worker nodes. When you call deployment commands, the Kubernetes server sends messages to EKS, then EKS sends the tasks to the worker nodes.
Worker node contains some pods, in which the docker container will be run. I choose controller Deployment to keep these pods running and observe them. For the worker node, I create a pod for the client, 2 pods for the server, and a pod for Redis. The load balancer can be used to communicate with the application from outside.
I decided to have 2 pods Server because I want to scale my application. In case when more people try to connect to my application, the request will be handled faster when we have 2 pods instead of 1 pod. The picture below shows a horizontal scaling, which means that it has more copies of the application and these copies can work with each other at the same time.
For example: for the pod client I write a client-deployment.yaml file
A deployment named client is created, indicated by the .metadata.name field.
The .spec.selector field defines how the deployment finds the pods to be managed.
The deployment creates one replica pod, indicated by the .spec.replicas field.
the .template.spec field indicates that the pod is running a container. The container is created by docker image, which has been saved in ECR (Elastic Container Registry)
The container is created using the .spec.template.spec.containers.name field which is called client.
To enable network access to the set of pods I have to create a Service, which is written in client-service.yaml.
This specification creates a new service object called “client” that targets TCP port 3000 on each pod, which is labeled as app = random-chat.
For pods Server and Redis, I also create Deployment and Service for each.
e. Problem
Service of pod Server:
Pods can usually send requests with each other by using a normal type of Service, which means, in my case, that the pod Client can send a request to the pod Server without having an attribute ‘type’ in server-service.yaml. The Endpoint of the Client will be ‘server:5000’, which is the combination of the name of the service and the targetPort. But after many attempts, it still does not work. So, I decided to make the Service of pod Server as type Load Balancer, which is shown in the picture above. Now the Endpoint of the client will be the address of this Load Balancer.
6. Conclusion
During the course ‘Software Development for Cloud Computing’ and this project, I have a chance to know the concept of Docker containers and how to manage them with Kubernetes. I gain not only theoretical knowledge but also practical experience by developing and deploying the application. Moreover, working with cloud computing is new and interesting for me. Cloud computing is nowadays applied in the development of applications a lot. What I applied in my project is just a small part of cloud computing and I want to learn more about it in the future.
by Oliver Klein (ok061), Daniel Koch (dk119), Luis Bühler (lb159), Micha Huhn (mh334)
Abstract
You are probably familiar with the HdM SB-Funktionen. After nearly four semesters we were tired of the boring design and decided to give it a more modern look with a bit more functionality then it currently has. So we created “Studidash” in the course “Software Development for Cloud Computing”. “Studidash” shows your grades and automatically calculates the sum of your ECTS and also an average of your grades.
Since this is a project for SD4CC it runs as a serverless web application at Amazon Web Services, or AWS for short. Our tech stack for this project consists of Angular, Python, Terraform and some AWS Services like Lambda or S3.
While developing this Web-App we encountered some difficulties but also learned a lot of stuff and we hope that this blog post can give you a quick overview of what we did, what we learned, what problems we had and how we solved them so you have it easier for your next project.
What did we do?
As mentioned in the abstract, we developed a serverless Web-App called “Studidash” because of said boring design of the SB-Funktionen. First of all, we decided that we wanted to learn a new tech stack and came to the conclusion that Angular as our frontend would be the most modern frontend framework. For our backend we decided to use Python since it’s lightweight and easy to learn. From another course we learned about Terraform so this was something we were already somewhat familiar with and decided to use it for our deployment to AWS. We also used AWS to host the Web-App since we got access to AWS Student Accounts.
After we settled for a project and our tech stack we had to think about a way to make it “cloud native” and started to research some information and came across serverless. We dug a bit deeper and found some useful information. So we came to realize that serverless might be the way to go. Serverless means that our (or maybe your application) isn’t running completely on a “on-prem”-server but is running in the cloud instead. That means the application itself isn’t coupled to the server. Servers are still there but you don’t have to think about the administrative stuff around that. This is all going to be handled by your cloud service provider. The serverless approach brings scalability, high availability and efficient resource usage and management with it. As mentioned, you can focus more on the development itself rather than thinking about servers. A connection to a CI/CD pipeline makes it easy and fast to release a new version of your application. But serverless also has its downsides. The functions have to be as small as possible to only fit one purpose and some Web-Apps can have higher latency due to a cold start (When a function isn’t used for quite some time it gets destroyed and needs to be instantiated again, which takes time). You are also going to have a bad time debugging your application since it isn’t as easy as you might be used to. In the end we went with a static frontend in a S3-Bucket, a backend running as AWS Lambda Functions and AWS API Gateway to connect them.
Architecture
Our architecture is fully hosted on AWS and our code repositories are hosted on the HdM GitLab server. The clients can access our frontend via their favourite web browser. Our frontend application is hosted in an AWS S3-Bucket. The good thing here is that we don’t have to manage or deploy any web server by ourselves. This reduces the management overhead and in the end the costs. After the frontend is served to the client, the user can input their user credentials to access their grades from the third party service (HdM SB-Funktionen). A HTTP-Request will then be sent to a Lambda Function with an API-Gateway to receive the request. This Lambda Function contains a Python script which will parse the user credentials provided in the received HTTP-Request and use them to make a login at the SB-Funktionen platform and scrape the necessary grades and lecture data from the user. This scraped data will then be preprocessed and returned as a JSON-Object to the frontend.
From the developer side we used Git/GitLab for the version control of our code. In GitLab we created a CI/CD pipeline to build the frontend, the Python grade scraper and a Terraform image to deploy all our neccessary AWS resources. Thanks to the CI/CD pipeline the developer can just push the newest code base to the repository and it will be deployed automatically to AWS.
Architecture overview
Frontend
For our frontend we decided to build an Angular single page application. We made this decision because it’s an up-to-date framework to build fast and easy web applications.
When the user loads the website the header only displays a login component for the HdM SB-Funktionen credentials. This component triggers a POST request to the Lambda Function containing the login data. The Lambda Function then responds and returns several grade objects to the frontend which are identically defined in front- and backend. The grade object exactly maps the table structure of the HdM page. The response then triggers the rendering of the table and you will receive a login message. Also there is an error handling if the login failed. The table can be sorted according to the different values, the grade average and ECTS are calculated and displayed in the header of the page.
Screenshot of our frontend after successful login
Backend
Our backend consists of a Python script which is hosted in a Lambda Function with an API-Gateway to receive HTTP-Requests. The frontend sends a HTTP-Request with the user credentials in the request body to the API-Gateway. The request is then forwarded to the Lambda Function which then injects the HTTP-Request into our Python grade scraper script. The Python script then parses the request body and performs a login at the SB-Funktionen website of the HdM where all the student grades and lectures are stored.
Backend workflow
In our code example the event variable is the received HTTP-Request from the frontend. The received request body is a string, so the content of the body has to be parsed to JSON again. When there is no login data provided, the script will send a HTTP-Response with the status code 401 and a corresponding message.
In the next step our script scrapes all the data we need and parses them into a JSON format which our frontend can handle easily. This JSON data is then sent as response to the Lambda Function which will forward this response to the API-Gateway. The API-Gateway then also forwards this response back to our frontend application where the received data will be processed and displayed.
Code snippet – try-except
We also had to keep some other things in mind. For example what should happen when our backend throws an exception or the third-party-service isn’t available? In our backend we created an error handler which takes a HTTP-Status Code and an error message as parameter, converts the data in the right format for our frontend and then sends the response.
Code snippet – error handling
Our main lambda_handler function is then divided into different parts. Each part is surrounded by a try-except clause to catch exceptions. For example if the third party service is down or if there were no credentials provided by the frontend. This makes our backend more reliable and also gives the user enough feedback to know what’s going on. Since we use an external service we need to think of a solution for the case when the third party service is down, for example for maintenance reasons. A possible solution to this would be to implement a caching mechanism which we don’t provide in the current state.
CI/CD
To make our application as cloud native as possible we implemented a CI/CD pipeline in our project. This pipeline builds our Web-App as well as our Lambda Functions, tests our Python script and deploys them to AWS. For that we are using different stages (build, test, deploy) in our .gitlab-ci.yml file. The build_webapp stage first pulls a Node-image and runs a few lines of script to install all dependencies and then builds the Angular based frontend. While this part is running, a second instance is pulling an Alpine image and is also running a few lines of script to package our Lambda Function(s) into a ZIP file.
After that, the test stage is invoked to test the application before deployment. This is a crucial part in the pipeline since it can reveal mistakes that we made during development before going “live” with the application. When the tests succeed, the next stage is invoked.
In our case, we made the deployment stage manually since we didn’t want to push every small change to AWS and also the Student Accounts had some time limits that would forbid us doing that anyway. But what happens in the deploy stage is fairly simple. Like in the stages before we are pulling an image for Terraform to run the usual Terraform commands like init, validate, plan and apply. This initializes Terraform, validates our main.tf in the root of the repository, creates a plan for creating the different resources in this main.tf and finally applies it.
But what exactly is in this main.tf file? This file contains every resource we need in AWS and creates it. First of all, we declared variables for our different buckets, one for the Lambda Function and one on which the Angular app is going to be hosted at. After that, we created the S3-Bucket for the Lambda Function and uploaded the ZIP file with the function to the bucket. From there, it gets deployed to AWS Lambda. We also needed to create a role and policy to give the bucket the correct access rights to execute their task properly. After that, the S3-Bucket for the Angular app is created and the needed files are uploaded. This bucket hosts the frontend as a static website which we also configured in our main.tf to do that.
.gitlab-ci.yml file for our pipeline (1/2) .gitlab-ci.yml file for our pipeline (2/2)
Testing
Testing is one of the most important things when implementing a CI/CD pipeline and with automated deployment. When you don’t implement tests you don’t really know if your application works before deployment and after the deployment, it is too late. So implementing a stage for testing in our project was the way to go. For our Python backend we wrote some basic Unit-Tests to test functionality and also added a test stage for the backend to our CI/CD pipeline.
We also managed to write an End-To-End-Test for our frontend which checks if the Error-Snackbar is shown when the user puts in wrong credentials. The harder part in this scenario was to get it running in the CI/CD pipeline, which we unfortunatly didn’t manage to do.
What problems did we have and how did we solve them?
One of the biggest problems we encountered was due to the fact that we only had access to an AWS Student Account. It ensured that we only had restricted access to AWS. For example we needed to create different kinds of roles to deploy our Lambda Function with the correct set of rights to be executed. Due to the restrictions we were not allowed to give the roles the needed permissions which caused our CI/CD pipeline to fail and our project didn’t get fully deployed. This could only be solved by getting a “real” AWS Account which gives you all the permissions you would need.
Another problem we faced was CORS (Cross-Origin Resource Sharing). In the first steps of our development we always got a CORS-Error when our frontend was requesting the grades and lecture data from our backend service. The reason for that was because in our Python backend script we just sent back the JSON-Object containing all the data but without any HTTP-Headers to our frontend. The frontend then failed to receive the response because the URL of the API-Gateway was different from the URL that our frontend had. To fix this problem we had to set the Access-Control-Allow-Origin HTTP-Header in the response from our backend.
Code snippet – http-headers (CORS)
After that, the request worked and our frontend could receive the scraped data.
Another problem we had was to integrate our End-to-End-Test in our CI/CD-pipeline, which we unfortunately didn’t manage to fix in time. It would’ve required us to have a runner that has a browser available but we weren’t able to set that up. We managed to implement an E2E-Test which is running locally without any problems. So at least we have a bit of code quality assurance here. Having to run the tests manually isn’t what you want to do for a fully automated cloud native approach.
Conclusion
It was quite a long way from where we started, but in the end we managed to get our Web-App running on AWS as we liked. We made it a bit difficult in the beginning because we said we wanted to learn some new technologies like Python and Angular, so we first had to learn those. But we also had to learn about serverless-architecture. It is also something to look forward to working with in the future.
At the presentations we found out about AWS Amplify, which is basically a tool by AWS to get serverless Web-Apps running as fast as possible without the need of S3-Buckets. It showed us that there isn’t really the “one and only” way to get something running in the cloud. There are many possible solutions.
In our opinion we learned a lot about AWS, serverless-architecture and cloud in general. But also about developing an application where you don’t have to think about renting and maintaining a server. Maybe we can continue with this project in the near future and give the HdM SB-Funktionen a new look 🙂
Unser Ziel war es, einen Programm Updater für Entwickler zu erstellen, den diese einfach in ihre CI/CD-Pipeline integrieren können. Für die Umsetzung haben wir die IBM Cloud und eine Serverless Architektur verwendet, um eine unbegrenzte Skalierbarkeit zu erreichen. Zu den verwendeten Serverless Services zählen die Cloud Functions, DB2 und ein Object Storage.
Das Projekt besteht aus einem Uploader, mit dem der Entwickler sein Programm in den Object Storage hochladen kann. Und einem Downloader für den Benutzer, mit dem automatisch die aktuelle Version heruntergeladen wird.
Verwendung aus der Entwicklersicht:
Programm wird registriert und man bekommt die dazugehörigen API-Keys
Erstellen der Config für den Downloader
Mit dem Uploader kann das Programm hochgeladen werden, dies kann einfach in eine CI/CD Pipeline eingebunden werden
Verwendung aus der Benutzersicht:
Herunterladen des Downloaders und der Config
Starten des Downloaders
Vor Programmstart wird nach neuen Updates gesucht und diese falls vorhanden heruntergeladen
Nach dem Update wird das eigentliche Programm gestartet
Audio in the form of podcasts has become increasingly popular as a digital medium in recent years. In the U.S., one in two people have already consumed podcasts and 32% are monthly listeners. In Germany, one in five listens to a podcast at least once a month. In addition to the podcast phenomenon, which has existed and established itself in the market for some time, a new medium is now blossoming – social audio. Unlike podcasts, which are a one-way broadcast medium (they are recorded to be listened to in the future), this is real-time audio. Listeners can actively participate in the dialogue.
Social audio apps like Clubhouse seem to benefit from several factors. Headphones and earbuds have become ubiquitous; Bluetooth-based offerings, like Apple’s Airpods, have built-in microphones, making communication easy and intuitive. The podcast boom also appears to be a driving factor. Audio-based content has an enormous reach, and users are now accustomed to audio formats. Last but not least, digital voice communication has become commonplace, driven by voice messaging and phone calls via messenger platforms like Whatsapp, among others.
The Corona pandemic also seems to have played its part, as people began to experience Zoom Fatigue after only a short time. On the one hand, text messages simply don’t convey the emotions and nuances that human character requires – especially during isolation. On the other hand, Zoom calls and video calls are simply too exhausting, too demanding for us humans in the long run. For example, we mainly look at our own faces to make sure that the vegetables from lunch are not still stuck between our teeth. In general, this can be summarized under the camera effect. Many people are blocked and do not dare to speak if they feel they are being watched.
Currently, there are more than 40 companies or apps that are active in the field of “social audio”. The largest include Clubhouse, Twitter Spaces, Facebook Live Audio, Spotify Greenroom and Reddit Talk. In June 2020, Discord announced a new tagline, “Your place to talk,” in an attempt to make the service seem less gamer-centric to capitalize on people’s need to connect during the pandemic. In response to the hype around Clubhouse, a new feature has now also been implemented that further supports this new direction – Discord Stages. Other notable mentions are Fireside, Cappucino and Angle Audio. Interestingly enough Angle Audio switched to a SAaaS (Social Audio as a Service) offering recently. ProductHunt reported a significant increase in new audio products for 2020, explaining that face-to-face encounters are currently becoming more difficult to maintain due to social distancing, but social connections and exchange are needed more than ever.
Since audio as a medium is still a niche market in organizations, we at InspireNow wanted to find out whether this hype, this success in terms of audio-based content, can also find resonance in the business and professional environment. We perceive great potential, especially in terms of knowledge transfer.
That is why we have decided to delve deeper into the topic by means of an innovation project. The overall goal of this innovation project was to evaluate whether Enterprise Social Audio works, i.e. whether the added value and appeal of social audio can also be used in the context of companies, institutions and organizations. This was evaluated in the context of our existing SaaS solution InspireNow.
If you're looking for a step-by-step guide on how to include and implement
social audio in your own mobile app, I'm afraid this blog post is not for you.
Rather I'm going to give a birdseye view over the topic itself and depict the
procedure of analyzing requirements for enterprise context.
I'll describe some challenges encountered during development and
provide insights into security, GDPR and compliance concerns.
Approach
In the first step, a feasibility study was carried out on the basis of a proof of concept in order to obtain initial certainty for the technical viability.
von Benjamin Schweizer (bs103) und Max Eichinger (me110)
Abstract
Können Passwort Manager Anbieter meine Passwörter lesen? Wir wollten auf Nummer sichergehen und haben unseren Eigenen entwickelt. Dieser Artikel zeigt auf welche Schritte wir hierfür unternehmen mussten. Dabei haben wir unser Frontend mittels Flutter und unser Backend in AWS umgesetzt. Außerdem gehen wir auf IaC mittels Terraform ein. Am Ende teilen wir unsere Probleme bei der Umsetzung sowie Erweiterungsmöglichkeiten, welche in Zukunft umgesetzt werden könnten.
Mobile App
Für die Umsetzung des Frontends haben wir uns für das Flutter Framework entschieden. Durch Flutter konnten wir eine gemeinsame Codebasis für alle unsere Zielplattformen (iOS, Android) verwenden. Daher konnten neue Features schnell implementiert und Änderungen konnten sofort auf unterschiedlichen Geräten getestet werden. Außerdem wurde durch einen Integrationstest sichergestellt, dass die App auf beiden Plattformen fehlerfrei läuft.
Die App bietet eine einfache Benutzeroberfläche, in welcher folgende Aktionen möglich sind:
Login und Registrierung eines Nutzers
Hinzufügen und Löschen eines Passworts
Ändern von Passwörtern
Diese Funktionen sind in folgenden Benutzeroberflächen abgebildet
Die Oberfläche ist auf Android und iOS identisch.
Architektur
Grundlegend ist unsere Architektur in Frontend und Backend aufgeteilt. Dabei wird, wie bereits erwähnt das Frontend mit Flutter umgesetzt und das Backend über die AWS-Cloud realisiert. Alle Anfragen an das Backend werden mit HTTP-Requests an das API-Gateway-Service gesendet. Die Anfragen der Nutzer müssen einen validen JWT (JSON Web Token) enthalten. Diesen Session Token bekommt der Nutzer bei erfolgreichem Log-in über den Cognito-Service. Durch den Token kann in den Lambda Funktionen sichergestellt werden, das Nutzer nur Daten ändern können, für die Sie eine Berechtigung haben. Die Lambda Funktionen evaluieren die Anfragen und Ändern die Passwortdaten im DynamoDB-Service. Alle Passwortdaten, welche an das Backend übertragen werden, sind bereits lokal vom Client verschlüsselt worden, um Missbrauch zu verhindern.
AWS Services
Da wir dieses Semester bereits in einem anderen Studienfach Erfahrung mit AWS in Verbindung mit IoT sammeln konnten, war AWS unsere erste Wahl. Außerdem waren wir uns am Anfang des Projektes sicher, das AWS alle unsere Anforderungen erfüllt.
DynamoDB AWS DynamoDB ist ein vollständig verwalteter NoSQL-Datenbankservice. Dort werden alle Passwortdaten gespeichert. Um schnelle Query Anfragen zu ermöglichen, ist unsere Tabelle in folgende Felder aufgeteilt:
Partitionsschlüssel: User_Id (Eine eindeutige ID für jeden Nutzer)
Sortierschlüssel: PasswordName
Passwort (in verschlüsselter Form)
Beschreibung
API-Gateway
Um HTTP-Anfragen an unsere Lambda Funktionen weiterzuleiten, nutzen wir den API-Gateway-Service. Dieser validiert Nutzeranfragen auf erforderliche Parameter und lehnt bei fehlenden Daten die Anfrage ab. Außerdem wird hier der Token mithilfe von Cognito geprüft. Wir nutzen 3 verschiedene HTTP-Methoden, um unsere Client-Anfragen zu bearbeiten. Zudem sind alle Methoden über einen API-Key gesichert.
Die DELETE Methode löscht ein Password von einem Nutzer.
Die GET Methode gibt alle Passwörter eines Nutzers zurück.
Die PUT Methode erstellt oder überschreibt ein Passwort.
Lambda Innerhalb jeder unserer Lambda Funktionen haben wir Zugriff auf den Cognito Authorizer. Dieser bietet uns die Möglichkeit, direkt auf die Daten (User_Id, Username etc.) des Nutzers zuzugreifen, welcher den Request geschickt hat.
PUT Methode:
In der PUT Methode werden neue Passwörter gespeichert oder schon vorhandene überschrieben.
Durch das in API-Gateway angelegte JSON-Schema können wir prüfen, ob der HTTP-Body die erforderlichen Parameter enthält. Trotzdem kann es sein, dass vom Nutzer ein leerer String (“”) geschickt wird. Dies ist der erste Validierungsschritt, welcher in der Lambda Funktion ausgeführt wird.
Mithilfe der User_Id und der Passwortdaten können wir nun einen neuen Eintrag in DynamoDB erstellen. Falls der Passwortname bereits in der Datenbank steht, wird das Passwort überschrieben.
GET Methode:
Die GET Methode liefert alle Passwörter eines Nutzers zurück.
Durch die User_Id können wir an DynamoDB eine Query schicken, welche uns alle Daten von einem einzigen Nutzer zurückliefert. Dadurch wird sichergestellt, dass ein Nutzer nur auf seine eigenen Passwortdaten zugriff hat.
DELETE Methode:
Die DETELE Methode löscht ein Passwort eines Nutzers.
Auch für diese Methode existiert in API-Gateway ein JSON-Schema, welches den Body validiert.
Mithilfe des Authorizers und des Passwortnamens können wir nun für diesen Nutzer das Passwort löschen. Dafür müssen wir den Partitionsschlüssel (User_Id) und den Sortierschlüssel (PasswordName) angeben und diese Anfrage an DynamoDB senden.
Verschlüsselung
Um sicherzustellen, dass alle Passwörter sicher sind und nur von dem Nutzer gelesen werden können, welcher die Passwörter auch angelegt hat, nutzen wir lokale Verschlüsselung. Damit der Nutzer die App auf mehreren Geräten gleichzeitig verwenden kann, muss es gemeinsamen Schlüssel geben.
Dieser Schlüssel basiert bei uns auf dem Login-Passwort. Dieser Schlüssel wird bei erfolgreichem Einloggen auf dem Gerät in einem sicheren Bereich gespeichert.
Beim Ver- und Entschlüsseln wird ein AES Algorithmus verwendet. Die verschlüsselten Bytes müssen danach nur noch zu einem String encodiert werden, damit man das Passwort leichter zu einem JSON serialisieren kann.
Testing in Flutter
Um alle Funktionen in Flutter leicht testen zu können, haben wir uns für einen Integrationstest entschieden. Damit können wir herausfinden, ob alle wichtigen Funktionen richtig funktionieren. Unsere Hauptfunktionen, welche wir getestet haben sind:
Login eines Nutzers
Hinzufügen und Löschen eines Passworts
Ändern von Passwörtern
Ver- und Entschlüsselung
Die Login Prozedur prüft ob die App die richtigen Daten anzeigt, sobald der Nutzer eingeloggt wurde.
Terraform
Wir haben in unserem Projekt Terraform eingesetzt. In unser Ziel war es hierbei, das jeder einfach dieses Projekt bei sich zu Hause nachbilden kann. Dadurch war es aber auch möglich, schnell den AWS Account oder die Region zu ändern und sämtliche Infrastruktur Änderungen zu versionieren.
main.tf
variables.tf
dynamodb.tf
Main und Cognito
Grundsätzlich haben wir unseren Terraform Code in mehrere Files aufgeteilt. Dabei werden in der main.tf vor allem die Standard Terraform Parameter gesetzt und zusätzlich wird hier noch der Cognito Service aufgesetzt.
Variablen
Im variable.tf File werden für Terraform die AWS AccountID und die Region festgelegt. Diese Daten werden von Terraform benötigt, um die richtigen Account und Region für die Cloud Infrastruktur zu finden.
DynamoDB
Dienst und die Tabellen dem dynamodb.tf File werden, wie zu erwarten, alle DynamoDB Einstellungen übernommen. Hier wird also der AWS Dienst und die Tabellen Felder angelegt.
API Gateway in Terraform
Methoden für API Gateway in Terraform
Lambda API Verbindung
API Methode Response
API Deployment in AWS
API Models und Authorizer
API Gateway Terraform Code
API Gateway
Im api.tf wird zunächst der normale AWS API Gateway Dienst eingestellt. Danach werden die Methoden der API definiert. Für jede Methode muss zudem angegeben werden welche Lambda Funktion ausgeführt werden soll, zusätzlich kann hier ein Template für die Request hinzugefügt werden. Dadurch wird unter anderem auch der Lambda Code vereinfacht. Jetzt wo in den Methoden alles Wichtige eingestellt ist, wird im tf File die Response erstellt. Als Nächstes wird in Terraform definiert, wie die API bereitgestellt wird. Dadurch spart der Entwickler die Zeit später in AWS API Gateway den Deploy Butten von Hand zu drücken. Am Ende vom api.tf File wird noch für jede API Methode ein Model / Schema für die JSON Daten angeben. Das hat den Vorteil das Request an die API, ohne diese benötigten Daten, automatisch abgelehnt werden. Und zum Schluss wird noch der Authorizer von Cognito für die API richtig eingerichtet.
Lambda in Terraform
Policy für Lambda
Permissions für Lambda
AWS Lambda Terraform Code
Lambda
Alle Lambda Funktionen müssen lokal gespeichert sein. Im lambda.tf File wird dann der Pfad zur Funktion definiert, beim Ausführen von Terraform wird dann ein zip File von jeder Funktion erstellt und in AWS Lambda hochgeladen. Danach wird werden noch die Policies für das Logging mit Cloudwatch und die Access Rechte für DynamoDB geben. Am Ende werden noch Permissions für API Gateway und Cognito an die richtigen Lambda Funktionen verteilt.
Probleme
Jedes Projekt hat seine Probleme, so auch unseres. Direkt am Anfang hatten wir viel mit AWS zu kämpfen, den wenn man für die Cloud entwickelt ist Debugging nicht mehr so einfach wie in einer IDE. Man kann dadurch kaum mehr nachvollziehen, was das AWS Setup oder der Lambda Code macht. Am Ende konnten wir das Problem über den Service Cloudwatch lösen. Hier werden alle Aktion geloggt, dadurch können Fehler schnell gefunden und gelöst werden.
Weitere Schwierigkeiten sind beim Arbeiten mit Terraform aufgetaucht. So sollte Terraform eigentlich von alleine alle Dienste in der richtigen Reihenfolge anlegen. Leider geht dies oft schief, und wir mussten im Terraform File von Hand mittels depens_on, die Reihenfolge einstellen. Ein weiteres Problem war, dass AWS beim Erstellen von Services viele Optionen im Hintergrund von alleine einstellt. Später mit Terraform raus zu finden, welche Einstellungen man jetzt genau braucht, war nur über das ausführliche Lesen der Dokumentation möglich.
Beim Arbeiten mit den AWS Dienst Cognito hatten wir Schwierigkeiten mit dem Bestätigen eines Nutzers. Denn Cognito legt zwar alleine alle Nutzer an, aber die Bestätigung des Accounts muss man von Hand gemacht werden. Jedoch konnten wir dieses Problem schnell über eine eigene Lambda Funktion lösen, welche automatisch jeden Nutzer verifiziert.
Erweiterungen
Das Projekt wurde von Anfang an mit dem Zeitlimit eines Semesters geplant. Jedoch könnte man mit weiterem zeitlichen Investment noch viele wichtige Features umsetzen:
So funktioniert Flutter auch im Web, leider haben wir innerhalb des Codes viele Abhängigkeiten zu iOS / Android. Jedoch wäre der Aufwand, die App auch als Web App laufen zu lassen, überschaubar.
Momentan sind die Passwörter in der Detailansicht noch sichtbar, in Zukunft sollte man diese verbergen und ein Kopierbutton hinzufügen. So könnte man die Passwörter noch besser schützen.
Zudem könnte man Power-Usern das Leben vereinfachen, in dem man eine Passwortsuche einbauen würde, so könnten Nutzer aus einem Berg von Passwörtern schnell das Richtige finden.
Ein weiter Feature wäre das Ändern des Masterpassworts, hier wäre aber der Aufwand sehr groß. Da jedes Passwort des Nutzers in der Datenbank mittels des Masterpassworts verschlüsselt ist, müsste jedes Passwort neu verschlüsselt werden.
Lessons Learned
Wie im Projekt bereits zu erkennen ist, haben wir viel Erfahrung mit den AWS Diensten: IAM, Cognito, Lambda, API Gateway, Cloudwatch und DynamoDB, sammeln können. Dank Terraform ist uns auch das Konzept der IaC (Infrastructure as Code) jetzt viel greifbarer geworden, zusätzlich hat uns Terraform fast schon gezwungen, von jedem benutztem AWS Service, die wichtigste Einstellung zu kennen. Außerdem konnten wir erste Kenntnisse in der App Entwicklung sammeln. Zuletzt haben wir unser Wissen im Bereich Testing um das Thema Integrations Tests erweitert.
You must be logged in to post a comment.