Können Sie Programmieraufgaben mit Low-Code bewältigen? Sicher! Aber warum?
Bei der Bewerbung auf Stellen als Softwareentwickler besteht der aktuelle Trend zur Vorbereitung darin, „LeetCode“-Herausforderungen zu absolvieren. LeetCode ist eine Website mit Aufgaben, die speziell darauf ausgelegt sind, Softwareentwickler auf mögliche Fragen im Vorstellungsgespräch vorzubereiten. Derzeit sind mehr als zweitausend Herausforderungen verfügbar, die alle darauf ausgelegt sind, das Wissen eines Kandidaten in Bezug auf Effizienz, Muster und Problemlösung zu testen.
Hier haben wir also eine ganze Site voller Programmierherausforderungen, die speziell darauf ausgelegt sind, Programmierkenntnisse in mehreren Sprachen zu testen. Da ich meine Zeit mit C# und JavaScript verbracht habe, könnte ich diese Probleme problemlos mit einer dieser Sprachen lösen, aber das mache ich nicht mehr. Ich bin jetzt ein Low-Code-Evangelist. Sicherlich sollte ich versuchen, diese Probleme mit Low-Code zu lösen, oder?
Zugegeben, Low-Code ist nicht speziell für diese Art von Problemen konzipiert. Es ist eine Plattform, die für die Erstellung von Geschäftsanwendungen gedacht ist, nicht für Problemlösungen, bei denen es auf höchste Effizienz ankommt. Es gibt jedoch einen Grund, warum diese Herausforderungen zum Testen von Kandidaten verwendet werden: Sie können auf reale Anwendungen angewendet werden. Versuchen wir uns also an dieser Herausforderung und sehen wir, ob wir sie bewältigen können. Dann werden wir darüber sprechen, wie dies auf eine reale Anwendung angewendet werden könnte und wie Mendix könnte zum Bau verwendet werden.
Herausforderung eins: Two Sum
Bei dieser Herausforderung geht es darum, ein Zahlenarray zu nehmen und den Index der beiden Zahlen zu finden, die zusammen den Zielwert ergeben. Auf den ersten Blick ist die Herausforderung einfach: Nehmen Sie das Array und durchlaufen Sie es, dann durchlaufen Sie es für jeden Wert erneut und finden Sie den Wert, den Sie zum Erreichen des Ziels benötigen. Ineffizient, aber einfach. Also fangen wir damit an.
Zuerst erstellen wir eine einfache Entität, die einen String zur Darstellung des Arrays, ein ganzzahliges Attribut zur Darstellung eines Zielwerts und einige weitere Werte zur Speicherung der Indizes der Elemente, die die Bedingungen erfüllen (siehe unten), enthält. Wir fügen außerdem eine Start-/Endzeit hinzu, um die Effizienz zu verfolgen.
Sobald wir diese Entität erstellt haben, können wir ein Formular zusammenstellen, um die Werte einzugeben und die Details der Herausforderung zu verfolgen. Nichts Ausgefallenes – hier ist die Praxis der Schlüssel. Wie Sie sehen, müssen wir auch eine Schaltfläche hinzufügen, um einen Mikrofluss auszuführen. (Ein Mikrofluss ist das, was Mendix ruft eine Funktion auf.)
Problem Nummer eins: Das String-Array. Mendix ist nicht wirklich dafür ausgelegt, mit String-Arrays zu arbeiten. Wenn Sie dieses Problem in einer realen Lösung angehen würden, hätten Sie eine Liste von Objekten, mit denen Sie arbeiten könnten. Das fühlt sich an dieser Stelle ein bisschen wie Schummeln an, also arbeiten wir vorerst einfach mit dem String.
Das Community Commons-Modul, verfügbar auf der Mendix Marketplace bietet eine Funktion, mit der wir die Zeichenfolge in eine Liste aufteilen können. Außerdem wird jedes Element praktischerweise mit einem Index versehen. Die Werte werden jedoch nicht in Ganzzahlen umgewandelt, sodass wir uns spontan darum kümmern müssen.
Da wir nun eine Liste mit Werten haben, müssen wir nur noch Liste eins durchlaufen und – vorausgesetzt, der erste Wert überschreitet den Zielwert nicht – noch einmal durchlaufen, um zu sehen, ob es einen anderen Wert gibt, dessen Summe den Zielwert ergibt.
Diese Einrichtung sollte jedoch funktionieren, also versuchen wir es.
Perfekt! Funktioniert wie am Schnürchen. Job erledigt, oder? Nein. Nicht ganz. Es gibt noch eine weitere Herausforderung: Können Sie einen Algorithmus entwickeln, dessen Zeitkomplexität weniger als O(n2) beträgt?
Da unsere Lösung eine verschachtelte Schleife enthält, ist dies eindeutig nicht die effizienteste Vorgehensweise. Was also wäre es? Zeiger. Sortieren Sie die Liste und setzen Sie dann einen Zeiger an den Anfang und einen ans Ende. Überprüfen Sie die Summe der beiden Elemente. Wenn sie zu niedrig ist, verschieben Sie den ersten Zeiger in der Liste nach oben. Wenn sie zu hoch ist, verschieben Sie den letzten Zeiger in der Liste nach unten. Wiederholen Sie dies, bis Sie die Lösung gefunden haben oder die Liste erschöpft ist.
Dabei gibt es einige wichtige Herausforderungen. Erstens die sortierte Liste. Unsere Liste ist als Zeichenfolgen gespeichert, daher funktioniert das Sortieren nach Wert nicht. Wir müssen eine Schleife durchlaufen und jeden Wert in eine Ganzzahl umwandeln.
Als nächstes können Sie nicht auf eine Liste mit Indexwerten zugreifen mit Mendix wir können also nicht einfach zwei Indexzeiger haben. Es gibt jedoch eine einfache Lösung, indem wir die Listenoperation „Kopf“ verwenden, um das erste Objekt aus der Liste abzurufen. Wir können dann einfach zwei Kopien der Liste behalten – eine aufsteigend sortierte und eine absteigend sortierte. Während wir uns durch die Liste arbeiten, entfernen wir einfach das Element, das wir gerade prüfen, aus der entsprechenden Liste, wenn es zu hoch oder zu niedrig war.
Die Anwendung funktioniert wie vorgesehen, ist aber weniger effizient als der Brute-Force-Ansatz mit zwei Schleifen für kleinere Zahlenlisten. Wenn jedoch die Anzahl der Werte erhöht wird, wird sie wesentlich effizienter.
Das zeigt nur, dass das, was Sie mit herkömmlichem Code tun können, mit ein wenig kreativem Denken auch mit Low-Code möglich ist. Gehen wir nun einen Schritt weiter: Was wäre, wenn dies ein reales Geschäftsproblem wäre?
Wir gehen davon aus, dass wir für ein Unternehmen arbeiten, das Produkte verpackt, und wir wollen zwei davon in einen Karton packen. Wir müssen jedoch das Gewichtslimit des Kartons einhalten – nicht höher oder niedriger. Dazu müssen wir zwei Produkte in unserem Bestand finden, die zusammen verpackt unserem Zielwert entsprechen. Kommt Ihnen das bekannt vor?
Machen wir zunächst die Mendix und laden die Daten von Anfang an in eine geeignete Entität. Wir generieren eine Liste mit Zufallswerten und verknüpfen diese mit der Ergebnisentität, die wir zuvor erstellt haben. Wir machen sie auch persistent, damit wir die Produkte verfolgen können.
Da wir nun eine Liste haben, mit der wir beginnen können, können wir einfach den Code aus dem zweiten Versuch umgestalten. Dieser Abschnitt unseres ursprünglichen Microflows kann problemlos in einen Sub-Microflow extrahiert und sowohl in unserer ursprünglichen Funktion als auch in der neuen Funktion verwendet werden.
Wir haben jetzt drei verschiedene Möglichkeiten zur Verarbeitung der Daten (wenn die Zahlenliste generiert wird, füllt sie auch das Zeichenfolgenarray, sodass die ersten beiden Funktionen weiterhin funktionieren).
Dadurch finden wir die erste exakte Übereinstimmung. Wir müssen nachverfolgen können, welche Produkte verpackt wurden und mit welchem Produkt sie gepaart sind. Es gibt viele Möglichkeiten, dies zu tun, aber wir werden eine Selbstassoziation für das Produkt verwenden. Auf diese Weise können wir bei Bedarf problemlos zwischen Produkten wechseln. Ich habe die Assoziation zwischen den Entitäten auch so eingestellt, dass alle Produkte automatisch gelöscht werden, wenn die Hauptcharge gelöscht wird. Sie werden feststellen, dass ich die Entitäten in „Charge“ und „Produkt“ umbenannt habe, um die Übersichtlichkeit zu wahren.
Wir müssen auch die Funktionsweise des Microflows zum Finden von Übereinstimmungen ändern, da wir nicht mehr nur nach einer genauen Übereinstimmung suchen. Jetzt wollen wir alle genauen Übereinstimmungen finden. Wir können auch eine weitere Optimierung hinzufügen, indem wir den Aufwand für das Sortieren der Liste wieder in die Datenbank übertragen.
Wie Sie sehen, werden die beiden Produkte bei einer Übereinstimmung miteinander verknüpft und anschließend aus den überprüften Listen entfernt. Anschließend werden die nächsten beiden Produkte ausgewählt.
Unten sehen Sie einen Screenshot der fertigen Anwendung. Wir können sehen, dass wir in der gezeigten Charge 764 Produkte miteinander verbinden konnten. Dies ist nicht die beste Art, die Daten anzuzeigen, da alle Produkte effektiv zweimal angezeigt werden, da sie von jeder Seite der Verbindung angezeigt werden, aber es zeigt, dass es funktioniert!
Wenn überhaupt, unterstreicht es die Tatsache, dass die beste Möglichkeit, diese Daten zu strukturieren, wahrscheinlich darin besteht, eine dritte Entität namens „Box“ zu haben und diese von dort aus den beiden Produkten zuzuordnen. Sie könnten dann eindeutige Box-IDs generieren und jedes Produkt nur einmal anzeigen.
Von dort sind es nur wenige Schritte, um dies mit Kunden, Kurieren und sogar einer Ladenfront zu verknüpfen. Mendix kann problemlos zum Erstellen aller dieser Anwendungen verwendet werden – nicht nur von Spesenabrechnungen oder Urlaubsantragssystemen. Wir sind zwar eine „Low-Code“-Plattform, aber das bedeutet nicht, dass Sie damit keine Anwendungen erstellen können, die komplexe Probleme lösen. Und wo Low-Code nicht ausreicht, besteht immer die Möglichkeit, eine Anwendung mit Java-Aktionen zu erweitern.
Bleiben Sie dran für mein nächster Beitrag Dort versuche ich mich an einer der schwierigeren Herausforderungen: „Behälter mit dem meisten Wasser“. Dabei geht es darum, anhand einer Reihe von Säulenhöhen herauszufinden, welches Säulenpaar einen Behälter bildet, der das meiste Wasser aufnehmen kann oder den größten rechteckigen Bereich zwischen den Säulen aufweist.












