|
| 1 | +- Start Date: 2015-04-06 |
| 2 | +- RFC PR: (leave this empty) |
| 3 | +- Rust Issue: (leave this empty) |
| 4 | + |
| 5 | +# Summary |
| 6 | + |
| 7 | +Provide guidelines for builder types in the standard library. |
| 8 | + |
| 9 | +# Motivation |
| 10 | + |
| 11 | +We use builder pattern in a few places in the standard library, but they are not consistent. We |
| 12 | +have `thread::Builder`, `process::Command` and there’s `fs::OpenOptions`. They are somewhat ad-hoc |
| 13 | +and inconsistency makes forming the intuition about them hard. |
| 14 | + |
| 15 | +A common example is people not knowing about `OpenOptions` builder and being confused by its name |
| 16 | +and lack of discoverability. |
| 17 | + |
| 18 | +# Detailed design |
| 19 | + |
| 20 | +## Naming |
| 21 | + |
| 22 | +If the module containing the builder is small and module name represents itself clearly (such as |
| 23 | +`thread` or `process`), the builder should be exported as `Builder`. For example: |
| 24 | + |
| 25 | +* `thread::Builder` builds and spawns threads; |
| 26 | +* `process::Builder` builds and spawns processes; |
| 27 | + |
| 28 | +Otherwise, the name of the built object is suffixed with `Builder` to make it clear this is a |
| 29 | +builder and what object can be expected as an outcome. For example, `fs::OpenOptions`, if it |
| 30 | +followed this guideline, would be `fs::FileBuilder` instead, because the final result is `fs::File` |
| 31 | +object. |
| 32 | + |
| 33 | +Otherwise, if there’s no clear object that can be built using the builder (most likely because it |
| 34 | +contains a several different finalizers), a noun describing all the buildable objects and suffixed |
| 35 | +with the word `Builder` is used. For example: `ThreadBuilder`, even though it produces |
| 36 | +`JoinHandle`s and `JoinGuard`s, rather than `Thread`s. |
| 37 | + |
| 38 | +## Methods |
| 39 | + |
| 40 | +Option setters – methods which represent options that can be set on the builder – should receive |
| 41 | +the builder object as `&mut self` rather than `self` unless there is a good reason to do otherwise. |
| 42 | + |
| 43 | +Finalizers – methods which produce the built object – should consume the builder object (i.e. |
| 44 | +receive `self`, rather than a reference), unless there is a good reason to do otherwise. |
| 45 | + |
| 46 | +In order for method listing in documentation to be predictable, methods in the builder’s `impl` |
| 47 | +block should be declared following this order: |
| 48 | + |
| 49 | +* `new` – a method to create the builder object comes first in the `impl` block; |
| 50 | +* followed by one or more option setters; |
| 51 | +* followed by one or more finalizers. |
| 52 | + |
| 53 | +### Naming |
| 54 | + |
| 55 | +Option setters should be nouns or adjectives. Avoid `is_*` prefix and nouns derived from |
| 56 | +adjectives. For example: |
| 57 | + |
| 58 | +* `name`; |
| 59 | +* `stack_size`; |
| 60 | +* `readable` (rather than `is_readable` or `readability`); |
| 61 | +* `writable` (rather than `is_writable` or `writability`). |
| 62 | + |
| 63 | +Finalizers should be verbs. For example: |
| 64 | + |
| 65 | +* `spawn`; |
| 66 | +* `create`; |
| 67 | +* `open`. |
| 68 | + |
| 69 | +## Clone |
| 70 | + |
| 71 | +Builder objects should strive to implement the `Clone` and `Copy` traits. |
| 72 | + |
| 73 | +# Drawbacks |
| 74 | + |
| 75 | +Breaking change after 1.0-beta. |
| 76 | + |
| 77 | +# Alternatives |
| 78 | + |
| 79 | +* Only apply these guidelines to builders introduced after 1.0-beta. |
| 80 | + |
| 81 | +# Unresolved questions |
| 82 | + |
| 83 | +None known to the author. |
0 commit comments