
Kevin Erath
Geschäftsführer
Veröffentlicht am
6. Februar 2021

Die letzten Posts zu den beiden Prinzipien PoMO und IOSP waren eher theoretischer Natur. Deshalb möchte mich in diesem Post an einer weiteren einfachen Aufgabe probieren und ein einfaches Informationssystem bauen. Hierzu habe ich die beliebteste Aufgabe auf SPOJ (SPhere Online Judge) herausgepickt. Bei der Aufgabe sollen Zahlen von der Konsole eingelesen und so lange auf dem Bildschirm ausgegeben werden, bis die Zahl 42
eingegeben wird. Die Zahl 42 ist deshalb so besonders, weil ein gewisser Anhalter, diese als Antwort auf die unklar gestellte Frage „nach dem Leben, dem Universum und dem ganzen Rest“ erhalten hat.
Die Aufgabe lässt sich leicht in folgende Teilschritte zerlegen:
- Zahlen von der Konsole einlesen
- Zahlen vor Eingabe der 42 ermitteln
- Zahlen auf der Konsole Ausgeben
Die Aufgabe erinnert dabei an das klassische EVA-Prinzip. Also Eingabe, Verarbeitung und Ausgabe. Dies trifft quasi auf so gut wie jedes Software-Problem zu. Weshalb sich EVA auch in meinem Flow Design-Entwurf widerspiegelt. Eine mögliche Lösung für die hier gestellte Aufgabe nach Flow Design sieht dann wie folgt aus:

Flow Design für 42
In diesem Flow Design sind schön die einzelnen Teilschritte in Form von Funktionseinheiten zu sehen. Jede der Funktionseinheiten ist in diesem Falle so einfach, dass diese direkt als Operation implementiert werden kann. Eine weitere Zerlegung ist somit nicht notwendig. Zwischen den Funktionseinheiten fließen jeweils beliebig viele Zahlen (0-n
). Dies wird durch das Sternchen (*
) gekennzeichnet. Eine Umsetzung eines solchen Datenflusses kann z. B. in C# mit dem Interface IEnumerable<int>
erfolgen.
Die Integration übernimmt in diesem Falle die Main-Methode. Bei der Konsole handelt es sich genau genommen um eine Ressource. Der Zugriff darauf, und damit die Abhängigkeit, kann in Flow Design modelliert werden. Aus diesem Grund sieht das vollständige Diagramm dann so aus:

Vollständiges Flow Design für 42
Die Umsetzung dieses Flow-Designs kann dann so aussehen (https://github.com/KevinErath/FindTheAnswer):
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
var numbers = ReadNumbersFromCmd();
var answer = FindTheAnswer(numbers);
PrintNumbers(answer);
}
public static IEnumerable<int> ReadNumbersFromCmd()
{
while (true)
{
var line = Console.ReadLine();
yield return int.Parse(line);
}
}
private static IEnumerable<int> FindTheAnswer(IEnumerable<int> numbers)
{
return numbers.TakeWhile(x => x != 42);
}
private static void PrintNumbers(IEnumerable<int> numbers)
{
foreach (var number in numbers)
{
Console.WriteLine(number);
}
}
}
Auf Tests habe ich, aufgrund der Einfachheit des Codes, an dieser Stelle verzichtet. Außerdem wird die Lösung bei Einreichung durch SPOJ selbst getestet. Dort wird sie nach erfolgreichem Test in einem Ranking veröffentlicht. Unter allen damals eingereichten Lösungen (Sprachen übergreifend) ist die Variante doch weit abgeschlagen. Vermutlich, da bei einer .NET Anwendung erst die Laufzeitumgebung initialisiert werden muss und ein JIT-Compiling durchgeführt wird. Gefiltert auf C# Lösungen befand sich die Lösung in 2015 hingegen im Mittelfeld.

Ranking.png Screenshot des Rankings auf der Webseite SPOJ
Für die Bewertung scheint auf SPOJ hauptsächlich die Performance zu zählen. Das Ergebnis verwundert deshalb auch nicht ganz. Habe ich die Lösung doch auf mehrere Methoden verteilt, LINQ verwendet und ein nicht zwingend notwendiges int
-Parsing durchgeführt. Vermutlich letzteres ist hier der größte Bremser. Was letztendlich aber wirklich der Zeitfresser ist, müsste jetzt mit einem Profiler ermittelt werden. Einen guten Blog-Artikel zum Thema Performance-Messung habe ich damals hier gelesen.
Trotz der durchwachsenen (Performance-)Bewertung favorisiere ich am Ende des Tages trotzdem die hier vorgestellte Lösung, da sie für mich eine saubere Struktur aufweist.
Anmerkung: Bei diesem Text handelt es sich um einen überarbeiteten Repost eines alten Blog-Artikels aus 2015 von mir.

Hier schreibt
Kevin Erath
Als Mitbegründer und Geschäftsführer von pep.digital verbringe ich zwar nicht mehr jeden Tag ausschließlich damit, coole Lösungen für unsere Kunden zu realisieren. Trotzdem finde ich immer wieder die Zeit, mich auch mal tiefer in die Technik einzutauchen und meine Erkenntnisse hier im Blog zu teilen. Und ehrlich gesagt, das Unternehmen und unsere tollen Mitarbeiter:innen weiterzuentwickeln, macht mir mindestens genauso viel Spaß.
Quellen
Weitere interessante Artikel
Wir möchten hier nicht nur über Neuigkeiten aus dem Unternehmen berichten, sondern auch das Wissen und die Erfahrung unserer Experten teilen.

Performance Monitoring mit Annotations und Prometheus
Die Überwachung der Anwendungsleistung ist entscheidend in der modernen Softwareentwicklung. In diesem Blog-Artikel zeige ich dir das Performance Monitoring durch die Messung der Ausführungsdauer von Methoden in einer Spring Boot-Anwendung. Wir verwenden dazu benutzerdefinierte Annotations, AOP und Prometheus.

Dirk Randhahn
Teamleiter, Softwarearchitekt

Was ist Microsoft Roslyn?
Die .NET Compiler Platform ermöglicht es, C#-Code programmatisch zu lesen und auch zu generieren. Dadurch ist es nicht nur möglich Code besser zu analysieren, sondern auch dynamisch zur Laufzeit neuen Code zu erzeugen.

Kevin Erath
Geschäftsführer