Wäre es nicht schön, alle zum Programmieren zu befähigen?
Wir leben in einem Zeitalter rasanten informationstechnologischen Wandels. Computer sind inzwischen einer der Mittelpunkte des Lebens von Vielen. Mit ihrer weiteren Verbreitung steigt auch der Bedarf an für sie entwickelten, auf Bedürfnisse zugeschnittenen Anwendungen. Sowohl im privaten als auch im kommerziellen Bereich. Durch den steigenden Bedarf an Anwendungen steigt auch der Bedarf derer, die zur Erstellung dieser benötigt werden. Obwohl mit den Computern auch das Programmieren inzwischen in der Mitte der Gesellschaft angekommen ist und viele es sogar in ihrer Freizeit als Hobby betreiben, fehlt es auf dem Arbeitsmarkt massiv an ausgebildeten Entwicklern. Es liegt deshalb nahe, nach Möglichkeiten zu suchen, jeden des Programmierens zu ermächtigen und somit den Markt potentieller Arbeitnehmer zu erweitern. In der Industrie ist es inzwischen gängige Praxis auch nicht professionell ausgebildete Entwickler gezielt auf ihr Anwendungsgebiet bzw. die im Umgang mit den dafür nötigen Entwicklungstools zu schulen und in Projekten einzusetzen. Der limitierende Faktor ist also nur die fehlende Kenntnis einer Programmiersprache. Dem kann mit Low-Code entgegengewirkt werden.
Ziel der Bachelorarbeit war es, eine beispielhafte, schlanke und auf der Low Code-Idee basierende Applikation zum Test der Hardware eines über RS232 angeschlossen Geräts zu erstellen. Aber was ist nun Low Code genau?
Definition Low Code
Literatur und Experten sind sich einig, dass Low-Code ein massiver Trend der Zukunft sein wird. Dennoch existiert in der Fachliteratur keine klare Definition dessen, was Low-Code genau ist. Vielmehr wird Low-Code eingeordnet aufgrund dessen, was die momentan auf dem Markt befindlichen Low-Code-Entwicklungs-Plattformen bieten. Eine für uns völlig ausreichende und sehr klare Zusammenfassung findet sich in der Arbeit über die Charakteristiken und Herausforderungen der Low-Code-Programmierung geschrieben von Yajing Luo u. a. Die zwei Kerncharakteristiken sind: Zum einen die nicht mehr nötige Kenntnis von Sourcecode und zum anderen der Begriff Drag and Drop, also das Realisieren eines Programms durch simples Zusammenziehen grafischer Einheiten, sind. Im Zuge dieser Bachelorarbeit sind genau diese zwei Kernpunkte umgesetzt worden.
Low Code Frameworks
Wie in der Arbeit von Yajing Luo u. a. dargestellt wurde, ist die Wahl der richtigen Plattform von großer Wichtigkeit. So kann Low-Code sowohl in der Entwicklung vorteilhaft sein, wenn es angemessen genutzt wird, andernfalls jedoch auch Einschränkungen oder Herausforderungen mit sich bringen. Da kommerzielle Lösungen meist keinen Zugriff auf ihren Programmcode zulassen, bringt die Entscheidung für eine dieser Plattformen die Gefahr einer zukünftigen Abhängigkeit von diesem einen Hersteller mit sich. Deshalb wurden im Rahmen dieser Arbeit lediglich Open Source-Lösungen in Betracht gezogen.
Blockly
Blockly ist ein von Google entwickeltes Javascript-Framework zur Erstellung von blockbasierten Programmiersprachen, das seit Mai 2012 existiert und seitdem stetig weiterentwickelt wird. Blockly ähnelt prinzipiell der graphischen Programmierung in Scratch, hat jedoch eine insgesamt professionellere, an eine erwachsene Zielgruppe gerichtete Aufmachung. Es arbeitet zu einhundert Prozent clientseitig in allen gängigen Web-Browsern. Durch ein aktiv bei Google arbeitendes Team ist sichergestellt, dass etwaige Bugs schnell behoben werden und die Code-Basis im Allgemeinen sehr gut gewartet ist. Auch existiert eine große Blockly-Community mit einem aktiven Forum, in dem bei auftretenden Problemen entweder schon gefundene Lösungen existieren oder schnell Hilfe gefunden werden kann. Für Blockly existieren bereits Code-Generatoren für die Programmiersprachen JavaScript, Python, PHP, Lua und Dart. Diese bieten eine grundlegende Funktionalität und können von Entwicklern in eigenen Projekten um neue Blöcke erweitert werden. Blockly wird in hunderten, meist auf das Lernen des Programmierens bezogenen Projekten genutzt.
Django
Django wird im Python-Wiki als Full-Stack Framework für Web Development gelistet. Es wird als umfassendes Framework beworben, bei dem so gut wie alle nötigen Funktionalitäten schon integriert sind. Umfassend bedeutet in Djangos Fall auch, dass sich die Entwickler in sehr eng gesteckten Rahmen bewegen müssen. Das bringt anfangs eine umfangreiche Einarbeitungszeit mit sich, gleichzeitig jedoch auch die Möglichkeit, als eingearbeiteter Entwickler Apps und Funktionalitäten mit relativ geringen zeitlichen und konzeptuellen Aufwand zu realisieren. Django erzeugt bei Projekterstellung automatisch eine komplexe Ordner- und Dateistruktur, um Konfigurationen des Projekts klar zu strukturieren und voneinander zu trennen. Der Aufbau von Websites wird bei Django mithilfe von Templates definiert. Durch die von Django bereitgestellte Template-Sprache können die statischen Teile einer HTML-Datei durch Variablen und Tags dynamisch mit Daten befüllt werden. Die Daten werden dabei im Voraus geprüft ob sie Zeichen enthalten, die auf potentiell gefährlichen HTML-Code hindeuten und falls ja, diese durch andere Repräsentationen ersetzt. Durch diesen Aufbau entsteht ein insgesamt sehr sauberer Code – nach dem Schema ”Konvention geht vor Konfiguration ”. Mit dem engen Rahmen, den das Framework vorgibt und der einheitlichen Basis kommt auch größere Sicherheit mit sich. Das macht Django zu einem Framework, das bedenkenlos in einer produktiven Arbeitsumgebung genutzt werden kann.
Ziele und Umsetzung der Bachelorarbeit
Die Bachelorarbeit bestand aus drei Zielen:
- Die Bereitstellung von Blöcken, die komplexe Algorithmen abstrahieren,
- die Erstellung und Ausführung von Pytests und
- die Möglichkeit, eine serielle Kommunikation mittels Pyserial aufzubauen.
Das Ganze wurde als Webanwendung realisiert. Ihre Oberfläche ist in mehrere Abschnitte unterteilt. Sie wird durch Dateien strukturiert, die in der Django-Template-Language geschrieben und strukturell HTML-Dateien sehr ähnlich sind. Ihr Style wird durch statische CSS-Dateien konfiguriert. Die Anzeige wird letztendlich durch Django dynamisch mit Daten befüllt. Die Oberfläche ist in zwei Hauptteile gegliedert und mit einer exemplarischen Erzeugung von zwei Tests in Abb. 1 zu sehen.
Abbildung 1: Blockly_GUI.png: Die Oberfläche der Webanwendung, Blockly-Arbeitsbereich rechts, erzeugter Code links, Rückgabe der Test- und Skriptläufe links unten
Der größte und wichtigste Teil der Anwendung ist der Blockly-Arbeitsbereich auf der rechten Seite. In ihn werden die Blöcke mittels Drag and Drop eingefügt und angeordnet, um die gewünschte Funktionalität zu realisieren. Der gesamte Aufbau des Bereichs wird durch Blockly definiert. Der Teil auf der linken Seite enthält den durch die Blöcke definierten und von Blockly erzeugten Code. Ebenfalls auf der linken Seite befinden sich Buttons, um den erzeugten Python-Code auf das Client-System herunterzuladen, ein erstelltes Skript in Echtzeit auf dem Server auszuführen oder einen erstellten Pytest ebenfalls in Echtzeit auf dem Server-System zu evaluieren. Die Rückgabe eines solchen serverseitigen Skript- bzw. Testlaufes wird unter den Buttons angezeigt. Als optischer Teiler dient die Blockly-Toolbox, die gleichzeitig Funktionalität zur Verfügung stellt. Sie enthält, in Kategorien unterteilt, alle verfügbaren Blöcke.
Blockdefinition und Aufbau
Der Aufbau der Blöcke wird in JSON definiert. Als Beispielist nachfolgend die JSON-Definition und die daraus resultierende Oberfläche eines Blocks für die Definition eines Pytests(Listing 3.1, Abb. 2)
Listing 1: Die JSON-Definition eines Blocks zur Erstellung eines Pytests
const pytesttest = { ” type ” : ” pytesttest ” , ”message0 ” : ”Erzeuge einen Test mit dem Namen : %1 und folgendem Ablauf : %2 %3”, ” args0 ” : [ { ” type ” : ” fieldinput ” , ”name ” : ” testname ” , ” text ” : ” testdefault ” } ,{ ” type ” : ”input dummy” } , { ” type ” : ” input statement ” , ”name ” : ” testprocedure ” } ] , ” inputs Inline ” : false , ” colour ” : ”#56d415 ” , ” tooltip ” : ”” , ” helpUrl ” : ”” }
Abbildung 2: Die Oberfläche des Blocks zur Erstellung eines Pytests
Die dabei wichtigsten Elemente sind type
und die jeweils zusammengehörigen nummerierten
message
-Strings und args
-Arrays. Dabei wird der type
als Key eines Blockly-internen
Dictionaries genutzt, um sich später im Codegenerator sowie der Toolbox wieder auf den Block
beziehen zu können und ihm codeerzeugende Funktionalität zuzuordnen bzw. ihn dem Nutzer
verfügbar zu machen.
Codegenerator
Bei Low-Code Plattformen ist neben dem übersichtlichen Aufbau der Blöcke die hinterliegende, für den Benutzer unsichtbare, Codegenerierung essenziell. Bei Blockly erfolgt sie mithilfe eines Dictionarys innerhalb des eingebauten Generators. Diesem Dictionary müssen eigene Implementierungen hinzugefügt werden. Als Key dieses Dictionarys fungiert der eineindeutige, bei der Blockdefinition gewählte type (eine Art Name) des Blocks. Verwiesen wird auf eine codeerzeugende Funktion, die für jeden Block individuell ist. Im Laufe der Funktion werden alle Eingaben des Blocks, also die zuvor genannten Fields und Inputs, ausgewertet und die eigene Programmierlogik festgelegt. Für Inputs gilt weiter die Unterscheidung zwischen Statements und Values, sowohl für die Eingaben des Blocks als auch für seine Rückgaben.
Sollten Statements in andere Statements eingebunden werden, wie beispielsweise bei Schleifen oder Verzweigungen, so werden sie lediglich eingerückt, um weiterhin syntaktisch korrekten und gut lesbaren Code zu erzeugen. Diese Funktionalität ist dabei schon im eingebauten Generator gegeben.
Abstraktion von Algorithmen und Utility-Blöcke
Dieser Fall tritt bei der Abstraktion komplizierter Algorithmen ein, da viele Endnutzer von Programmen nicht an der Art und Weise wie etwas passiert interessiert sind, sondern lediglich an der Tatsache, dass etwas passiert. Dieser Effekt ist natürlich noch verstärkt, wenn keine tiefe Kenntnis der Programmierung besteht. Es wird deshalb versucht die komplizierte Logik weitestgehend vor dem Nutzer zu verbergen und ihm lediglich einen fertigen, Funktionalität zur Verfügung stellenden Block zu präsentieren. Als Anschauungsobjekte wurde der Bubblesort-Algorithmus ausgewählt. Für den Endnutzer zählt, dass er einen Block hinzufügt und dieser sortiert. Umgesetzt wird das mit einer Definitions-Map. Das ist eine in den Generator eingebaute Map, in der alle nötigen Definitionen der momentan genutzten Blöcke gespeichert werden.
Pytest
Pytest ist ein Python-Testframework, das sich durch eine leicht verständliche Syntax auszeichnet und gleichzeitig auch in der Lage ist, vollumfängliche Funktionstests umzusetzen. Es wurde zur Blockly-Toolbox hinzugefügt, damit essenzielle Blöcke zur Erstellung eines Pytests.
Tests bestehen im Grundlegenden aus den Phasen Arrange, Act, Assert und Cleanup. Diese Bachelorarbeit sollte lediglich ein umsetzbares Produkt von relativ geringem Umfang implementieren. Deshalb wird lediglich eine arithmetische Kalkulation durchgeführt und ein numerischer Rückgabewert erwartet.
Das Cleanup ist nicht nötig, da kein Speicher für große Objekte reserviert werden muss. Für die Phase Act wird ein neuer Block erstellt. Er ermöglicht es, dass beliebig viele Programmanweisungen gebündelt, innerhalb eines Tests gruppiert und der Test für Pytest erkennbar wird. Pytest erkennt alles als Test, was eine Funktionsdefinition ist und dessen Name entweder mit dem Konstrukt ”test” beginnt oder endet.
Um die Phase Assert umzusetzen existiert in Pytest das Keyword ”assert”. Das ist der verifizierende Teil eines Tests. Auch diese Funktionalität ist als eigener Block umgesetzt. Für beide Umsetzungen ist der Import von Pytest nötig. Pytest erkennt automatisch um welche Art von Assertion es sich handelt und wertet diese aus. Alle Vergleiche haben jedoch gemein, dass sie als Ausgabe einen booleschen Wert produzieren. Die Realisierung eines Blocks für die Erzeugung eines Assert-Statements ist dadurch sehr leicht. Er erzeugt lediglich ein Statement, welches mit dem Ausdruck assert beginnt und darauf folgend, die an den Block angehängte Bedingung. Damit dies nicht fehlschlägt, ist es nötig eine Voraussetzung an den Value-Input des Blocks zu stellen. An diesen Input ist es nur möglich, Blöcke anzuhängen, die als Rückgabe einen booleschen Ausdruck liefern.
Pyserial
Ein Ziel der Arbeit war es, die Lowcode-Applikation mit der Fähigkeit auszustatten, eine serielle Kommunikation mit einem angeschlossenen Gerät aufzubauen und Daten darüber auszutauschen. Dazu wurde eine weitere Kategorie hinzugefügt, in der gesammelt alle Blöcke zur Hardware-Kommunikation mittels Pyserial enthalten sind. Pyserial ist ein Framework zur Kommunikation über serielle Schnittstellen, das standardmäßig das Protokoll RS232 nutzt. Es bietet umfangreiche Möglichkeiten zur Konfiguration und auch zur Nutzung weiterer Protokolle. Dafür wurden weitere drei Blöcke hinzugefügt: einer zum Aufbau einer Verbindung, einer zum Senden über eine geöffnete Verbindung und einer zum Lesen von einer offenen Verbindung.
Webpack
Webpack sorgt dafür, dass die Anwendung in der Gesamtheit funktional wird. Dazu muss das Blockly-Projekt aus JSON-Definitionen, CSS-Konfigurationen und Javascript-Modulen Django in Form von statischen Dateien zur Verfügung gestellt werden. Django und moderne Webbrowser können zwar ohne Probleme mit einzelnen statischen Javascript-Dateien umgehen. Probleme entstehen jedoch, sollten diese als Module voneinander abhängig sein. Um sowohl die bessere Übersichtlichkeit während der Entwicklung durch die Unterteilung in Module zu nutzen als auch Blockly in das Django Projekt einzubinden und im Browser nutzbar zu machen, ist es nötig einen Zwischenschritt einzubauen, in dem das Modulnetz zu einer einzigen großen Datei zusammengefasst wird, mit der Django arbeiten kann. Diese Aufgabe übernimmt Webpack.
Django-Project
Das entstandene Javascript-Bundle wird in ein Django-Projekt eingebunden. Es besteht aus einem Projektteil, der die allgemeinen Settings enthält und den Startpunkt in die Anwendung darstellt, sowie einer oder mehrerer Apps, die in einer komplexeren Anwendungen für unterschiedliche Funktionalitäten stehen. Die dabei verwendeten Templates sind dabei in der Django internen Django-Template-Language(DTL) geschrieben, die HTML sehr ähnelt und nur um Funktionalitäten wie die Nutzung von Variablen oder einfacher Verzweigungen und Schleifen erweitert ist. Auch können in die Templates statische Dateien wie das von Webpack erstellte Bundle mit der kompletten Implementierung eingebunden werden. Views wiederum sind Python-Dateien und ermöglichen somit die komplette Funktionalität von Python zu nutzen, um die Backend-Funktionalität bereitzustellen. Erhalten Views Daten, können sie beliebig komplexe Kalkulationen durchführen bevor sie ihre Ausführung mit dem Rendern einer neuen Seite beenden, mit eventuell aus der Bearbeitung entstandenen Daten.
Literatur:
Yajing Luo u. a.: Characteristics and challenges of low-code development: the practitioners’ perspective. In: Proceedings of the 15th ACM/IEEE international symposium on empirical software engineering and measurement (ESEM). 2021, S. 1–11.