hi folks! I was wondering whether somebody here might know of a good pattern to use here --
I have a struct like this ```rust
pub struct MyStruct {
a: ComponentA,
b: ComponentB,
c: ComponentC,
}
ComponentA has no dependency.
to create ComponentB, we need to have successfully created ComponentA.
to create ComponentC, we need to have successfully created ComponentB.
The creation of any of these components (A, B, or C) may fail for a variety of reasons.
Therefore, I have an enum to describe these cases ```rust
pub enum MyStructCreationError {
CreatingAFailed,
CreatingBFailedForReason1,
CreatingBFailedForReason2,
CreatingCFailed,
etc.
}
I would like to provide a guarantee that if such a struct can be constructed, all of its subcomponents are adequately initialized.
So, I have a new function which returns a result:
impl MyStruct {
pub fn new() -> Result<Self, MyStructCreationError> {
todo!();
}
}
My question is: what is the appropriate way to initialize a struct such as this? I thought at first to make ComponentB and ComponentC optional, and use (within the new function)
let mut x = Self {
a,
b: None,
c: None,
};
x.maybe_initialize_b()?;
x.maybe_initialize_c()?;
Ok(x)
However, this seems flawed for a number of reasons.
I don't want to leak the Option interface everywhere. I would like to guarantee that if new returns Ok, we have a fully initialized struct. Otherwise, we return Err.
Essentially, I don't want the notion of Optional field values to need handling in all other methods.
Is there a good way to do this?