Meaningful Naming in Rust
Introduction
Welcome to the second lesson of the "Clean Code Basics with Rust" course, focusing on meaningful naming. In the previous lesson, we introduced clean code and its significance in developing maintainable and efficient software. Now, let's explore the importance of meaningful naming — an essential part of clean code. Selecting appropriate names is vital for creating code that is clear, understandable, and easy to maintain.
Good Naming at a Glance
In this lesson, we'll cover the following naming guidelines:
-
Reveal Intent Through Names: Ensure names clearly convey the role and functionality of variables, structures, and functions. For instance, replacing
calcwithcalculate_interestenhances code clarity. 🧠 -
Avoid Misleading Names: Avoid names that imply incorrect assumptions, such as using
users_listfor aHashSet, ensuring accuracy and understanding. 🚫 -
Choose Descriptive, Searchable Names: Opt for names like
ageinstead ofa, facilitating easy searchability and recognition within the codebase, which enhances maintainability. 🔍 -
Name Traits and Implementations Wisely: Use clear and descriptive names that reflect behavior or capabilities, such as
Readablefor traits andFileReaderfor implementations, without unnecessary prefixes or suffixes. -
Consistent Naming Across the Codebase: Use uniform patterns like
get_all_usersinstead of varied terms such asfetch_all_users, maintaining clarity and preventing confusion. 📚 -
Provide Sufficient Context in Names: Include enough context, such as using
file_sizeinstead ofsize, to eliminate ambiguity, especially when components are used across different contexts. 🌐
Reveal Intent Through Names
Names should clearly express the purpose and functionality of your variables, structures, and functions, leaving no room for ambiguity.
| Bad Example | Good Example |
|---|---|
struct MyStruct { id: u32, name: String } | struct User { id: u32, name: String } |
let coll: Vec<User>; | let users: Vec<User>; |
fn calc() -> f64 { /* ... */ } | fn calculate_interest() -> f64 { /* ... */ } |
let temp: f64; | let temperature: f64; |
fn proc() -> Result<(), Error> { /* ... */ } | fn process_order() -> Result<(), Error> { /* ... */ } |
Effective names provide immediate insight into what the code does, reducing the need for additional explanations. For example, replacing let coll: Vec<User>; with let users: Vec<User>; instantly conveys the collection's purpose and the type of data it holds.
