Mit der Restrukturierung sind wir jetzt im Wesentlichen durch und wir sind sehr zufrieden mit dem Ergebnis. Ich kann eigentlich gar nicht aufhören, in der neuen Dateistruktur hin- und her zu scrollen, so toll finde ich sie 🙂

Leider war dies nur der erste Schritt vor einem viel größeren.

Die „neue“ Sprache

Die verwendete Programmiersprache für das Projekt ist Dart. Dart ist aktuell in der Version 2 verfügbar. Doch man hat sich bei den Verantwortlichen entschieden, auf eine neue Version 3 umzusteigen, die massive Änderungen mit sich bringt.

Für uns sind diese Ankündigungen nicht neu. Bereits vor einem Jahr hatte ich mal reingeschaut, was es für uns bedeuten würde, würden wir auf die neue Version intern upgraden. Und ich verwarf diesen Gedanken augenblicklich wieder. Jede einzelne unserer ca. 1500 Code-Dateien war auf einen Schlag unbrauchbar. Der Compiler würde sie schlicht nicht mehr bauen. Die Änderungen dieser neuen Version 3 von Dart sind extrem massiv.

Null-Safety

Im Prinzip führt Dart ein grundlegendes neues Konzept ein. Programmiersprachen arbeiten, einfach ausgedrückt, mit Variablen. Diese Variablen bekommen einen Wert. Zum Beispiel kann die Variable A den Wert 1 erhalten. Es ist aber auch möglich, dass eine Variable gar keinen Wert hat, zum Beispiel weil eine bestimmte Berechnung noch nicht ausgeführt wurde. Wir reden dann von einem NULL-Wert (NULL ist nicht der Wert 0, sondern einfach nichts).

Je komplexer ein Programm wird, desto größer die Anzahl an Variablen und Berechnungen. Es kann dann schnell vorkommen, dass man hier und da die Übersicht verliert, wann eine Variable bereits mit einem Wert versehen wurde und wann nicht. Wenn nun aus Versehen eine leere Variable für eine weitere Berechnung benutzt wird, sagen wir zum Beispiel, dass A jetzt in der Addition A + B verwendet wird, dann kommt es zu einem Fehler, weil der Computer nicht weiß, wie er eine leere Variable, einen NULL-Wert, addieren soll. Es kommt zu einer sogenannten Null Pointer Exception und in dessen Folge direkt zum Absturz der App.

Die neue Dart-Version integriert nun ein Konzept, das sich Null Safety nennt. Intern wird es dabei extrem erschwert, noch nicht initialisierte Variablen verwenden zu können. Die Änderung zwingt den Programmierer zu deutlich mehr Aufmerksamkeit, was zu deutlich saubererem und weit weniger fehleranfälligerem Code führt.

Für die Techies unter euch: Hier wird das Konzept ausführlicher beschrieben.

Code Clean-Up

Eigentlich ist jeder Programmierer von sich überzeugt, dass er immer den bestmöglichen Code abliefert. Das ist natürlich grundlegend falsch. Man sagt, dass etwa jede 1000. Zeile Code einen Bug enthält. Das klingt nicht viel, aber hochgerechnet auf die 200.000 Zeilen Code, die der GC Wizard enthält, sind das 200 Bugs, die sich vermutlich recht problemlos finden ließen.

Nun, wir waren eh an einem Refactoring unseres Codes und so beschlossen wir, Nägel mit Köpfen zu machen und uns des Upgrades anzunehmen. Nach der Umstellung der Compiler-Version wurden uns etwa 4500 (!) Inkompatibilitäten angezeigt. Im Schnitt also drei pro Datei. Es ist kaum möglich, da irgendwelche Automatismen anzusetzen, jede Stelle muss einer Einzelfallüberprüfung unterzogen werden. Hier wartete also ein Berg Arbeit auf uns.

Wir mussten in alten Code rein, wieder verstehen, was er tut und abwägen, ob der Compiler hier mit der Fehlermeldung Recht hatte. In den meisten Fällen hatte er. Es zeigte sich, dass wir – obwohl wir uns stets bemühen, sauber zu programmieren – deutlich mehr potentielle Bugs hatten, also Stellen wo wir möglicherweise auf leere Variablen zugriffen – als nur in jeder 1000. Zeile. Ich schätze, ich habe allein 1000 tatsächlich dramatische Fehler gefunden, Mike vermutlich noch mehr. Einige dieser Fehler sind schnell zu beheben, aber für einige mussten wir tief in den Code einsteigen, zum Teil sogar ganze Dateien mehr oder weniger neu denken und schreiben.

Das eigentliche Problem

Man kann sich nun sicherlich gut vorstellen, dass, wenn man 4500 Stellen editieren muss, man schnell den Überblick verliert. Beim normalen Entwickeln ändert man eine Stelle, startet das Programm und schaut, ob noch alles so funktioniert, wie es sollte. Hier haben wird nun aber das Problem, dass der Compiler eben dauerhaft meckert. Solange auch nur eine einzige Stelle fehlerhaft markiert ist, so lange werden wir das Programm nicht starten können. Das heißt, wir können nicht nach einer einzelnen Änderung schauen, ob die Fehlerbehebung Erfolg hatte. Wir arbeiten im Blindflug.

Erst wenn alle markierten Stellen ausgemerzt sind, können wir die App wieder starten und anschauen, ob alles noch läuft. Obwohl wir absolut achtsam sind, bei dem was wir gerade veranstalten, ist es sicherlich leicht vorstellbar, das sich gerade bei den größeren notwendigen Änderungen wieder neue Fehler eingeschlichen haben. Wir werden es erst in ein paar Tagen erfahren.

Wie geht es weiter

Wir sind bereits gut vorangekommen mit den Fehlerstellen. Dennoch haben wir – das muss ich zugeben – den Überblick verloren, welche der tausenden Stellen größerer Änderungen bedurften und welche trivial waren. Wir sind gezwungen, die komplette App auf Herz und Nieren zu prüfen. Jedes einzelne Tool muss ausprobiert werden. Jedes einzelne Eingabefeld geprüft und mit allerlei unterschiedlichen Daten gefüttert werden. Arbeitet alles noch so wie erwartet?

Bei vielem können uns automatisierte Tests helfen. Das trifft vor allem auf die Logik zu, also die internen Berechnungen der Funktionen. Was wir aber nur schwer automatisieren können, sind die Oberflächen: Nimmt dieses Textfeld wirklich nur Ziffern entgegen? Funktioniert jenes Ausklappmenü noch mit allen Einträgen?

Hier werden wir massive Hilfe von jedem benötigen, die sie uns geben können. Wir arbeiten gerade an einem Testplan, der von jedem einsehbar sein wird. Wir diskutieren gerade intern im Team, inwieweit es Sinn ergeben könnte, dass wir nicht einfach nur ein neues Update rausgeben, sondern eine neue, temporäre App nur zum Testen. „GCW 3.0 Beta“ oder so. Einfach, um zu vermeiden, dass das kommende Update eure eigentlich funktionierende App überschreibt und ggf. einige Tools nicht mehr funktionieren.

Wer hat Lust, uns zu unterstützen? 🙂