7.6 KiB
Code Review – PR 1: "Feature/improve UI"
Datum: 2026-08-02
Review-State: OPEN (nicht gemerged)
Commits im PR: 2 ("improve ui", "update build scripts")
1. ✅ Was gut ist
- Neues
include/date_utils.h: Saubere Extrahierung der Datumsformatierung in einen wiederverwendbaren Helper (DateUtils::formatShortDE). Sakamoto-Algorithmus für Wochentag-Berechnung ohne NTP ist korrekt implementiert. Eliminiert die vorherige Code-Duplizierung vonformatEventTimeinhome_screen.cppundcalendar_detail_screen.cpp. - Gewitter-Icon: Neue
drawThunderstorm/drawLightningBoltFunktion mit farbenfroher Akzentfarbe (ACCENT_STORM). Unterscheidet sich optisch klar von einfacher Bewölkung. ÜberloaddrawWeatherIcon(symbol, description, ...)mit Rückwärtskompatibilität via Default-Overload ist sauber gelöst. - Verbessertes Kalender-Icon: Ersetzt das vorherige checkbox-ähnliche Symbol durch ein echtes Kalenderblatt-Icon (Header-Balken, Heftklammern, Tagespunkt). Deutlicher UI-Qualitätsgewinn.
- CI-Workflow-Fix:
.github/workflows/build.ymlgeneriert automatisch eine Wegwerf-secrets.haussecrets.h.examplefür Builds. Bricht kein Build mehr in CI, weilsecrets.hper.gitignoreausgeschlossen ist. Kommentar erklärt die Motivation gut. - UI-Feinabstimmung: Kalender-Detail und MVG-Screen erhalten mehr Zeilenabstand (
rowHKonstante), Trennlinien und farbige Datumsangaben. Visuelle Hierarchie ist klarer. drawCloudcolor-Parameter: Neuer Default-Parameter (Theme::TEXT_DIM) ermöglicht farbige Wolken für das Gewitter-Icon, ohne die bestehenden Aufrufer zu brechen..gitignoreCleanup: Eintrag für.venv-platformio/neu organisiert, Kommentar hinzugefügt.- Manuelle Retries: Durch
forceRefresh=truebei Button-Druck (viagoToScreen) wird automatisch ein Retry ausgelöst – entspricht SPEC.
2. ⚠️ Was verbessert werden sollte
-
Kommentar-Entfernung zu radikal: Viele wertvolle Design- und Dokumentationskommentare wurden gelöscht (z.B. in
http_client.h,weather_api.h,screen_base.h,home_screen.h). Diese Kommentare erklären warum der Code so funktioniert, nicht nur was er tut. Die SPEC.md bleibt zwar als Referenz, aber inline-Dokumentation auf Ebene der Header wäre wertvoll. Insbesondere die Erklärung des Retry-Mechanismus inhttp_client.hfehlt jetzt.- Dateien betroffen:
src/api/http_client.h,src/api/weather_api.h,src/api/calendar_api.h,src/api/departures_api.h,src/screens/screen_base.h,src/screens/home_screen.h - Fix: Kurze Doc-Strings / Design-Kommentare wiederherstellen oder als
/** ... */Dokumentation ergänzen.
- Dateien betroffen:
-
wifiConnectedFlag nie verwendet (src/main.cpp:16): Das Flag wird inconnectWifi()gesetzt, aber nirgends gelesen. Wenn WiFi ausfällt, gibt es keine Reconnect-Logik. Inloop()wird der Verbindungsstatus nicht geprüft, bevor API- Calls gemacht werden – das wird durch denWiFi.status()-Check inhttpGetabgefangen, aber ein dedizierter Reconnect-Versuch oder eine Fehlermeldung wäre robuster.- Fix:
wifiConnectedentweder nutzen (z.B. für UI-Statusanzeige) oder entfernen. Optional: Hintergrund-Reconnect inloop()implementieren.
- Fix:
-
Keine JSON-Key-Validierung: In
weather_api.cpp,calendar_api.cpp,departures_api.cppwerdendoc["events"],doc["forecast"],doc["departures"]direkt iteriert, ohne zu prüfen, ob der Schlüssel existiert oder obdocerfolgreich deserialisiert wurde (nur auferrgeprüft, aber nicht aufdoc.containsKey(...)). Bei einer unerwarteten API-Antwort (z.B. Fehler-JSON statt Daten-JSON) würde dies zu einem leeren Array oder undefiniertem Verhalten führen.- Dateien betroffen:
src/api/weather_api.cpp,src/api/calendar_api.cpp,src/api/departures_api.cpp - Fix: Vor Iteration
if (!doc.containsKey("events")) { data.valid = false; return data; }prüfen.
- Dateien betroffen:
-
Fehler-Anzeige-Duplizierung: Der Retry-Icon + "Keine Verbindung"-Block ist identisch in
weather_detail_screen.cpp,calendar_detail_screen.cppundmvg_screen.cpp(3× dupliziert).- Dateien betroffen:
src/screens/weather_detail_screen.cpp:26-31,src/screens/calendar_detail_screen.cpp:39-44,src/screens/mvg_screen.cpp:39-44 - Fix: Gemeinsame Hilfsfunktion
drawErrorState(int x, int y, const char* label)in eine shared Header-Datei (z.B.src/screens/screen_utils.h) extrahieren.home_screen.cpphat bereits eine lokaledrawErrorState– diese sollte nach oben hinausgehoben werden.
- Dateien betroffen:
-
Heißer Crash bei
drawWeatherIconmit leerem Symbol:drawWeatherIconruftsymbol.charAt(0)undsymbol.charAt(1)auf. ObwoohlisNightundconditionmit Length-Checks abgesichert sind, wird dasdefault-Case im Switch bei unbekannten Symbolen aufdrawCloudgeleitet – das ist eine implizite Annahme, die nicht dokumentiert ist.- Datei betroffen:
src/icons/icons.h:53(PR-Version)
- Datei betroffen:
-
mvg_screen.cppZeilenbegrenzung hardcoded:y > 212Hardcoded-Wert ist nicht mitTheme::SCREEN_Hverknüpft. Bei Anzeigegrößen-Wechsel müsste dies manuell angepasst werden.- Datei betroffen:
src/screens/mvg_screen.cpp(PR-Version)
- Datei betroffen:
3. 🛑 Was blockierend ist (muss gefixt werden)
-
Kein Test-Framework vorhanden: Es gibt keinerlei Unit-Tests, keine Mock-Infrastruktur, keine Assertions. Insbesondere für
date_utils.h(kritische Datumsberechnung) undtext_utils.h(UTF-8-Transliteration) wären automatisierte Tests wertvoll. Ohne Tests ist nicht nachweisbar, dass z.B. der Sakamoto-Algorithmus korrekt funktioniert oder dasssanitizeGermanTextalle Umlautfälle abdeckt.- Betroffene Dateien:
include/date_utils.h(neu),include/text_utils.h - Blockade: Unit-Tests für
DateUtils::formatShortDEundDateUtils::computeWeekdayMonBasedhinzufügen (inkl. bekannte Test-Datumswerte). Test-Framework wählen (z.B. ArduinoUnity via PlatformIO, oder host-seitig mit Catch2 + Mock fürString).
- Betroffene Dateien:
-
http_client.cpp–http.begin()Return-Wert ignoriert:http.begin(url)gibtboolzurück (true = success). Der Rückgabewert wird ignoriert. Bei einer ungültigen URL oder fehlschlagender Verbindungsinitialisierung würdehttp.GET()dann undefiniertes Verhalten zeigen.- Datei betroffen:
src/api/http_client.cpp:16 - Fix:
if (!http.begin(url)) { result.success = false; http.end(); return result; }hinzufügen.
- Datei betroffen:
-
http_client.cpp– Stack-Größe beiDynamicJsonDocument: 8–16 KBDynamicJsonDocumentauf dem Stack plus die gesamte HTTP-Antwort imString body→ potenzieller Stack-Overflow bei großen API-Antworten. DerStringwächst dynamisch im Heap, aberres.bodynachhttp.getString()ist bereits vollständig im RAM geladen. Bei sehr großen Antworten (z.B. 10 Kalendertermine mit langen Description-Feldern) könnte der verfügbare RAM auf dem ESP32 knapp werden.- Datei betroffen:
src/api/weather_api.cpp:15,src/api/calendar_api.cpp:15,src/api/departures_api.cpp:15 - Nicht blockierend, da 8–16 KB üblich sind, aber
serializeJson-Stream-Ansatz in einem Follow-up-PR erwägen.
- Datei betroffen:
Checkliste für Follow-up
- Unit-Tests schreiben für
date_utils.hundtext_utils.h http.begin()Return-Wert inhttp_client.cppprüfen- JSON-Key-Validierung in allen drei API-Clients hinzufügen
- Duplizierte Error-Anzeige in eine shared Utility-Funktion extrahieren
- Entfernte Design-Kommentare in Header-Dateien als Doc-Strings wiederherstellen
wifiConnectedFlag entweder nutzen oder entfernen- Hardcoded
y > 212inmvg_screen.cppdurchTheme::SCREEN_H-Ableitung ersetzen - Optional: Reconnection-Logik für WiFi-Ausfall in
loop()implementieren