--- name: coding-standard-rules description: Coding standard rules for writing clean, maintainable, consistent code and review. --- ## Code Writing Rules > [!IMPORTANT] > Apply these rules by default. Do not violate them silently: if one conflicts with > the task or the existing codebase, explain the conflict before proceeding. # Basics The principle is to write simple code, human-readable, yet functional and modern. - Every function does one thing only (Single Responsibility Principle) - Ideally few lines (roughly under 20-30); if it grows too much, split it - Few parameters (ideally ≤ 3-4); beyond that, use an object/struct - Files and folders organized by domain/feature, not arbitrarily - Separation of concerns (e.g. business logic separated from presentation and data access) - Avoid duplication (DRY principle - Don't Repeat Yourself) - KISS (Keep It Simple, Stupid): no over-engineering or complex patterns unless truly needed - YAGNI (You Aren't Gonna Need It): don't add "future-proof" features unless requested # Syntax - Prefer concise syntax where it improves readability: elvis `?:`, ternary, null coalescing `??`, optional chaining - Do not create classes, interfaces or traits that contain a single function: use a standalone function, a static method on an existing class, or write the method in the current class - Prefer pure functions and direct composition over structural patterns (Factory, Strategy, etc.) — use them only if the complexity truly justifies it - Descriptive names without abbreviations; avoid redundant prefixes (e.g. `$userManager->getUserData()` → `$users->get()`) - No magic values: any literal number or string with a specific meaning (thresholds, status codes, fixed strings used in comparisons, timeouts, etc.) must be extracted into a named constant declared at the top of the file/class. Trivial values with no ambiguity (`0`, `1`, `-1` used as neutral/increment, empty string checks) are exempt. Example: ```php // Instead of: if ($user->status === 3) { ... } sleep(30); // Do: const STATUS_SUSPENDED = 3; const RETRY_DELAY_SECONDS = 30; if ($user->status === STATUS_SUSPENDED) { ... } sleep(RETRY_DELAY_SECONDS); ``` - Merge guard clauses that lead to the same outcome into a single condition instead of multiple identical exit points. This applies to any repeated body, not just `return` — including identical `throw`, error logging, or early-exit blocks. Example: ```php // Instead of: if ($a) return null; if ($b) return null; if ($x === null) throw new InvalidArgumentException('x missing'); if ($y === null) throw new InvalidArgumentException('x missing'); // Do: if ($a || $b) return null; if ($x === null || $y === null) throw new InvalidArgumentException('x missing'); ``` If the guards throw/log different messages depending on which condition failed, keep them separate — do not merge conditions that would lose information. # Naming conventions - Use consistent case style per language convention (e.g. camelCase for variables/methods in PHP/JS, snake_case for variables in Python, PascalCase for classes) - Do not mix styles within the same file or codebase # Error handling - Never silently swallow an exception/error (empty catch block, ignored return code) - Catch only the specific exception types you can meaningfully handle; let unexpected ones propagate - Log errors with enough context (input, operation, expected vs actual) to debug without reproducing # Configuration and secrets - No credentials, API keys, hostnames, or environment-specific paths hardcoded in source - Use environment variables or a config/secret manager; source code must be identical across environments # Code reuse - Before creating a new function, check if an existing one covers the same core logic with overlapping parameters and no additional side effects — if so, refactor it instead of duplicating - The refactor must not introduce breaking changes: the original public signature must remain unchanged and all previous consumers must continue to work without modifications - After any refactor, explicitly verify that the original public method signature is unchanged by showing the before/after diff of the signature # Code Comments - Comment every function with its purpose, inputs, output, and side effects. - No comments that just restate the obvious - Add a comment before a logical block only when its intent isn't clear from the code itself (e.g. non-obvious business rules, workarounds, non-trivial algorithmic steps) - Place one blank line before every comment to keep code readable and maintainable