DEV Community

Cover image for 30 Days of Rust - Day 24
johnnylarner
johnnylarner

Posted on

30 Days of Rust - Day 24

Good evening everyone, I'm back after a few days off. I had a friend from abroad visiting and put my studies to one side. I'm back now and have three Rust blogs planned for this week. Today's blog will be short and touch on error handling concepts rather than novel features

Yesterday's questions answered

No questions to answer

Today's open questions

No open questions

Handling errors like a pro

We've already looked at how errors are handled in Rust. But today while building a simple CLI tool (a chapter in the Rust book), I learned some new techniques for error handling could be applied to Rust an beyond.

Keep things simple

When reading code you have a number of markers of cognitive complexity (in terms of syntax, not the concept being represented in code):

  1. Vertical complexity: how deep am I in the stack when this code runs?
  2. Horizontal complexity: how many related data points do I need to track to understand how a function works?
  3. Durational complexity: how long do I need to follow the code before I can "drop" variables ?

When it comes to error handling, we often ask ourselves: where do I raise an error? This indicates to me that reducing vertical and durational complexity can help us handle errors better. In practice, this means two things:

  1. Errors should be handled at a single, higher level. Errors represent potential exit points. Therefore grouping these exit points at one point in call stack can make your code more expressive.
  2. Handle errors as early as possible. If we can rule out all errors early on, then whatever remaining code can be simplified as the "happy path".

Nuanced error handling syntax

Rust executables often contain a run function. This contains the application logic and often serves the purpose of bubbling errors up to your main file, as well as making your code testable. As a run function typically returns an empty tuple, often don't want to do anything with the variable.

The idiomatic of handling such errors in Rust is to use an if let statement:

if let Err(e) = minigrep::run(config) {
    eprintln!("Application error: {e}");
    process::exit(1);
};
Enter fullscreen mode Exit fullscreen mode

We don't care about the empty tuple returned by the run function, so we can save some noise in the catch all variable.

However, it's more often the case that we do, indeed, care about what our function returns to use. In that instance, we'd want to use the unwrap_or_else method of the Result type:

let config = Config::build(&args).unwrap_or_else(|err| {
    eprintln!("Problem parsing arguments: {err}");
    process::exit(1)
});
Enter fullscreen mode Exit fullscreen mode

Image of Wix Studio

2025: Your year to build apps that sell

Dive into hands-on resources and actionable strategies designed to help you build and sell apps on the Wix App Market.

Get started

Top comments (0)

Eliminate Context Switching and Maximize Productivity

Pieces.app

Pieces Copilot is your personalized workflow assistant, working alongside your favorite apps. Ask questions about entire repositories, generate contextualized code, save and reuse useful snippets, and streamline your development process.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay