- Use `fn` for performance-critical functions that require explicit type annotations and `def` for Python-compatible, dynamic functions.
- Annotate all `fn` parameters with concrete types (e.g., `Int`, `Float64`, `String`) — Mojo does not infer `fn` argument types.
- Prefer `let` for immutable bindings and `var` for mutable ones — `let` enables compiler optimizations and communicates intent.
- Use `SIMD[DType.float32, 8]` for vectorized numeric work instead of scalar loops over Python-style lists.
- Structure modules with `struct` types that implement `Copyable`, `Movable`, or `Destructable` traits explicitly to control value semantics.
- Use `owned` argument convention for values whose ownership transfers into the function and `borrowed` (default) for read-only access.
- Prefer `inout` over returning a modified copy when mutating large structs — it avoids allocation and copy overhead.
- Annotate performance-sensitive `fn` functions with `@always_inline` or `@noncapturing` only when profiling confirms a benefit.
- Follow PEP 8 naming for public APIs: `snake_case` for functions and variables, `PascalCase` for structs and traits.