---
title: How I have fun with Rust
teaser: A few guidelines to make Rust more fun and less frustrating.
tags: rust,beginner
author: Matheus Richard
published_on: 2023-12-21
---

Ruby is my main programming language, but in the last few months, I've been
playing with Rust on side projects. Sometimes it was super fun, sometimes it was
ultimately frustrating. To ensure I always break even, I came up with a few
guidelines for myself.

## Take the easy way out

A systems programming language introduces lots of new (and often hard) concepts.
Some of them are similar but have trade-offs. When starting, I often would pick
whatever was more performant -- that's the _whole_ point of using Rust, right?
--, but that led to much head-scratching. So, my advice is, instead, **to take
the easy way out, even if it's not the most performant**.

Applied to real situations, this results in:

- Using `String` instead of `&str` in structs and enums.
- Using `Vec<T>` instead of `&[T]` in structs and enums.
- Using `Box` (so you can finally write that linked list you always wanted).

They're just less cumbersome and more similar to what you might be used to in
other languages.

## Don't write tests... if you don't want to

It feels like blasphemy, given my Ruby background, but I'm writing (almost) no
tests for my side projects. Rust's type system is pretty good, so I need fewer
tests to be confident my code works.

I only write one when I have a bug to reproduce (which is [the perfect
opportunity to practice Test-Driven Development]).

[the perfect opportunity to practice Test-Driven Development]: https://www.matheusrich.com/a-simple-way-to-get-started-with-tdd/

## The elephant in the room

Oh, the borrow checker... It's absolutely cool, but also my main source of
frustration.

Many times I tried using references and lifetimes, but I always ended up with
hard to understand errors. Other times I'd try to fix the errors, only to end up
with a different error. My advice is to **avoid references and lifetimes** as
much as possible.

In practice, that means:

- Using `Box` more often.
- Using `.clone()` more often.
- Not putting references in structs.

## Don't try to please the Rust sommeliers (especially your internal one)

Trying to write idiomatic Rust from day one is a bad idea. There's no such thing as "perfect" code, so I advise you to be pragmatic. Here the old saying <q>don't let the perfect be the enemy of the good</q> applies. Or, in programming terms, <q>make it work, make it right, make it fast</q>.

I write Rust like it's an interpreted language and "go to lower level
abstractions" when needed. Especially on side projects, **be less diligent about
your code and edge cases**.

That means:

- Using `expect()` to avoid dealing with `Result`/`Option`.
  - You can leave a message telling yourself to deal with it later.
  - I usually handle them, though. I don't think these are hard like some other
    things.
  - If you're lazy, use `unwrap()`. But really, write something.
- Don't use any fancy features like `async`, `unsafe`, and don't write macros.
  - Boring code is good.
  - Unless it's strictly necessary.
- Don't compare your proficiency in Rust with your main language. It's not fair.

## Why?

These guidelines are meant to make Rust more forgiving, and help me not to deal
with too many things at once. I can focus more on the fun parts and don't let my motivation die. That gets me to actually finish something.

Yes, the code uses more memory, but hopefully, you'll have something
working! I'll take a slow-but-finished program over a fast-but-not-working-yet
one any day. Also, it keeps you from prematurely optimizing. Let the profiler
tell you what to focus on!

In a way, it's like building a to-do list or a [do-nothing script]. You can make
progress but still have a list of things to improve later. Once you get the
fundamentals, you can start learning the fancy stuff at your own pace.

[do-nothing script]: https://blog.danslimmon.com/2019/07/15/do-nothing-scripting-the-key-to-gradual-automation/
