# Einheitlicher Rechenkern für Next.js und Flutter: Abweichungen bei Zahlen vermeiden
Wenn derselbe Baukalkulator sowohl als Flutter-Mobilapp als auch als Next.js-Website existiert, können schon geringfügige Unterschiede in den Formeln das Vertrauen der Nutzer untergraben. Ein Praxisbeispiel zeigte: Wenn App und Website unterschiedliche Betonmengen für einen Zaunpfahl berechnen, ist das nicht nur ein Bug – es ist ein systemisches Problem durch duplizierte Logik. Die Lösung: eine einzige Quelle der Wahrheit basierend auf deklarativen JSON-Spezifikationen und Paritätstests.
Problem zweier unabhängiger Codebasen
Anfangs wurde die Berechnungslogik doppelt umgesetzt: in Dart für die Flutter-App und in TypeScript für die Next.js-Website. Beide Projekte entwickelten sich parallel, aber unabhängig voneinander. Koeffizienten, Standardwerte (z. B. Lochdurchmesser für einen Pfahl), Rundungsregeln und Materialverpackungen existierten getrennt in jedem Runtime-Code. Ergebnis: Abweichungen bei denselben Eingaben.
Diese Architektur verstößt gegen das DRY-Prinzip („Don’t Repeat Yourself“) und schafft technische Schulden, die sich irgendwann durch Nutzerbeschwerden bemerkbar machen. Besonders kritisch bei Nischen-Tools, wo RechenGenauigkeit direkt das Produktvertrauen beeinflusst.
Deklarativer Ansatz: JSON als Quelle der Wahrheit
Statt Geschäftslogik zu duplizieren, wurden alle variablen Parameter in strukturierte JSON-Dateien ausgelagert – eine pro Rechner. Jede Spezifikation enthält:
- Standardwerte für Eingabefelder (z. B. Pfaldurchmesser – 150 mm)
- Rundungsregeln (immer aufrunden)
- Verlustkoeffizienten je Genauigkeitsmodus
- Materialverpackungsinfos (25-kg-Säcke, 0,01 m³ Ertrag pro Sack)
- Mindest-Schichtdicken und Befestigungsabstände
Diese JSON-Dateien sind nun die einzige Quelle der Wahrheit. Parameteränderungen erfolgen einmal – in JSON – und wirken sich automatisch in beiden Runtimes aus.
Codegenerierung für Synchronisation
Um sicherzustellen, dass beide Projekte dieselben Daten nutzen, wurde ein Codegenerierungsprozess eingeführt:
- Bei JSON-Änderungen läuft das
npm run sync:specs-Skript - Das Skript liest alle Spezifikationen und erzeugt eine Dart-Datei mit einer Konstanten-Map (
const Map) - Die generierte Datei wird ins Flutter-Repository committed
- CI/CD beider Systeme prüft Änderungen und deployt aktualisierte Versionen
Die generierte Datei ist als @generated markiert, manuelle Bearbeitungen blockiert der Linter. So entfallen menschliche Fehler und Datenkonsistenz ist gewährleistet.
Paritätstests: Schutz vor Logikabweichungen
Selbst bei identischen Daten können Sprachunterschiede Verhaltensabweichungen verursachen: Math.ceil() in TypeScript und num.ceil() in Dart unterscheiden sich bei Edge-Cases. Deshalb wurde ein Paritätstest-System implementiert:
- Ein Fixture-Set – Dutzende Eingabekombinationen für jeden der 61 Rechner
- Der TypeScript-Rechner durchläuft alle Fixtures und speichert Ergebnisse in einer Referenzdatei
- Dieselbe Datei dient im Flutter-Repo zum Vergleich mit Dart-Rechner-Ergebnissen
- Jede Abweichung – selbst die letzte Dezimalstelle – scheitert den CI
In sechs Monaten fingen diese Tests drei echte Abweichungen auf, die ohne Automatisierung unbemerkt geblieben wären.
Drei Genauigkeitsmodi statt „Plus 10 %“
Traditionelle Rechner nutzen oft einen universellen Sicherheitsfaktor (z. B. +10 %). Dieser Shortcut führt zu Ungenauigkeiten: Fliesen brauchen Zuschneidezulauf, Putz Unebenheitsausgleich der Basis, Kleber Oberflächenabsorption.
Stattdessen wurden drei Berechnungsmodi eingeführt:
- Basic – normbasierte Berechnung ohne Puffer, nach GOST/SP
- Realistic (Standard) – berücksichtigt typische Wohnungssanierungsbedingungen
- Professional – maximale Puffer für komplexe Projekte und Liefermengensicherheit
Koeffizienten pro Modus sind ebenfalls in JSON-Spezifikationen gespeichert, Änderungen ohne Neukompilierung möglich.
Schlüsselregel: Bei identischen Eingaben muss Basic ≤ Realistic ≤ Professional gelten. Ein dedizierter CI-Test überprüft das für alle Rechner.
Validatoren als zweite Verteidigungslinie
Neben Unit-Tests und Paritätschecks läuft im CI drei spezialisierte Validatoren:
- Logischer Validator: stellt sicher, dass Kaufmenge ≥ Nettomenge, Ergebnisse nicht bei gültigen Eingaben nullen, Labels metrische Einheiten nutzen („m²“, nicht „sq m“)
- Verpackungs-Validator: prüft realistische Materialverpackungen (Kleber in 5/10/15-L-Eimern, Fliesen in Paketen, nicht einzeln)
- Einheiten-Validator: fängt metrische Vermischungen ab (z. B. Millimeter zu Metern addieren ohne Umrechnung)
Diese Skripte wirken wie ein „Sicherheitscheck“ am Systemtor – sie ersetzen keine Unit-Tests, verhindern aber dumme, aber kritische Ökosystem-Fehler.
Wichtige Erkenntnisse
- Einmalige Quelle der Wahrheit via JSON-Spezifikationen eliminiert Parameterduplikation über Runtimes.
- Codegenerierung sorgt für Datensync ohne manuelle Eingriffe.
- Paritätstests garantieren identische Ergebnisse in Dart und TypeScript.
- Drei Genauigkeitsmodi ersetzen simplen „+10 %“-Ansatz und geben Nutzern Kontrolle über Puffer.
- Spezialisierte Validatoren im CI schützen vor systemischen Fehlern, die Unit-Tests übersehen könnten.
— Editorial Team
Noch keine Kommentare.