Shop Project - Documentation
Coding Style
This guideline defines the practical coding style for BRULSIM Shop. The goal is maintainable, declarative, and pragmatic code, bridging the gap between clean architecture rules and high daily development speed.
Core Principles
- Structural: File structure, purposeful reusability, exactly one responsibility per function, and flat main execution paths via early returns.
- Readability: Human-first code, self-documenting code, project-wide consistency, and pragmatism.
- Error Handling: The anti-silence principle enforces instant localization, testability via tiered logs, and clear visibility in the UI.
- Standards: Type safety, state management, constants vs magic values, and limits.
Structural Principles
File Structure
Every source code file (PHP, JS) follows a consistent vertical structure from top to bottom:
- File Header (Doc-Block): Title, module, author, description.
- Setup & Declarations: Imports (use/require), class declarations, or main functions.
- Helper Elements: Subordinate helper functions/classes in the exact same order as they are called in the main functions above.
Placement Rules for Services & Helpers
- Generic reusable logic: Place by layer: app/helper/, app/model/helper/, app/view/helper/.
- Single view helper file: If only one file is needed, a direct path like app/view/helper.view.php is also allowed.
File-Specific Split Rule (Large Single File)
- Same level, same base name: If a large file is split for internal logic used only there, create a same-name subfolder on the same level (for example app/model/label.model.php + app/model/label-model/).
- Few internal helpers: May remain in the lower section of the file when readability stays clear.
- Many internal helpers: Move them into the file-specific split folder.
- No false centralization: File-specific logic moves to global helpers/services only when it is truly broadly reused.
Responsibility & Control
- Backend (PHP): Has full control over the database and frontend (HTML/JS).
- Frontend (JS): Only delivers what is needed for the current page. The exchange between front and back is fluid and modular.
- Selective Code Invocation: The backend does not need to keep everything active on the server but can selectively call code files as needed.
- Caching & Cleanup: The frontend must be retrievable in source inspection, but the cache must be cleared when the file is no longer needed (e.g., during a page change).
One Function → One Task (Single Responsibility)
A function solves exactly one clearly defined task. Helper functions are only extracted when complexity arises to keep the main flow flat. Micro-helpers are avoided if splitting adds more "mental overhead" than the code itself.
- Helper Functions for Complexity: When a process becomes complex, the sub-logic should be extracted into its own helper functions to keep the main flow flat.
- Avoiding Micro-Helpers: If splitting into a mini-helper function adds more "mental overhead" than the code itself, keep the logic together pragmatically (avoiding "helper overflow").
Reusability & Variant Pragmatism
Logic needed in more than two places in the project belongs in a central function or service class.
- Merging: If nearly identical code exists x times, it must be reviewed and consolidated into a central function.
- Creating Variants: If a function becomes unreadable due to too many special-case tests (if/else clutter), a targeted variant (or specialized helper function) is pragmatically created instead of building a "jack-of-all-trades" function.
Guard Clauses & Flat Main Path (Early Exit)
Errors, invalid parameters, missing permissions, or CSRF blocks are caught at the top, and the function exits immediately (return false; / return;).
- After the guard clauses, the primary logic proceeds flat and linear downwards.
- The actual execution of the work is delegated to specialized helper functions if it involves more than just a few lines of code.
/**
* @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);
}Readability & Pragmatism
- Human-First: Code is read more often than it is written. Write variables, loops, and structures so that developers and AIs can grasp the exact intent at first glance.
- Self-Documenting Code: Use expressive, self-explanatory names for variables and functions. Reserve inline comments for explaining complex backgrounds and technical decisions ("why").
- Consistency: Adhere to the established structures of the project. Once a pattern is set (e.g., for form validations), it is implemented consistently across the entire project.
- Pragmatism in UI & Rendering: Keep template files (PHP views) lean by focusing solely on output structure and simple display conditions (if/else). Business logic and database queries remain cleanly in the upstream controllers and services.
Error Handling (Anti-Silence Principle)
- Localization: Log entries must instantly pinpoint file, line, and function (`__FILE__`, `__LINE__`, `__FUNCTION__`).
- Testability: System states during errors must be traceable via `errorLog` (persistent errors) or `traceLog` (diagnostics).
- Visibility & No Silent Failures: Users always receive clear UI feedback. Silent catch blocks or swallowed errors are strictly forbidden.
- Controlled Crash: Critical failure paths terminate hard and intentionally when inconsistent data state is threatened.
| Function | Purpose | Lifetime & Behavior |
|---|---|---|
errorLog(...) | Critical system bugs (e.g., DB failure, missing core files, script crashes). | Permanent. Retained until resolved by a developer. |
traceLog(...) | Security & user events (e.g., CSRF errors, invalid form data, exploit attempts). | Temporary. Auto-cleaned over time/quantity. Used for system monitoring. |
debugLog(...) / console.log() | Local developer tooling (e.g., temporary variable inspection). | Transient. Must be removed before merge/commit. |
Central JS Monitoring (window.Shop.*): Relevant frontend errors and blocked interactions are captured centrally and forwarded to the backend for analysis. Frontend `debugLog(...)` stays local in the browser (`console.debug`) and is not forwarded to backend logs.
Basic Standards
- Type Safety: Every function declares its parameter types and return value (: bool, : array, : void). This prevents insidious bugs from automatic PHP type casting.
- No Hidden State Changes: Functions prefixed with get..., find..., or is... only read data. They must never modify sessions, write database entries, or trigger emails in the background.
- Constants instead of "Magic Values": No hard-coded numbers or strings in the middle of the code (e.g., if ($status === 3)). Central system classes (cCg, cSc, cFc) or custom class constants are consistently used.
- Pragmatism in Nesting: More than 2 to 3 levels of nesting (if in foreach in if) should be avoided. However, before a "helper overflow" occurs, it is acceptable to indent one level deeper locally for clarity.
- File Size Limits: Starting at 500 lines of code, consider splitting into subfolders, helpers, or services. Files exceeding 1200 lines of code must be avoided unless an explicit architecture exception applies.
- Hard Migration (No Aliases, No Duplicates): Renames and namespace transitions are applied directly and consistently across the codebase. Temporary compatibility aliases, parallel naming, and duplicate logic paths are not allowed.
- Crash-First Completion: If a hard migration misses references, resulting runtime/test crashes are accepted as signal and must be fixed explicitly at the failing call sites instead of introducing fallback aliases.
Operational Enforcement
- Rule Compliance While Working: If a developer touches code that is not rule-compliant, they must first correct it in that area before proceeding. The entire project is not analyzed; only the areas currently being touched are reviewed and cleaned up as needed. An absolute no-tinkering rule applies.
- Rule Priority in Conflicts: 1) flat and readable primary path, 2) one function one task, 3) pragmatic extraction depth. Readability and primary path win over forced micro-helpers.
- Crash-First Strict: No fallback aliases, no duplicate compatibility paths, and no silent degraded mode. Failing call sites are fixed directly.
- File Size Stages: JS at 350 lines requires a split plan in the cycle note; at 500 lines split is mandatory (except time-boxed architecture exception). PHP at 500 lines requires split review; 1200 lines is a hard limit.
- Architecture Exceptions: Allowed only with reason, owner, expiry date (max 30 days), and concrete removal plan. Expired exceptions block cycle completion.
- Definition of Done per Cycle: Rule refresh, file todos, implementation evidence, comment re-check, error/lint checks, runtime smoke checks, and updated governance mirrors.
- Enforcement: No merge/closure with open gates. Rule documents are reviewed quarterly and cleaned up.