Clean Code на Rust: принципы и примеры
编写整洁的代码不仅仅是追逐一时的潮流,而是一项区分专业人士与业余爱好者的基本技能。在系统编程领域,随着 Rust 越来越受欢迎,编写可理解、可维护且安全的代码变得至关重要。在本文中,我们将分解 Clean Code 在 Rust 中的主要原则,并用实际示例加以说明。
1. 命名:说明变量的用途
恰当的命名是可读代码的基础。在 Rust 中,强类型和所有权机制已经提供了大量信息,而好的名称则能使代码实现自文档化。
反面示例:
fn calc(x: &[i32]) -> i32 { let mut r = 0; for i in x { r += i; } r}正面示例(Clean Code):
fn calculate_sum(numbers: &[i32]) -> i32 { let mut total = 0; for number in numbers { total += number; } total}对函数使用动词(如 calculate、fetch、validate),对变量使用名词(如 total、user_name、config)。避免使用像 tmp、res 或 val 这样的缩写——它们无法说明用途。
2. 函数:小而专一
单一职责原则不仅适用于类,也适用于函数。每个函数应该只做一件事,并且要做好。
反面示例(函数做了太多事情):
fn process_user_data(user: &User) -> Result<(), String> { // Validation if user.name.is_empty() { return Err("Name is empty".to_string()); } // Logging println!("Processing user: {}", user.name); // Saving to DB save_to_database(user)?; // Sending email send_welcome_email(user.email)?; Ok(())}正面示例(拆分成小函数):
fn process_user_data(user: &User) -> Result<(), AppError> { validate_user(user)?; log_user_processing(user); save_user_to_db(user)?; send_welcome_email(&user.email)?; Ok(())}
fn validate_user(user: &User) -> Result<(), AppError> { if user.name.is_empty() { return Err(AppError::Validation("Name is required".into())); } Ok(())}
fn log_user_processing(user: &User) { println!("Processing user: {}", user.name);}注意:现在每个函数都有清晰的职责,代码也更容易测试和修改。
3. 错误处理:使用 Result 和自定义错误类型
Rust 没有异常,这很好。在 Rust 中实践 Clean Code 意味着通过 Result<T, E> 和 Option<T> 类型进行显式错误处理。避免在生产代码中使用 panic(unwrap()、expect())。
反面示例(错误时 panic):
fn read_config(path: &str) -> Config { let content = std::fs::read_to_string(path).unwrap(); serde_json::from_str(&content).unwrap()}正面示例(整洁的错误处理):
#[derive(Debug, thiserror::Error)]pub enum ConfigError { #[error("Failed to read file: {0}")] IoError(#[from] std::io::Error), #[error("Failed to parse config: {0}")] ParseError(#[from] serde_json::Error),}
fn read_config(path: &str) -> Result<Config, ConfigError> { let content = std::fs::read_to_string(path)?; let config: Config = serde_json::from_str(&content)?; Ok(config)}