ForgeStream

How Rust Helped Me Write Better Code


Before I learned Rust, I thought I had a good handle on writing clean and reliable code. But Rust challenged me on how I think about ownership, modeling, errors, and safety - and in the process, it made me a better developer.

1. Ownerships

Before, I didn’t really think much about a variable’s scope. I would simply create a variable and decide whether it should be constant or mutable — and that was it.

But when I started learning Rust, I realized there are a few important things to consider before declaring a variable:

Now, I think more carefully about a value’s lifetime and responsibility, which leads to more performant and better-structured code.

Example:

fn greet(name: String) {
    println!("Hello, {}", name);
}

fn main() {
    let name = String::from("Anthony");

    greet(name); // Ownership moved here

    println!("Hello again, {}", name); // Error: value was moved
}

In this example, name is moved into the greet function — meaning the ownership is transferred. After that, we can no longer use name anymore. But what if we still want to use it? What if we just want to pass the value without giving up ownership?

fn greet(name: &String) {
    println!("Hello, {}", name);
}

fn main() {
    let name = String::from("Anthony");

    greet(&name); // Borrowed name

    println!("Hello again, {}", name); // Will work
}

In this updated example, we use &name instead of name to borrow the value. We are letting the greet function to borrow it, so we can still use the name afterwards.

2. Structs

Structs in Rust is similar to TypeScript interfaces or types — where we can define our data model. But Rust’s structs are much more powerful. Not only we can define fields with specific types, but we can also attach methods and custom behaviour directly to the struct.

struct User {
    id: u32,
    name: String,
    is_active: bool,
}

impl User {
    fn greet(&self) {
        if self.is_active {
            println!("Hello, {}!", self.name);
        } else {
            println!("Account is inactive.");
        }
    }
}

fn main() {
    let user = User {
        id: 1,
        name: String::from("Anthony"),
        is_active: false,
    };

    user.greet();
}

In this example:

3. Write Safer Code

Rust forces us to write safer code by making us handle errors explicitly instead of letting us ignore potential errors or null values.

Two core features associated with it:

struct User {
    id: u32,
    name: String,
    is_active: bool,
}

impl User {
    fn get_greetings(&self) -> Result<String, String> {
        if self.is_active {
            Ok(format!("Hello, {}!", self.name))
        } else {
            Err("Account is inactive.".to_string())
        }
    }
}

fn find_user_by_id(id: u32) -> Option<User> {
    if id == 1 {
        Some(User {
            id,
            name: String::from("Anthony"),
            is_active: true,
        })
    } else {
        None
    }
}

fn main() {
    let user_id = 12;

    match find_user_by_id(user_id) {
        Some(user) => match user.get_greetings() {
            Ok(message) => println!("{}", message),
            Err(err) => println!("Error: {}", err),
        },
        None => println!("User not found."),
    }
}

What is happening is that:

In this example, we can see how Rust makes us handle potential errors and missing values explicitly. It shows that Rust enforces handling situations that could potentially occur, rather than letting us ignore them.

4. Compiler

Due to Rust’s complexity, learning the language without a guide would be much harder — especially for beginners.

Unlike other languages where error messages are vague or hard to understand, Rust’s compiler gives meaningful errors alongside with helpful suggestions. It doesn’t just tell you what’s wrong but tells you how to fix it as well.

I personally learned a lot about ownership and borrowing through it. It felt like having a built-in mentor reviewing my code. It may be strict but it makes learning enjoyable and rewarding.

5. Final Thoughts

Learning Rust is a challenge — it has a deep learning curve. But Rust’s design is full of amazing features that help us become better developers by writing safer and more reliable code. There’s so much to learn, and it’s absolutely worth it.