Shop Projekt - Dokumentation
Programmierstil
Diese Leitlinie definiert den praktischen Programmierstil für den BRULSIM Shop. Ziel ist wartbarer, deklarativer und pragmatischer Code. Sie schlägt die Brücke zwischen sauberen Architekturregeln und hoher Entwicklungsgeschwindigkeit im Alltag.
Kernprinzipien
- Strukturell: Dateistruktur, Wiederverwendbarkeit gezielt nutzen, genau eine Aufgabe pro Funktion und flache Hauptpfade via Early Returns.
- Lesbarkeit: Human-First Code, Self-Documenting Code, projektweite Konsistenz und Pragmatismus.
- Fehlerbehandlung: Das Anti-Silence-Prinzip erzwingt direkte Ortung, Prüfbarkeit über gestaffelte Logs und klare Sichtbarkeit im UI.
- Standards: Typsicherheit, State, Konstanten vs Magic, Begrenzungen.
Strukturelle Prinzipien
Dateistruktur
Jede Quellcodedatei (PHP, JS) folgt einem einheitlichen, vertikalen Aufbau von oben nach unten:
- Datei-Header (Doc-Block): Titel, Modul, Autor, Beschreibung.
- Setup & Deklarationen: Imports (use/require), Klassendeklarationen oder Hauptfunktionen.
- Hilfselemente: Untergeordnete Hilfsfunktionen/Klassen in exakt derselben Reihenfolge, wie sie oben in den Hauptfunktionen aufgerufen werden.
Platzierungsregeln für Services & Helper
- Generisch wiederverwendbare Logik: Wird nach Schicht platziert: app/helper/, app/model/helper/, app/view/helper/.
- Einzelne View-Helper-Datei: Wenn nur eine Datei benötigt wird, ist auch ein direkter Pfad wie app/view/helper.view.php zulässig.
Dateispezifische Split-Regel (große Einzeldatei)
- Gleiche Ebene, gleicher Basisname: Wird eine große Datei für interne, nur dort genutzte Logik gesplittet, entsteht ein gleichnamiger Unterordner auf derselben Ebene (z. B. app/model/label.model.php + app/model/label-model/).
- Wenig interne Helper: Können im unteren Bereich der Datei bleiben, wenn die Lesbarkeit klar bleibt.
- Viele interne Helper: Werden in den dateispezifischen Unterordner verschoben.
- Kein falsches Zentralisieren: Dateispezifische Logik kommt nur dann in globale Helper/Services, wenn sie wirklich breit wiederverwendet wird.
Verantwortung & Kontrolle
- Backend (PHP): Hat die volle Kontrolle über die Datenbank und das Frontend (HTML/JS).
- Frontend (JS): Wird nur so viel ausgeliefert, wie für die aktuelle Seite benötigt wird. Der Austausch zwischen Front- und Backend ist flüssig und modular.
- Selektiver Code-Aufruf: Das Backend muss nicht immer alles aktiv im Server halten, sondern kann selektiv Code-Dateien aufrufen, je nach Bedarf.
- Caching & Cleanup: Das Frontend muss in der Source-Untersuchung abrufbar sein, der Cache muss aber gelöscht werden, wenn die Datei nicht mehr benötigt wird (z. B. bei einem Seitenwechsel).
Eine Funktion → Eine Aufgabe (Single Responsibility)
Eine Funktion löst exakt eine klar definierte Aufgabe. Hilfsfunktionen werden nur bei Komplexität ausgelagert, um den Hauptablauf flach zu halten. Micro-Helper werden vermieden, wenn das Aufteilen mehr "Lesekost" (Mental Overhead) erzeugt als der Code selbst.
- Hilfsfunktionen bei Komplexität: Wenn ein Prozess komplex wird, gehört die Teil-Logik in eigene Hilfsfunktionen ausgelagert, um den Hauptablauf flach zu halten.
- Micro-Helper-Vermeidung: Erzeugt das Aufteilen in eine Mini-Hilfsfunktion mehr "Lesekost" (Mental Overhead) als der Code selbst, bleibt die Logik pragmatisch beieinander (Vermeidung von "Helper Overflow").
Wiederverwendbarkeit & Varianten-Pragmatismus
Logik, die an mehr als zwei Stellen im Projekt benötigt wird, gehört in eine zentrale Funktion oder Service-Klasse.
- Zusammenlegen: Existiert x-mal nahezu identischer Code, muss er geprüft und in einer zentralen Funktion gebündelt werden.
- Varianten bilden: Wird eine Funktion durch zu viele Sonderfall-Tests (if/else-Wust) unlesbar, wird pragmatisch eine gezielte Variante (oder spezialisierte Hilfsfunktion) angelegt, statt eine "eierlegende Wollmilchsau" zu bauen.
Guard Clauses & Flacher Hauptpfad (Early Exit)
Fehler, ungültige Parameter, fehlende Rechte oder CSRF-Sperren werden ganz oben abgefangen und die Funktion sofort beendet (return false; / return;).
- Nach den Guard Clauses läuft die primäre Logik flach und linear nach unten ab.
- Das eigentliche Ausführen der Arbeit wird bei mehr als nur ein paar Zeilen Code an spezialisierte Hilfsfunktionen übergeben.
/**
* @function: handleLabelUpdate
* @description: Handles the incoming label update form submission.
*
* @return: bool True on successful processing, false on validation/CSRF failure.
*/
function handleLabelUpdate(): bool {
// 1. Guard Clauses (Early Exits)
if (!isset($_POST['lky_ID'])) {
return false;
}
// User-/Security-Event -> temporäres Trace-Log statt permanentem Error-Log
if (!cAccess::testPostCsrfToken()) {
traceLog(__FILE__, __LINE__, __FUNCTION__, "Invalid CSRF Token on label update");
return false;
}
// 2. Primary Path (Linear Execution via Helper)
$labelID = (int)$_POST['lky_ID'];
return updateLabelsWithKey($labelID);
}Lesbarkeit & Pragmatismus
- Für Menschen lesbar: Code wird öfter gelesen als geschrieben. Schreibe Variablen, Schleifen und Strukturen so, dass Entwickler und KIs die genaue Absicht auf den ersten Blick erfassen.
- Self-Documenting Code: Nutze ausdrucksstarke, selbsterklärende Namen für Variablen und Funktionen. Reserviere Inline-Kommentare für das Erläutern von komplexen Hintergründen und fachlichen Entscheidungen ("Warum").
- Konsistenz: Halte dich an die etablierten Strukturen des Projekts. Ein einmal festgelegtes Muster (z. B. für Formular-Validierungen) wird projektweit an allen Stellen exakt gleich aufgebaut.
- Pragmatismus bei UI & Rendering: Halte Template-Dateien (PHP-Views) schlank, indem du dich dort rein auf die Ausgabestruktur und einfache Anzeige-Bedingungen (if/else) beschränkst. Geschäftslogik und Datenbankabfragen verbleiben sauber in den vorgelagerten Controllern und Services.
Fehlerbehandlung (Anti-Silence-Prinzip)
- Ortung: Aus dem Log-Eintrag muss sofort hervorgehen, in welcher Datei, Zeile und Funktion der Fehler aufgetreten ist (`__FILE__`, `__LINE__`, `__FUNCTION__`).
- Prüfbarkeit: Systemzustände beim Auftreten eines Fehlers müssen über `errorLog` (persistente Fehler) oder `traceLog` (Diagnose) nachvollziehbar sein.
- Sichtbarkeit & Tabu Stille Fehler: Anwender erhalten immer eine verständliche Rückmeldung im UI. Stille catch-Blöcke oder lautloses Verschwinden von Fehlern sind strikt untersagt.
- Gezielter Abbruch: Bei drohender Dateninkonsistenz oder kritischen Systemfehlern bricht die Ausführung bewusst und kontrolliert ab.
| Funktion | Zweck | Lebensdauer & Verhalten |
|---|---|---|
errorLog(...) | Echte Systemfehler (z. B. DB-Ausfall, fehlende Core-Dateien, Ausführungs-Crashes). | Permanent. Bleibt in der Datenbank/Datei gespeichert, bis ein Entwickler den Fehler behoben und das Log manuell gelöscht hat. |
traceLog(...) | Sicherheits- & User-Events (z. B. ungültige CSRF-Tokens, falsche Formulardaten, Hacker-Skripte). | Temporär. Wird automatisch nach Zeit oder Menge bereinigt. Dient dem System-Monitoring. |
debugLog(...) / console.log() | Lokales Entwickler-Tooling (z. B. temporäre Variablen-Inspektion während des Bauens). | Flüchtig. Darf verwendet werden, muss aber vor dem Merge/Commit wieder aus dem Code entfernt werden. |
Zentrales JS-Monitoring (window.Shop.*): Relevante Frontend-Fehler und blockierte Interaktionen werden zentral erfasst und für die Fehleranalyse an das Backend übermittelt. Frontend-`debugLog(...)` bleibt lokal im Browser (`console.debug`) und wird nicht an Backend-Logs gesendet.
Basis-Standards
- Typsicherheit: Jede Funktion deklariert ihre Parameter-Typen und ihren Rückgabewert (: bool, : array, : void). Das verhindert schleichende Bugs durch automatisches PHP-Type-Casting.
- Keine verdeckten Zustandsänderungen (State): Funktionen mit den Präfixen get..., find... oder is... lesen ausschließlich Daten. Sie dürfen niemals im Hintergrund Sessions verändern, Datenbank-Einträge schreiben oder Mails auslösen.
- Konstanten statt "Magic Values": Keine harten Zahlen oder Strings mitten im Code (z. B. if ($status === 3)). Es werden konsequent die zentralen System-Klassen (cCg, cSc, cFc) oder eigene Klassenkonsanten genutzt.
- Pragmatismus bei Verschachtelung: Mehr als 2 bis 3 Verschachtelungsebenen (if in foreach in if) sind zu vermeiden. Bevor jedoch ein "Helper Overflow" entsteht, darf im Sinne des Pragmatismus lokal eine Ebene tiefer eingerückt werden, wenn der Zusammenhang dadurch klarer bleibt.
- Dateigrößen-Grenzen: Ab 500 Zeilen Code sollte eine Aufteilung in Unterordner, Generische Helper oder Service-Klassen geprüft werden. Quellcodedateien über 1200 Zeilen Code sind strikt zu vermeiden, außer es liegt ein begründeter Architektur-Ausnahmefall vor.
- Harte Migration (Keine Aliasse, keine Doppelungen): Umbenennungen und Namespace-Wechsel werden direkt und vollständig umgestellt. Temporäre Kompatibilitäts-Aliasse, parallele Benennungen oder doppelte Logikpfade sind nicht erlaubt.
- Crash-First-Abschluss: Wenn bei der harten Umstellung Referenzen vergessen wurden, sind Laufzeit-/Testabstürze als Signal akzeptiert und werden gezielt an der fehlerhaften Stelle behoben, statt über Fallback-Aliasse verdeckt.
Operative Durchsetzung
- Regelkonformität beim Arbeiten: Wenn ein Entwickler Code berührt, der nicht regelkonform ist, muss er zuerst in diesem Bereich korrigiert werden, bevor er weiterarbeitet. Es wird nicht das gesamte Projekt analysiert, sondern nur die Bereiche, die gerade berührt werden. Diese werden bei Bedarf bereinigt. Ein absolutes Rumdoktern-Verbot gilt.
- Regel-Priorität bei Konflikten: 1) Flacher und lesbarer Hauptpfad, 2) eine Funktion eine Aufgabe, 3) pragmatische Extraktionstiefe. Lesbarkeit und Hauptpfad haben Vorrang vor erzwungenen Micro-Helpern.
- Crash-First strikt: Keine Fallback-Aliasse, keine doppelten Kompatibilitäts-Pfade, kein stiller degradierter Modus. Fehlerstellen werden direkt am fehlschlagenden Call-Site behoben.
- Dateigrößen-Stufen: JS ab 350 Zeilen mit Pflicht-Split-Plan in der Zyklus-Note, ab 500 Zeilen Split-Pflicht (außer zeitlich befristete Architektur-Ausnahme). PHP ab 500 Zeilen Pflicht-Review, 1200 Zeilen Hard-Limit.
- Architektur-Ausnahmen: Nur mit Begründung, Owner, Ablaufdatum (max. 30 Tage) und konkretem Rückbau-Plan. Abgelaufene Ausnahmen blockieren den Zyklusabschluss.
- Definition of Done pro Zyklus: Regel-Refresh, Datei-To-dos, Umsetzungsnachweis, Kommentar-Recheck, Error/Lint-Check, Runtime-Smoke-Checks und aktualisierte Governance-Spiegelung.
- Durchsetzung: Kein Merge/Abschluss mit offenen Gates. Regelwerk wird quartalsweise geprüft und bereinigt.