Jeder Entwickler hat seine Lieblingssprache oder sein Lieblingsframework und eine Menge hitziger Diskussion werden deshalb ausgetragen. Darum entschieden wir uns vor ein paar Wochen, dass es an der Zeit ist herauszufinden, welcher der beste/schnellste/produktivste/eleganteste Software Stack ist um eine Webanwendung zu bauen. Gesagt, getan: Nils Wloka und ich luden unsere Kollegen zu einer Partie „Extreme Startup“ ein. In diesem Blogpost möchten wir unsere Erfahrungen mit Ihnen teilen.
Die Herausforderung
Extreme Startup ist eine kleine Ruby Anwendung. Nachdem der Spielleiter den Spielserver gestartet hat, können sich die Teilnehmer am Spielserver registrieren, indem sie eine URL angeben unter der ihre eigene Anwendung erreichbar ist. Der Spielserver fängt danach an HTTP Requests mit Fragen an die registrierten URLs zu verschicken. Aufgabe der Spieler ist es eine Anwendung zu implementieren, welche in der Lage ist auf die verschiedenen Fragen zu antworten (also eine entsprechende Response mit der richtigen Antwort zurück zu schicken). Jedes mal, wenn auf eine Frage keine oder eine falsche Response folgt, bekommt der betreffende Spieler Minuspunkte. Richtige Antworten geben Pluspunkte. Das alles wird auf einem Leaderboard visualisiert, welches wir mittels Beamer an die Front des Konferenzraums projiziert hatten.
Im Verlauf des Spiels werden mehr und mehr Fragen hinzugefügt, sodass die Spieler ihre Anwendung kontinuierlich erweitern müssen um weitere Punkte zu sammeln. Das tolle daran ist, dass Extreme Startup nur HTTP verwendet um mit den Spielern zu interagieren. So kann jeder Teilnehmer seinen Lieblingsstack verwenden. Wir waren also sehr gespannt herauszufinden, welcher Stack die beste Produktivität bringt und es gab dabei für uns einige nette Überraschungen. Alle Implementierungen sind auf github zu finden.
…and the winner is: JavaScript
Ben Ripkens konnte das Rennen um die Punkte mit einem Stack bestehend aus ECMAScript6, node.js und express.js für sich entscheiden. Er hatte im Vorfeld einen ziemlich ausgefeilten Setup vorbereitet, bei dem nginx als Reversed Proxy verwendet wurde, sodass zu jeder Zeit eine Instanz seiner Anwendung vom Spielserver erreichbar war. Des Weiteren nutze er Integrationstests um sicher zu stellen, dass sich beim Implementieren keine Fehler in bereits bestehender Funktionalität einschleichen. Letzt endlich stellte er aber fest, dass es nicht dieser Setup war, welcher ihm zu Sieg verhalf. Stattdessen war es JavaScripts eval()
Funktion, die es relativ leicht machte die Fragen des Spielserver zu verarbeiten. Bens Implementierung auf github betrachtet werden.
Dicht gefolgt von: Clojure
Direkt hinter Ben Ripkens JavaScript Lösung konnte sich eine weitere dynamisch typisierte Sprache platzieren. Gerrit Hentschel verwendete Clojure . Die Clojure REPL half Gerrit dabei sehr schnell neue Funktionalität zur seiner Anwendung hinzuzufügen. Obwohl er dadurch sehr produktiv war, bemerkte Gerrit auch einige Probleme:
- Tests welche in einer REPL ausgeführt werden, sind nicht persistent. Das kann später zu Regressionsfehlern führen, wenn entsprechende persistente Tests nicht vorhanden sind.
- Wenn beim Implementieren nur die Handler-Funktionen getestet werden, können sich leicht Fehler im Routing selbst einschleichen.
Am Ende hatte Gerrit leider eine der Frage falsch verstanden, was ihn eine Menge Punkte kostete. Wäre das nicht passiert, hätte Clojure sogar JavaScript schlagen können. Gerrits Implementierung ist ebenfalls auf github zu finden.
Was ist mit Java?
Bei codecentric machen wir eine Menge Projekte mit dem guten alten Java. Das zeigte sich auch darin, dass drei Spieler auf einen Java 8 + Spring Boot Setup setzen. Was ist groß dazu zu sagen? Spring Boot ist ein wirklicher Game Changer, wenn es darum geht Java Anwendungen zu bootstrappen. Abgesehen davon funktioniert es einfach, nicht mehr und nicht weniger. Es ist nicht super fancy, nicht super-produktiv, aber in der Lage mitzuhalten. Das Hauptproblem für alle Java Programmierer war Javas umständliche RegEx und Pattern Matching API, welche es schwer macht Rechenaufgaben aus einem String zu extrahieren und zu berechnen. Da dies aber die Hauptaufgabe beim Extreme Startup ist, haben Sprachen wie JavaScript oder Clojure, die Strings wie Code evaluieren können, enorme Vorteile. Die Spring Boot Anwendung von Henning Treu ist ebenfalls auf github verfügbar.
Die Paradiesvögel
Neben den üblichen Verdächtigen hatten wir auch Setups, denen man im Projektalltag nicht so häufig begegnet. Fabian Lange entschied sich für Java mit OSGi und Apache Karaf . Moment, was war noch mal OSGi? Das ist das Framework, welches Anfang der 2000er versprach all unsere Modularitätsprobleme zu lösen (die Jar Hell lässt grüßen). OSGi konnte sich im Bereich der Geschäftsanwendungen jedoch nie wirklich durchsetzen. Fabians Setup war in der Lage neue Versionen seiner Anwendung nach erfolgreichem maven Build per Hot Swap in eine laufende JVM zu deployen (OSGi machts möglich). Am Ende hatte er aber auch mit den selben Problemen zu kämpfen wie die anderen Java Entwickler: Es ist schwierig in Java Operationen auf Strings auszuführen. Fabians Setup gibts ebenfalls in unserem github Repository .
Michael Lex entschied sich alle Probleme über das Typsystem seiner Sprache zu lösen: Sein Scala und Akka Setup bot einige Schmankerl, die sich aber leider erst mittelfristig bezahlt machten. Da er mit Akka so gut wie keine Erfahrung hatte, konnte er nicht um die vorderen Ränge mitspielen. Außerdem hinderten lange Compile- und Turn-Around-Zeiten ihn daran wirklich schnell zu entwickeln. Positiv an Scala ist für ihn:
- Ein mächtige Pattern Matching API
- Unit- und Integrationtests sind sehr einfach zu schreiben
- Scalas Typsystem: wenn es kompiliert, dann läuft es auch
Michaels Anwendung ist auch auf github zu finden.
Andreas Houben entschied sich für einen Nicht-JVM Stack. Er nutzte das Extreme Startup als Gelegenheit etwas Neues auszuprobieren: Python + flask . Natürlich hatte er schwer mit den üblichen Anfängerproblemen zu kämpfen (z.B. „wie antworte ich auf einen GET Request?“). Trotzdem war es mit flask sehr einfach eine Anwendung zum laufen zu bringen. Genau wie die Java Programmierer hatte Andreas Schwierigkeiten mit den regulären Ausdrücken. Deshalb war seine Anwendung am Ende nicht in der Lage alle Fragen zu beantworten. Um Pythons Ehre zu verteidigen, entschied sich Andreas das Extreme Startup später noch einmal alleine zu spielen. Deshalb gibt es auf github seine original und seine spätere Implementierung.
Was wir gelernt haben
Das Extreme Startup ist ein Riesenspaß und es gibt ein paar Einsichten, die wir hier teilen wollen:
Entwickler optimieren immer – Da es beim Extreme Startup darum geht Punkte zu sammeln, optimierten alle Spieler direkt in diese Richtung. Beispielsweise verwendet Ben Ripkens Lösung die eval()
Funktion, was gemeinhin als unsicher und schlechter Stil gewertet wird. Aber in dieser Situation war es der optimale Weg um die meisten Punkte zu sammeln. Gerrit Hentschel testete nur in der REPL und hatte daher wenige persistente Tests. Für das Extreme Startup war der Ansatz gewinnversprechend, da sich Tests erst mittelfristig und Richtung Wartungsphase in einem Projekt so richtig auszahlen. Außerdem stellten wir fest, dass einige Clean Code Praktiken beim Extreme Startup weniger wichtig waren, zum Beispiel…
Namen waren unwichtig – Unter dem Stress des Spiels, wurde es weniger wichtig den Dingen einen guten Namen zu geben. Es gab eine ganze Reihe von Tests wie „testFoo1“, „testFoo2“, „testFoo3“ und Variablennamen wie „bla“. Grund dafür ist wieder die kurzfristige Auslegung des Spiels. Da der Code nicht längerfristig gewartet werden muss, sparten sich die Spieler die Zeit zum Finden eines guten Names.
Tests helfen (Überraschung!) – Tests halfen den Spielern auf verschiedenen Ebenen. Da der Spielserver entscheidet, wann welche Frage an welchen Spieler gesendet wird, ist manuelles Testen im Prinzip nicht möglich. Unit Tests helfen deshalb neue Funktionalität schnell zu implementieren, ohne dass man darauf warten muss, dass der Spielserver endlich wieder eine Frage schickt. Außerdem konnten die Spieler sicher stellen, dass einmal richtig implementierte Antwortlogik nicht durch Regressionsfehler in Mitleidenschaft gezogen wurde.
Integrationtests sind wichtig – Eine Menge Probleme resultierte aus Fehlern in der Routinglogik der Anwendungen. In dieser Richtung zeigte sich, wie nützlich Integrationstests sind, welche die ganze Anwendung testen im Gegensatz zu Unit Tests, welche nur die Logik zur Beantwortung einer einzelnen Frage testen.
Zu guter Letzt können wir nur noch einmal unterstreichen, dass Extreme Startup ein sehr gutes Spiel ist. Wir empfehlen jedem es einmal mit den Kollegen auszuprobieren: https://github.com/rchatley/extreme_startup
Weitere Beiträge
von Benedikt Ritter
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Benedikt Ritter
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.