Skip to main content

General Codebase Standards

Introduction

This document outlines general coding and structural standards followed within our codebases.
The goal is to ensure consistency, readability, maintainability, and scalability across all projects.

Internal Conventions

  • Naming

    • Variables and functions: camelCase.
    • Use of PascalCase for files and folders (except specific codebases that have components which use snake_case or kebab-case).
    • Database naming (tables, fields, constraints, ...etc): snake_case.
    • Constants: UPPER_SNAKE_CASE.
  • Code Style

    • Indentation: 4 spaces.
    • Keep line length under 100 characters.
  • Documentation

    • Every module should include a README.md if it's reusable, or if it has technical debt behind it.
    • Functions and classes must have docstrings/comments where appropriate, including todo comments.
  • Other Conventions

    • Creating scripts and macros for frequently used bash commands.
    • Thorough review of packages: Popularity on GitHub (stars and forks), last maintenance date, thorough documentation and tutorial availability.
    • Use of project linters and static analysis tools (PHPCSF for PHP styling, PHPStan for PHP static analysis, ESLint/Prettier for JavaScript/TypeScript) to ensure code consistency and catch issues early.
    • Use of security analysis tools to detect vulnerabilities in code and dependencies (php-security-checker for PHP, npm audit for JavaScript/TypeScript).

Software Patterns

  • General Principles

    • Principle of Least Surprise – Code should behave in a way that is intuitive and expected for other developers.
    • DRY (Don’t Repeat Yourself) – Avoid code duplication by reusing functions, components, and modules.
    • Occam's Razor (Rule of Simplicity) – Keep solutions as simple as possible while still solving the problem.
    • YAGNI (You Aren’t Gonna Need It) – Don’t implement features until they are actually required.
    • SOLID Principles – Ensuring maintainable and extensible code.
    • Separation of Concerns (SoC) – Each module or class should handle a single, well-defined responsibility.
    • Convention over Configuration (CoC) – Prefer established conventions to minimize boilerplate and decision fatigue.
    • Fail Fast – Detect and report errors as early as possible to reduce debugging complexity.
    • Security by Design – Treat security as a first-class concern throughout development.
    • Scalability and Maintainability – Optimize code for long-term health, ensuring it can grow and adapt.
    • Never Trust User Input – Always validate, sanitize, and escape data coming from users, APIs, or external systems before processing or storing it.
  • Layered Architecture

    • Separation of concerns into controllers, services, repositories, and models.
  • Dependency Injection

    • Avoiding of tight coupling by injecting dependencies instead of hardcoding them.
  • Error Handling

    • Centralized error handling – Throw exceptions from any layer and handle in one place.
    • Extra exception handling should be localised to the same layer before throwing again.
    • Use of custom exception classes where appropriate.
  • Configuration Management

    • Default configuration with environment variables serving as overrides.
    • Storage of secrets in environment variables.
    • Never committing sensitive data into version control.

RESTful APIs

  • End-to-End Type Safety

    • Use DTOs (Data Transfer Objects) for both request and response payloads.
    • Define generalized DTOs (e.g., UserDTO) that can be composed of smaller, specific ones (e.g., UserProfileDTO, UserSettingsDTO).
    • DTOs should explicitly define required vs optional fields.
    • When extending DTOs, new fields must be optional by default to avoid breaking existing clients.
  • HTTP Methods & Verbs

    • GET – Fetch resources without side effects.
    • POST – Create a new resource.
    • PUT – Update an existing resource fully.
    • PATCH – Update a resource partially.
    • DELETE – Remove a resource.
  • Semantic Error Codes

    • 200 OK – Successful response; the request was processed as expected.
    • 400 Bad Request – Invalid/missing request parameters or any validation errors.
    • 401 Unauthorized – Missing or invalid authentication.
    • 402 Payment Required – Client must settle payment or subscription requirements before access.
    • 403 Forbidden – Authenticated but not authorized.
    • 404 Not Found – Resource does not exist.
    • 405 Method Not Allowed – The HTTP method used is not supported for this endpoint.
    • 425 Too Early – The server has the resource but refuses to process the request because it may be accessed prematurely (e.g., replayed or before the resource is fully ready).
    • 429 Too Many Requests – The server rejected the request because the client has exceeded the allowed rate limit in a given time window.
    • 500 Internal Server Error – Unhandled errors (should be logged & traced).
    • 501 Not Implemented – The server does not support the request method or functionality.
    • 503 Service Unavailable – Server temporarily unavailable (maintenance or overload).
  • Consistency & Documentation

    • Always return a standardized response format (e.g., { data, message }).
    • DTO validation errors should return at least a message, and optionally a structured list of fields with messages.

These cover standards from big names that we've adopted, ranging from rules that help write maintainable software, to security/reliability-first approaches.