Files
bbs-md/.planning/codebase/CONVENTIONS.md
T
2026-02-28 20:12:08 +01:00

201 lines
5.6 KiB
Markdown

# Coding Conventions
**Analysis Date:** 2026-02-28
## Overview
This is an early-stage Rust project with minimal codebase (single `main.rs` file). Conventions are established based on:
- Rust language defaults and community standards
- Cargo default behavior
- Current code patterns in the project
## Naming Patterns
**Files:**
- Snake case: `main.rs`, `lib.rs` are standard entry points
- Module files use snake_case: `user_service.rs`, `data_handler.rs`
- Test modules within files or in separate `tests/` directory
**Functions:**
- Snake case throughout: `fn handle_connection()`, `fn parse_input()`
- Use descriptive verb-based names: `fn calculate_sum()`, `fn build_response()`
**Variables:**
- Snake case for bindings: `let user_id`, `let response_data`
- Constants use UPPER_CASE: `const MAX_BUFFER_SIZE: usize = 1024`
- Mutable bindings explicitly marked: `let mut count = 0`
**Types and Structs:**
- PascalCase for type names: `struct User`, `enum Status`, `trait Handler`
- Generic parameters use single letters or PascalCase: `T`, `S`, `Request`
- Lifetime parameters use lowercase: `'a`, `'static`
## Code Style
**Formatting:**
- Default Rust formatting applied by `rustfmt` (de facto standard)
- 4-space indentation (Rust default)
- No semicolons in final expressions that return values
- Closing braces on same line except for block statements
**Linting:**
- Clippy lints should be addressed as part of development
- No explicit `clippy.toml` or linting configuration currently present
- Default clippy warnings and errors should be resolved before commit
**Edition:**
- Rust 2024 edition (specified in `Cargo.toml`)
- Supports latest language features and idioms
## Import Organization
**Order:**
1. Standard library imports (`use std::`)
2. External crate imports (`use ratatui::`, other external deps)
3. Internal crate imports (`use crate::`)
4. Module declarations (`mod xyz;`)
**Example:**
```rust
use std::io;
use std::collections::HashMap;
use ratatui::backend::CrosstermBackend;
use ratatui::Terminal;
use crate::ui::draw;
use crate::handler::InputHandler;
```
**Path Aliases:**
- No path aliases configured currently
- Can be added via workspace root configuration if needed
## Error Handling
**Patterns:**
- Use `Result<T, E>` for fallible operations
- Propagate errors with `?` operator rather than unwrapping when possible
- Use `anyhow::Result` for application-level errors (dependency available)
- Only use `.unwrap()` or `.expect()` for code that should never panic in normal operation
**Example:**
```rust
fn read_config(path: &str) -> Result<Config> {
let content = std::fs::read_to_string(path)?;
let config = serde_json::from_str(&content)?;
Ok(config)
}
```
## Logging
**Framework:** Not yet selected/integrated
**When logging is added:**
- Use `log` crate for production logging
- Use `env_logger` or similar for log configuration
- Log levels: ERROR for failures, WARN for unusual conditions, INFO for significant events, DEBUG for detailed traces
- Avoid logging sensitive data (credentials, tokens, PII)
## Comments
**When to Comment:**
- Explain the "why" not the "what"
- Document non-obvious algorithmic decisions
- Explain trade-offs or workarounds
- Mark intentional violations of conventions with `// FIXME:` or `// TODO:`
**Doc Comments:**
- Use `///` for public item documentation
- Document public functions, structs, enums, traits
- Include examples for complex or non-obvious public APIs
**Example:**
```rust
/// Processes a user command from the input buffer.
///
/// This function parses the raw input and dispatches to appropriate handlers.
///
/// # Arguments
/// * `input` - Raw user input string
///
/// # Returns
/// `Result<CommandResult, Error>` indicating success or the error encountered
pub fn process_command(input: &str) -> Result<CommandResult> {
// Implementation
}
```
## Function Design
**Size:**
- Keep functions small and focused (ideally < 50 lines)
- Extract helper functions for complex logic
- Separate parsing, validation, and execution logic
**Parameters:**
- Use owned values for simple types, references for larger types
- Prefer `&[T]` over `&Vec<T>` for function parameters
- Use structs to group related parameters (> 3 related params)
**Return Values:**
- Use `Result<T, E>` for operations that can fail
- Use `Option<T>` for values that may be absent
- Avoid returning `Box<dyn Trait>` unless necessary for dynamic dispatch
## Module Design
**Exports:**
- Explicitly declare public items with `pub`
- Use `pub use` to re-export important types at module boundaries
- Keep implementation details private (`non-pub` by default)
**Module Structure:**
```rust
// src/main.rs
mod ui;
mod handler;
mod model;
use ui::App;
use handler::InputHandler;
fn main() {
// Implementation
}
```
**Barrel Files:**
- Use `mod.rs` files in subdirectories to organize module exports
- Example: `src/ui/mod.rs` exports types from `ui/draw.rs`, `ui/state.rs`
## Unsafe Code
**Usage:**
- Avoid unsafe blocks unless necessary for FFI or performance-critical code
- Document unsafe code with `// SAFETY:` comments explaining invariants
- Minimize unsafe scope
**Example:**
```rust
// SAFETY: ptr is guaranteed to point to valid, initialized memory
// returned from foreign_function, which owns its lifetime
unsafe {
let result = process_data(ptr);
}
```
## Workspace and Multi-Crate Structure
**Currently:** Single binary crate (`bbs-md`)
**If expanding:**
- Consider separating into `bbs-md` (binary) and `bbs-md-core` (library)
- Use workspace for shared dependencies and configuration
- Place library code in `src/lib.rs`, binary-specific code in `src/main.rs`
---
*Convention analysis: 2026-02-28*