Rust Coding Standards

Rust Coding Standards

1. Follow Rust Style Guidelines

The Rust community has a set of widely accepted style conventions. Use rustfmt to automatically format your code.

Good Practice:

  • Install rustfmt:
rustup component add rustfmt
  • Format your code:
cargo fmt

Example:
Unformatted code:

fn main() {println!("Hello, world!");}

Formatted code:

fn main() {
println!("Hello, world!");
}

2. Use Meaningful Names

Choose variable, function, and type names that clearly describe their purpose. Avoid abbreviations or single-letter names unless they are universally understood.

Example:
Bad Practice:

fn calc(x: i32, y: i32) -> i32 {
x + y
}

Good Practice:

fn calculate_sum(number1: i32, number2: i32) -> i32 {
number1 + number2
}

3. Write Small and Focused Functions

Each function should perform a single task. Break down complex logic into smaller functions for better readability and reusability.

Example:
Bad Practice:

fn process_data(data: &str) {
let uppercase = data.to_uppercase();
let trimmed = uppercase.trim();
println!("{}", trimmed);
}

Good Practice:

fn convert_to_uppercase(data: &str) -> String {
data.to_uppercase()
}

fn trim_string(data: &str) -> &str {
data.trim()
}

fn main() {
let data = " rust coding ";
let uppercase = convert_to_uppercase(data);
let trimmed = trim_string(&uppercase);
println!("{}", trimmed);
}

4. Use match Instead of Multiple if-else

Leverage Rust’s powerful pattern matching with match to handle conditions more cleanly.

Example:
Bad Practice:

fn get_status_code(code: i32) -> &'static str {
if code == 200 {
"OK"
} else if code == 404 {
"Not Found"
} else {
"Unknown"
}
}

Good Practice:

fn get_status_code(code: i32) -> &'static str {
match code {
200 => "OK",
404 => "Not Found",
_ => "Unknown",
}
}

5. Handle Errors Gracefully

Use Rust’s Result and Option types to manage errors and avoid panics.

Example:

use std::fs::File;

fn open_file(filename: &str) -> Result<File, std::io::Error> {
File::open(filename)
}

fn main() {
match open_file("data.txt") {
Ok(file) => println!("File opened successfully: {:?}", file),
Err(error) => println!("Error opening file: {}", error),
}
}

6. Use Iterators and Closures

Prefer iterators and closures for looping and data transformation.

Example:
Bad Practice:

let numbers = vec![1, 2, 3, 4];
let mut sum = 0;
for number in numbers {
sum += number;
}

Good Practice:

let numbers = vec![1, 2, 3, 4];
let sum: i32 = numbers.iter().sum();

7. Write Comprehensive Tests

Include unit and integration tests to validate your code. Use the #[test] attribute for unit tests.

Example:

#[cfg(test)]
mod tests {
#[test]
fn test_addition() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}

Run tests using:

cargo test

8. Document Your Code

Use /// for documentation comments to describe the purpose of functions, modules, and structs.

Example:

/// Adds two numbers and returns the result.
fn add(a: i32, b: i32) -> i32 {
a + b
}

Generate documentation with:

cargo doc --open

9. Use Clippy for Linting

Clippy is a linter that checks for common mistakes and suggests improvements.

Install Clippy:

rustup component add clippy

Run Clippy:

cargo clippy

10. Avoid Unsafe Code

Use the unsafe keyword only when absolutely necessary and document why it’s required.

Example:

unsafe {
let raw_pointer = &10 as *const i32;
println!("Raw pointer value: {}", *raw_pointer);
}

11. Use Constants and Enums for Fixed Values

Avoid using magic numbers in your code. Use constants and enums for better readability.

Example:
Bad Practice:

if age > 18 {
println!("Adult");
}

Good Practice:

const ADULT_AGE: i32 = 18;

if age > ADULT_AGE {
println!("Adult");
}

12. Modularize Your Code

Split your code into modules for better organization and reuse.

Example:

// main.rs
mod math;

fn main() {
let result = math::add(2, 3);
println!("Sum: {}", result);
}

// math.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}

Leave a Comment

BoxofLearn