Unternehmen Qualitätssicherung Entwicklung XML

profi.com LAB - Ein Backend für alle Fälle!

von Jean-Lukas Wagner

Der dritte Teil unserer "profi.com LAB-Serie" widmet sich den eingebundenen Statistiken. Jean Lukas erklärt, woher die Daten kommen, wie sie mitttels einer JSON-API und Python eingebunden werden und wie das Backend diese Daten individuell verarbeiten kann.

Ich bin Jean Lukas und habe im September 2020 als Werkstudent bei der profi.com AG angefangen. Unsere neue Landingpage zeigt motivierende Statistiken aus dem LAB, wobei die Daten aus unterschiedlichen Quellen stammen. Dafür braucht es ein flexibles Backend, welches die Daten der verschiedenen Dienste sammelt, aufbereitet und über eine REST-API zur Verfügung stellt. Eine API ist eine definierte Schnittstelle, die es Programmen erlaubt, miteinander zu interagieren. Der Zusatz REST- ist ein Überbegriff für alle API‘s, die auf standardisierten Verfahren wie HTTP/S, JSON oder XML beruhen. Ich bin für das Backend verantwortlich und möchte in diesem Blogbeitrag meine Erfahrungen beim Aufbau einer JSON-API mit Python – Flask teilen.

Danach sollt ihr einen kleinen Überblick über die Programmstruktur und den Datenfluss im Backend bekommen. Als Letztes will ich euch an meinen Erfahrungen und Gefühlen als Werkstudent bei der profi.com teilhaben lassen.

Für alle, die sich für das LAB generell interessieren, haben Daniel und Florian hier einen Blogbeitrag geschrieben. Sollte euch das Frontend der LAB-Landingpage interessieren oder wenn ihr die Meinung eines anderen Werkstudenten bei der profi.com hören wollt, dann seht euch Olivers Artikel hier an.

Statistiken – Unsere täglichen Freunde

Statistiken begleiten uns überall. Ob wir wollen oder nicht, wir Menschen des 21. Jahrhunderts verwenden Statistiken, um uns zu informieren, um zu vergleichen oder um zu prahlen. Wer von uns hat seit März 2020 sich nicht regelmäßig den Inzidenzwert für seine Region angeschaut und gehofft, dass dieser sinkt, aber zumindest nicht steigt?

Dabei betrachten wir staunend die neuesten Spielereien und kreativen Ideen der Frontendentwickler (die leisten auch wirklich super Arbeit!) und vergessen dabei, dass hinter der schönen Fassade einer Statistik immer auch ein starkes Backend liegt. Zumindest ging es mir so, bevor ich mich zum ersten Mal in meinem Leben mit der Thematik eines Backends beschäftigt habe.

Statistiken auf der Lab-Landing-Page sollen übersichtlich und auf das Mehrheitsinteresse der Anwender zugeschnitten sein. Die Lab-Landing-Page soll primär eine Übersicht über die internen Services der profi.com bieten. Kleinere Statistiken sollen z.B. über den Anteil der verwendeten Programmiersprachen im Git der profi.com informieren oder einen Vergleich der Anzahl an Containern und VMs innerhalb der profi.com bieten. Für detailreichere Servicestatistiken sollen Links zu Dashboards bereitgestellt werden.


Abbildung 1: Die Statistik zeigt die Anteile der verwendeten Sprachen in Git der profi.com. In diesem Artikel soll es nicht ums Frontenddesign gehen, sondern darum wie das Backend an die Daten für eine Statistik kommt.  

Wie komme ich an die Daten für Statistiken?

Im Idealfall sind die Daten für die Statistiken in einer zentralen Datenbank in einem einheitlichen Format gespeichert. In dieser idealen Welt muss das Backend nur noch die Daten suchen und für das Frontend bereitstellen. Bei der LAB-Landingpage ist dies nicht der Fall und das Backend muss in der Lage sein, die Daten in verschiedensten Formaten zu empfangen. Die Daten werden über die Schnittstellen der verschiedenen Services abgerufen, die alle etwas anders sind, denn es gibt zwar Best Practices für API‘s aber keine Normen. Anschließend müssen die Daten gefiltert und umformatiert werden. Für manche Statistiken müssen die Daten gemittelt werden. Andere Datensätze sollen später in Prozent dargestellt werden oder bedürfen einer anderen mathematischen Überarbeitung. Beim Projekt der Lab Landing-Page war es eine Vorgabe, das Backend möglichst schlank zu halten. Explizit soll es keine Datenbank geben. Sämtliche Daten werden lediglich im Cache zwischengespeichert. Ältere Datensätze können nach der Aktualisierung nicht mehr rekonstruiert werden. Die Daten werden vom Backend im JSON-Format bereitgestellt. Das Frontend kann die Daten nach Bedarf abrufen. Alle sechs Stunden wird der Datensatz aktualisiert.

Aber warum in Python und warum Flask?

