From cda296029c3951a28cec305a1973c96ab690fed4 Mon Sep 17 00:00:00 2001 From: Moritz Moeller Date: Mon, 29 Jan 2024 14:56:58 +0100 Subject: [PATCH 1/2] Add init-struct pattern. --- src/SUMMARY.md | 1 + src/patterns/creational/init-struct.md | 66 ++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/patterns/creational/init-struct.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 01a4c728..ff714578 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -32,6 +32,7 @@ - [Visitor](./patterns/behavioural/visitor.md) - [Creational](./patterns/creational/intro.md) - [Builder](./patterns/creational/builder.md) + - [Init-Struct](./patterns/creational/init-struct.md) - [Fold](./patterns/creational/fold.md) - [Structural](./patterns/structural/intro.md) - [Compose Structs](./patterns/structural/compose-structs.md) diff --git a/src/patterns/creational/init-struct.md b/src/patterns/creational/init-struct.md new file mode 100644 index 00000000..308ac256 --- /dev/null +++ b/src/patterns/creational/init-struct.md @@ -0,0 +1,66 @@ +# Init-Struct + +## Description + +Construct an object relying on defaults for omitted fields. + +## Example + +```rust +#[derive(Debug, Default, PartialEq)] +pub struct Foo { + pub foo: Some(u32) + pub bar: String, + // Private members. + baz: Vec + // A lots more fields. +} + + +#[test] +fn inint_struct_test() { + let foo = Foo { + bar: "Some string".to_string(), + ..Default::default + }; +} +``` + +## Motivation + +Useful when you have a struct with a lot of fields that have well-defined/useful defaults. + +## Advantages + +On complex/deeply nested structs only the fields that require explicit initalization have to be +touched. + +Prevents proliferation of constructors. + +Can be used for one-liner initialisation as well as more complex construction. + +Avoids having to write a lot of boilerplate for the common alternative, the [Builder](builder.md) +pattern. + +Can still be combined with the Builder pattern if initializtion requires transformation of some +sort. + +Members can still be private as long as they implement [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html). + +## Disadvantages + +Requires each field of the struct to implement `Default`. + +I.e. if a field is missing `Default`, `default()` has to be implemented and all fields have to be set manualy to their defaults. + +## Discussion + +This pattern is seen frequently in Rust since you can only have a single method with a given name. +Having multiple constructors is thus less nice in Rust than it is in C++, Java, or others. + +The common way to solve this is the [Builder](builder.md) pattern but this often requires a lot of +boilerplate. + +## See Also + +- [Init Struct Pattern](https://xaeroxe.github.io/init-struct-pattern/) From be5d52872477cb31ec99ecd3ea76f222ebfd45ba Mon Sep 17 00:00:00 2001 From: Moritz Moeller Date: Tue, 30 Jan 2024 11:26:15 +0100 Subject: [PATCH 2/2] Syntax error and spelling. --- src/patterns/creational/init-struct.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/patterns/creational/init-struct.md b/src/patterns/creational/init-struct.md index 308ac256..ac4d22b4 100644 --- a/src/patterns/creational/init-struct.md +++ b/src/patterns/creational/init-struct.md @@ -9,16 +9,16 @@ Construct an object relying on defaults for omitted fields. ```rust #[derive(Debug, Default, PartialEq)] pub struct Foo { - pub foo: Some(u32) + pub foo: Option, pub bar: String, // Private members. baz: Vec - // A lots more fields. + // A lot more fields. } #[test] -fn inint_struct_test() { +fn init_struct_test() { let foo = Foo { bar: "Some string".to_string(), ..Default::default