]> git.lizzy.rs Git - rust.git/commitdiff
Document config pattern
authorAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 12 Feb 2021 15:10:16 +0000 (18:10 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 12 Feb 2021 15:10:16 +0000 (18:10 +0300)
docs/dev/style.md

index 0482bc19027e97d3d50c0ddd7c248b9d19a69365..73ce59b8701da549443eec3dbc779f8eb04d7cb3 100644 (file)
@@ -368,6 +368,66 @@ impl ThingDoer {
 
 **Rationale:** not bothering the caller with irrelevant details, not mixing user API with implementor API.
 
+## Functions with many parameters
+
+Avoid creating functions with many optional or boolean parameters.
+Introduce a `Config` struct instead.
+
+```rust
+// GOOD
+pub struct AnnotationConfig {
+    pub binary_target: bool,
+    pub annotate_runnables: bool,
+    pub annotate_impls: bool,
+}
+
+pub fn annotations(
+    db: &RootDatabase,
+    file_id: FileId,
+    config: AnnotationConfig
+) -> Vec<Annotation> {
+    ...
+}
+
+// BAD
+pub fn annotations(
+    db: &RootDatabase,
+    file_id: FileId,
+    binary_target: bool,
+    annotate_runnables: bool,
+    annotate_impls: bool,
+) -> Vec<Annotation> {
+    ...
+}
+```
+
+**Rationale:** reducing churn.
+If the function has many parameters, they most likely change frequently.
+By packing them into a struct we protect all intermediary functions from changes.
+
+Do not implement `Default` for the `Config` struct, the caller has more context to determine better defaults.
+Do not store `Config` as a part of the `state`, pass it explicitly.
+This gives more flexibility for the caller.
+
+If there is variation not only in the input parameters, but in the return type as well, consider introducing a `Command` type.
+
+```rust
+// MAYBE GOOD
+pub struct Query {
+    pub name: String,
+    pub case_sensitive: bool,
+}
+
+impl Query {
+    pub fn all(self) -> Vec<Item> { ... }
+    pub fn first(self) -> Option<Item> { ... }
+}
+
+// MAYBE BAD
+fn query_all(name: String, case_sensitive: bool) -> Vec<Item> { ... }
+fn query_first(name: String, case_sensitive: bool) -> Option<Item> { ... }
+```
+
 ## Avoid Monomorphization
 
 Avoid making a lot of code type parametric, *especially* on the boundaries between crates.