Design Principles

This document outlines the fundamental design principles that guide the development of the Phaser programming language. These principles inform decisions across all aspects of the language, from Grammar Specification to Error Handling and the Compilation Pipeline.

Core Language Principles

Explicit Over Implicit

All behavior should be clear and unambiguous. Avoid magic, hidden behaviors, or implicit conversions that could surprise users. When in doubt, require explicit declaration.

Readability Counts

Prioritize clarity and human comprehension over brevity. Code is read far more often than it is written.

Simplicity Over Cleverness

Avoid overly complex solutions. Simple, straightforward code is easier to understand, debug, and maintain. Design features intuitively so the language behaves as users expect, following the principle of least astonishment. Simple isn’t always easy. We strive for the simplest solution that meets our needs but no simpler than that. We don’t want to unduly shift the burden of complexity onto our users.

One Way to Do It

Prefer a single, canonical approach to solving common problems. This reduces cognitive load and makes code more predictable and maintainable across projects.

Local Reasoning

Code should be understandable without requiring knowledge of distant context. Dependencies should be clear, and side effects should be minimized and obvious. There’s no spooky action at a distance.

Pareto Principle - Make the Common Case Easy and the Advanced Case Possible

The Pareto Principle, also known as the 80/20 rule, suggests that 80% of effects come from 20% of causes. In programming, this means focusing on the most impactful features and optimizing them while accepting that some less critical aspects may remain less optimized.

Security Through Capability-Based Design

Adopt capability-based security principles where possible. Grant components and users only the minimum privileges necessary to accomplish their tasks. This principle of least privilege reduces attack surface and contains potential damage from security breaches or bugs.

Best Practices

Fail Fast

Detect and report errors as early as possible. Catch problems at parse time, compile time, or early runtime rather than allowing invalid states to propagate.

Clear Error Messages

Errors should provide actionable information. Include context about what went wrong and suggest corrective actions when possible.

Consistency

Maintain consistent naming conventions, patterns, and structures throughout the language. This reduces friction when switching between different parts of code.

Composability

Design features to work well together. Prefer orthogonal, small composable pieces over monolithic features.

Minimize Surprise

Design features intuitively. Following principle of least astonishment ensures that the language behaves as users expect.