Code Quality Guidelines

Principles and practices that define code quality within the UNA ecosystem. It complements the UNA CMS Code Convention, which details specific syntax and formatting rules, by focusing on the broader characteristics and practices that lead to superior code.

Why Code Quality Matters

Investing in code quality yields significant benefits:

  • Maintainability: High-quality code is easier to understand, modify, and debug, reducing long-term development costs and effort.
  • Collaboration: Consistent, readable code allows development teams to work together more effectively.
  • Reliability: Well-written, tested code leads to fewer bugs, crashes, and unexpected behaviors, resulting in a more stable platform for end-users.
  • Security: Quality code incorporates security best practices from the outset, protecting the platform and its users from vulnerabilities.
  • Performance: Efficient code ensures a responsive user experience and optimizes server resource utilization.
  • Scalability: Code designed with quality in mind is easier to adapt and scale as the platform's needs grow.

Pillars of Code Quality

We evaluate code quality based on the following key pillars:

Readability and Maintainability

Code is read far more often than it is written. Prioritize clarity and ease of understanding.

  • Adhere to Code Conventions: Strictly follow the UNA CMS Code Convention regarding naming, formatting, indentation, and structure. Consistency is paramount.
  • Meaningful Naming: Choose descriptive names for variables, functions, methods, classes, and database elements that clearly convey their purpose. Avoid overly cryptic or generic names.
  • Clear Structure: Organize code logically.
    • Classes & Methods: Ensure classes and methods have a single, well-defined responsibility (Single Responsibility Principle - SRP). Keep them concise.
    • Modularity: Leverage UNA's modular architecture. Encapsulate functionality within modules.
    • Code Grouping: Group related code together and use whitespace effectively to separate logical blocks.
  • Simplicity (KISS - Keep It Simple, Stupid): Avoid unnecessary complexity. Opt for straightforward solutions over overly clever or convoluted ones.
  • Don't Repeat Yourself (DRY): Avoid duplicating code. Use functions, methods, classes, traits, or includes to abstract and reuse common logic. Utilize UNA's core functions and services where applicable.
  • Effective Comments: Write comments to explain the why behind complex logic, business rules, or non-obvious decisions, not just what the code does. Keep comments concise and up-to-date. Use PHPDoc blocks for all structural elements (classes, methods, functions).

Efficiency and Performance

Quality code performs well and uses resources responsibly.

  • Algorithmic Choice: Select appropriate algorithms and data structures for the task at hand. Be mindful of time and space complexity, especially for operations on large datasets.
  • Database Optimization:
    • Write efficient SQL queries. Fetch only the necessary columns (SELECT col1, col2 instead of SELECT *).
    • Use JOINs effectively instead of multiple separate queries where appropriate. Beware of the N+1 query problem.
    • Ensure proper database indexing for columns used in WHERE, JOIN, ORDER BY, and GROUP BY clauses. Analyze slow queries.
    • Use prepared statements (also crucial for security).
  • Resource Management: Be mindful of memory consumption and CPU usage, especially in loops and frequently executed code paths.
  • Caching: Leverage UNA's caching mechanisms appropriately (Object Cache, Template Cache, Page Cache, CSS/JS Mixes) to reduce database load and improve response times. Cache data that is expensive to compute or fetch and doesn't change frequently.
  • Asset Optimization: Ensure CSS and JavaScript are minified and bundled (using UNA's "Mixes") for production environments to reduce load times. Optimize images.

Security

Secure code is a non-negotiable aspect of quality code.

  • Input Validation: Rigorously validate and sanitize all data from untrusted sources (user input via GET/POST, cookies, API requests, file uploads) using functions like bx_process_input() with appropriate type flags. Assume all external input is potentially malicious.
  • Output Escaping: Prevent Cross-Site Scripting (XSS) by correctly escaping all data before rendering it in HTML, JavaScript, or other contexts. Use UNA's output functions (bx_process_output, bx_html_attribute, bx_js_string, etc.) according to the specific context.
  • SQL Injection Prevention: Exclusively use prepared statements (BxDolDb::prepare) for all database queries involving variable data.
  • Permission Checks (Authorization): Always verify user permissions using the ACL system (BxDolACL::getInstance()->isAllowed(...)) before performing actions or displaying sensitive data. Apply the principle of least privilege.
  • CSRF Protection: Implement and verify CSRF tokens (bx_get_csrf_token, bx_verify_csrf_token) for all state-changing requests (forms submissions, actions).
  • Dependency Management: Keep third-party libraries (managed via Composer) up-to-date to patch known vulnerabilities.
  • Secure Configuration: Avoid hardcoding sensitive information (API keys, passwords). Use secure methods for storing and accessing configuration.

Reliability and Robustness

Quality code functions correctly and predictably, handling errors gracefully.

  • Correctness: The code should produce the expected results for valid inputs and handle invalid inputs appropriately.
  • Error Handling:
    • Anticipate potential failures (e.g., database connection errors, file access issues, API timeouts).
    • Use try...catch blocks to handle exceptions gracefully.
    • Log detailed error information using BxDolErrorHandler::getInstance()->log() for debugging and monitoring.
    • Provide informative but non-technical error messages to end-users in production environments (_t('_error_occurred')). Avoid exposing stack traces or sensitive details.
  • Edge Case Handling: Consider and test boundary conditions, empty values, null inputs, and unusual scenarios.
  • Testing:
    • Unit Tests: Write unit tests (e.g., using PHPUnit) to verify the correctness of individual classes and methods in isolation.
    • Integration Tests: Test the interaction between different components or modules.
    • Functional/Acceptance Tests: Test application workflows from a user's perspective.
    • Write testable code (e.g., using dependency injection).

Supporting Tools and Processes

Achieving and maintaining code quality is supported by established development practices and tools:

  • Code Reviews: Regularly have peers review code before merging. This helps catch issues, share knowledge, enforce standards, and improve overall code quality.
  • Static Analysis: Utilize static analysis tools (e.g., PHPStan, Psalm, PHP_CodeSniffer configured with PSR/UNA standards) to automatically detect potential bugs, style violations, and inconsistencies without running the code.
  • Automated Testing: Implement automated test suites (unit, integration, functional) that run regularly (ideally via Continuous Integration) to catch regressions early.
  • Version Control (Git): Use Git effectively for tracking changes, branching, merging, and collaborating. Write clear commit messages.
  • Continuous Integration (CI): Automate the process of building, testing, and analyzing code whenever changes are pushed to the repository.

Continuous Improvement

Code quality is not a one-time achievement but an ongoing commitment.

  • Refactoring: Regularly revisit and refactor existing code to improve its structure, readability, or performance without changing its external behavior.
  • Learning: Stay updated with PHP best practices, security vulnerabilities, UNA core updates, and new development techniques.
  • Feedback: Be open to constructive feedback during code reviews and discussions. Learn from mistakes.

Testing issues on almost every possible device using BrowserStack

On This Page