zlacker

[return to "Patterns for Defensive Programming in Rust"]
1. stouse+aE[view] [source] 2025-12-05 19:27:47
>>PaulHo+(OP)
Good article, but one (very minor) nit I have is with the PizzaOrder example.

    struct PizzaOrder {
        size: PizzaSize,
        toppings: Vec<Topping>,
        crust_type: CrustType,
        ordered_at: SystemTime,
    }
The problem they want to address is partial equality when you want to compare orders but ignoring the ordered_at timestamp. To me, the problem is throwing too many unrelated concerns into one struct. Ideally instead of using destructuring to compare only the specific fields you care about, you'd decompose this into two structs:

    #[derive(PartialEq, Eq)]
    struct PizzaDetails {
        size: PizzaSize,
        toppings: Vec<Topping>,
        crust_type: CrustType,
        … // additional fields
    }

    #[derive(Eq)]
    struct PizzaOrder {
        details: PizzaDetails,
        ordered_at: SystemTime,
    }

    impl PartialEq for PizzaOrder {
        fn eq(&self, rhs: &Self) -> bool { 
            self.details == rhs.details
        }
    }
I get that this is a toy example meant to illustrate the point; there are certainly more complex cases where there's no clean boundary to split your struct across. But this should be the first tool you reach for.
◧◩
2. kazina+5i1[view] [source] 2025-12-05 23:04:49
>>stouse+aE
Decomposing things just to have different equality notions doesn't generalize.

How would you decompose a character string so that you could have a case-insensitive versus sensitive comparison?

:)

◧◩◪
3. stouse+HY2[view] [source] 2025-12-06 17:35:47
>>kazina+5i1
Right, I did note that this decomposition isn’t always applicable. But it often is, and you should default to that when possible.
[go to top]