I'm a scientist first and a programmer third or fourth, so a lot of software engineering concepts are somewhat foreign to me. I've worked through the Rust Book, and Rustlings, and I feel like I have a nebulous grasp of the language. I've even built a few crufty things that work on the embedded side for ESP32-C3. I'm running into a real road block here when thinking about building my first user-facing application though.
I've seen this advice a lot:
Please do not use unwrap() in production code
Which I understand, because panics are bad, but I'm stuck trying to think about how the control flow actually works in this case.
Let's say that I have a series of actions that I would like to perform:
- The user picks a folder from a browser (RFD for instance)
- I apply some glob pattern to that folder looking for specific files
- I have to unwrap the glob to get the actual filenames
- I use Polars to read the files into a DataFrame
- I do some analysis and spit out the result
Obviously, throughout all of this there are lots of things that can go wrong, and most of them should be recoverable errors. Say the user selects a folder, and the glob pattern matches nothing, I think the right thing to do would be to go back to the folder picker, and instruct them to pick a different folder, or check their file naming.
This leads me to think that a structure like this:
use rfd::FileDialog;
enum DataFlow {
NeedFolder,
NeedGlob(PathBuf),
NeedFilenames(Paths),
NeedDataFrames(Vec<PathBuf>),
}
fn main() {
let mut state = DataFlow::NeedFolder;
loop {
match state {
DataFlow::NeedFolder => state = DataFlow::NeedGlob(get_folder()),
DataFlow::NeedGlob(folder_dir) => state = DataFlow::NeedFilename(glob(&some_pattern)),
_ => todo!() // Omitted for brevity
}
}
}
fn get_folder() -> PathBuf {
let folder_path = rfd::FileDialog::new()
.set_directory("~")
.pick_folder();
match folder_path {
Some(path) => path,
None => {
println!("Invalid folder or No folder selected");
get_folder()
}
}
Is this a standard design pattern? Or is there another way to accomplish this? I'm basically looking for a way to establish retry paths for errors so that I can handle my errors gracefully. I've done a decent amount of searching on this topic, but I've come up a bit empty-handed. Any and all help/discussion is appreciated.