Wer bereits Olivers Teil dieser Artikelserie gelesen hat, dürfte wissen, dass das Frontend in JavaScript geschrieben ist. Die für das Backend eingesetzte Sprache kann separat von der im Frontend verwendeten Sprache gewählt werden. Wichtig ist nur, dass beide Sprachen eine gemeinsame Schnittstelle haben. In unserem Fall ist dies mit JSON gegeben. Ich durfte aussuchen, in welcher Sprache ich das Backend schreiben möchte und entschied mich für Python. Obwohl es gute Argumente für Python gibt, wie die unglaubliche Flexibilität und große Auswahl an Tutorials im Internet, war der ausschlaggebende Faktor, dass ich bereits Erfahrung mit Python habe. Da dies mein erstes Projekt in der profi.com und so vieles neu für mich war, empfand ich es als wichtig, die Programmiersprache gut zu kennen. Letztlich wären alle Programmiersprachen, die im Backend eingesetzt werden können, für die LAB-Landingpage geeignet gewesen.

Die Entscheidung für das richtige Framework entstand nach ausgiebiger Recherche. Es sollte ein Framework werden, welches leichtgewichtig ist und gleichzeitig viele Online-Ressourcen bietet. Die Hauptaufgabe des Backends ist zwar, eine REST-API für das Frontend bereitzustellen, dennoch wollten wir uns Flexibilität bewahren und kein reines API-Framework verwenden. Am Ende fiel die Entscheidung auf Flask. Flask ist ein sehr schlankes Webframework für Websites. Da es die gängigen Web-Technologien unterstützt, eignet es sich auch, um REST-API‘s zu programmieren.

How to REST-API mit Flask

Ich möchte euch hier kurz ein Minimalbeispiel für eine simple JSON-API zeigen. Als Erstes muss Flask und die Funktion „jsonfiy“ importiert werden. Danach kann die Flaskapp gestartet werden.

from flask import Flask, jsonify
app = Flask(__name__)

Im zweiten Schritt erstellt ihr euch ein Dictionary:

developers = {
    "Oliver": {
        "Lieblings_Spielkarte": {
            "Farbe": "Herz",
            "Symbol": "König"},
        "Kaffee": {
            "trinkt_Kaffee": True,
            "Anzahl_Zuckerwürfel": 5,
            "Milch": True},
        "Aufgabengebiet": "Frontend"},
    "Jean_Lukas": {
        "Lieblings_Spielkarte": {
            "Farbe": "Kreuz",
            "Symbol": "Sieben"},
        "Kaffee": {
            "trinkt_Kaffee": False},
        "Aufgabengebiet": "Backend"}}

Erstellt die Route, unter der ihr die API aufrufen wollt. In der Funktion dieser Route wird die Funktion „jsonify“ aufgerufen. Mit „jsonify“ könnt ihr ein Dictionary ins JSON-Format überführen. Als Argument wird das zuvor erstellte Dictionary mitgegeben:

@app.route("/")
def main_page():
    return jsonify(developers)

Als letztes, damit Flask gestartet wird, sobald ihr Eure Anwendung ausführt:

if __name__ == "__main__":
    app.run()

Ihr seht, es ist sehr leicht, eine API mit Flask bereitzustellen. Nach dem Ausführen eurer Anwendung könnt ihr euch das Resultat unter http://127.0.0.1:5000/ in einem Browser eurer Wahl anschauen. Ich persönlich empfehle Firefox aufgrund der übersichtlichen Darstellung von JSON-Files. 


Abbildung 2: Strukturierte Darstellung es JSON-Files in Mozilla Firefox

In Python braucht ihr nur ein Dictionary erzeugen und könnt dieses mit einer Flask-Funktion in JSON überführen. Das reduziert den Schwierigkeitsgrad einer REST-API auf die Erstellung eines Dictionary. Der weitaus komplexere Teil ist das reibungslose Einsammeln der Datensätze aus verschiedenen Quellen bei einer möglichst schlanken und effizienten Code-Struktur.

Datenfluss im Backend

Für den Datenfluss im Backend habe ich die Klasse StatisticBuilder.py geschrieben. Diese Klasse generiert ein Dictionary aus den Daten eines Service. Dafür benötigt der Builder drei Objekte. Er braucht einen Client zum Service, von dem die Daten abgeholt werden sollen. In diesem Client sind die Verbindungscredentials hinterlegt und die Datenabfrage erfolgt darüber. Die Daten werden vom Builder weitergeleitet an das Funktions-Objekt.

Hier ist die individuelle Logik enthalten, die sich je nach Service und angestrebter Statistik ändert. Ursprünglich war hier geplant, eine Unterscheidung in Basic-Funktionen und Special-Funktionen durchzuführen. Die Basic-Funktion sollten möglichst allgemein gehalten und für viele Use Cases anwendbar sein, während die Special-Funktionen individuelle Maßanfertigungen werden sollten. Fun Fact am Rande: Unsere Statistiken wurden am Ende so individuell, dass es gar keine Basic-Funktionen mehr gibt.

Das dritte Objekt ist eine settings.yml. Hier ist die Steuerungslogik für die Builder-Klasse implementiert. Welche Datensätze über den Client geholt werden und an welche Funktionen diese übergeben werden sollen, kann hier festgelegt werden.


Abbildung 3: Schematische Darstellung des Datenflusses im Backend

Mit dieser Logik wird die Modularität von Klassen effektiv ausgenutzt. Sämtliche Logik, die immer identisch ist, ist in der Builder Klasse enthalten. Wenn Statistiken von einem neuen Service erstellt werden sollen, muss nur der richtige Client gewählt (oder neu geschrieben) werden. Im Anschluss kann direkt mit der Verarbeitung der gewonnenen Daten in einer neuen Function.py begonnen werden. Diese modifiziert das Dictionary so, wie es an die API weitergegeben werden soll. Letzteres muss nur noch - wie eingangs beschrieben - in eine JSON umgewandelt werden und kann bei Aufruf der entsprechenden URL abgerufen werden.

Mit der beschriebenen Struktur ist das Backend in der Lage, Informationen aus verschiedenen Quellen individuell zu bearbeiten. Gleichzeitig soll mit der Struktur Redundanz reduziert sowie die Modularität und Erweiterbarkeit erhöht werden.

Die profi.com und Ich als Werkstudent

Mein Arbeitsbeginn viel mit dem Projektstart des Backends für die LAB-Landingpage zusammen. Der Anfang des Projektes war vor allem von Recherche und Abstimmung zusammen mit Oliver gezeichnet. Das Ziel war zwar definiert, aber die verwendeten Technologien, die konkreten Statistiken und die Aufteilung der Arbeit lagen komplett in unseren Händen. Im Rückblick würde ich meinen Projektstart als “smooth” beschreiben. Als ich damals im Kickoff für das neue Projekt saß, war dies allerdings alles andere als ersichtlich.

Ich habe keinen Informatik- sondern einen Elektrotechnikstudium-Background. Wir programmieren zwar auch, allerdings ist die dort verwendete Fachsprache nicht so ausgeprägt und differenzierend wie bei den Informatikern. Dementsprechend musste ich anfangs häufiger Begriffe nachschlagen oder diskret im bidirektionalen Kontakt mit meinen Kolleg:innen erfragen. Diese konnten mir immer sehr gut weiterhelfen und hatten ein gutes Gespür dafür, wo es gerade beim Verständnis hakt.

Die profi.com ist nicht mein erster Arbeitgeber. Allerdings wurde mir bislang nirgends so viel Eigenverantwortung gegeben wie hier. Anfangs hat mich das sehr überrascht und überfordert. Ich rechnete damit, Aufgaben mit klaren und engen Grenzen zu bekommen, stattdessen wurde mir ein Projekt übertragen, dessen Dimensionen ich mit meiner Erfahrung noch nicht abschätzen konnte und bei dem ich mir am Anfang nicht ganz sicher war, ob ich den Anforderungen gewachsen bin. Man hat mich sprichwörtlich ins „kalte Wasser“ geworfen. Ich persönlich muss sagen, dass mir das sehr gefallen hat. Auch standen meine Betreuer für Rückfragen stets zur Verfügung und gaben mir immer das Gefühl einzugreifen, wenn das Projekt in Schwierigkeiten geraten würde.

Wir hatten auch das Glück, in jenem Zeitfenster im Spätsommer 2020 anzufangen, in dem Präsenzarbeit noch möglich war. Bereits zwei Monate später ging dies nicht mehr. Praktischerweise ist es in der profi.com bereits vor Corona möglich gewesen, remote zu arbeiten. Auch wir Werkstudenten bei der profi.com haben einen eigenen Arbeitslaptop. So konnten wir ohne Probleme ins Homeoffice wechseln.

Das Ritual des kollegialen Mittagessens gab es somit für mich nicht lange. Die vielen geplanten Präsenzevents, wie eine Weihnachtsfeier, Teamessen und anderen Social Events konnte ich leider nur den Erzählungen meiner Kolleg:innen entnehmen beziehungsweise den abgesagten Terminen in meinem Outlook-Kalender. Generell ist das Arbeitsumfeld bei der profi.com sehr angenehm und kollegial zu beschreiben. Von meinen Vorgesetzten gab es keine unerfüllbaren Erwartungen und der einzige Zeitstress den es gab, war meinem eigenen Ehrgeiz geschuldet.

Unsere Vorgesetzten haben sich zufrieden mit unserer Arbeit gezeigt. Für Oliver und mich geht es weiter bei der profi.com. Wir haben bereits ein neues, herausforderndes Projekt, wo wir einen Automaten in Ansible entwickeln, der virtuelle Maschinen bereitstellen kann.

Aktuell freue ich mich auf die nahende Präsenzarbeit und hoffe, mit meinen Kolleg:innen bald auf den Feierabend anstoßen zu können.

Autor

Björn FröbeMarketing Manager
Björn Fröbe

Tel.:+49 351 4400 8292
Mobil:+49 171 9364 362
E-Mail:bfroebe@proficom.de

XING
LinkedIn