|
4 | 4 |
|
5 | 5 | > We should discuss visibility, nesting, `mod.rs`, and any interesting patterns
|
6 | 6 | > around modules.
|
| 7 | +
|
| 8 | +#### Naming conventions |
| 9 | +> **[OPEN]** |
| 10 | +> - Anything else? |
| 11 | +> - Are there cases where *not* separating words with underscores is OK, |
| 12 | +> or should this be a hard rule? |
| 13 | +
|
| 14 | +- Module names should contain only lowercae letters and underscores. |
| 15 | + For example, use `std::io::timer`, not `Std::IO::Timer`. |
| 16 | +- Multiple words should be separated by underscores. |
| 17 | + Use `std::local_data`, not `std::localData` or `std::localdata`. |
| 18 | + |
| 19 | +#### Headers |
| 20 | +> **[OPEN]** Is this header organization suggestion valid? |
| 21 | +
|
| 22 | +Organize module headers as follows: |
| 23 | + 1. [Imports](../style/imports.md). |
| 24 | + 1. `mod` declarations. |
| 25 | + 1. `pub mod` declarations. |
| 26 | + |
| 27 | +#### Avoid `path` directives |
| 28 | +> **[OPEN]** This is hardly ever seen in the Rust codebase (only 4 uses, all in |
| 29 | +> `libsyntax`) and seems like overall a bad idea. |
| 30 | +
|
| 31 | +Avoid using `#[path="..."]` directives except where it is *absolutely* |
| 32 | + necessary. |
| 33 | + |
| 34 | +### Use the module hirearchy to organize APIs into coherent sections |
| 35 | +> **[OPEN]** |
| 36 | +
|
| 37 | +The module hirearchy defines both the public and internal API of your module. |
| 38 | +Breaking related functionality into submodules makes it understandable to both |
| 39 | +users and contributors to the module. |
| 40 | + |
| 41 | +#### Place modules in separate files |
| 42 | +> **[OPEN]** |
| 43 | +> - "<100 lines" is completely arbitrary, but it's a clearer recommendation |
| 44 | +> than "~1 page" or similar suggestions that vary by screen size, etc. |
| 45 | +
|
| 46 | +For all except very short modules (<100 lines) and [tests](../testing/README.md), |
| 47 | +place the module `foo` in a separate file: either `foo.rs` or `foo/mod.rs`, |
| 48 | +depending on your needs, rather than declaring it inline like |
| 49 | + |
| 50 | +```rust |
| 51 | +pub mod foo { |
| 52 | + pub fn bar() { println!("..."); } |
| 53 | + /* ... */ |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +#### Use folders to organize submodules |
| 58 | +> **[OPEN]** |
| 59 | +
|
| 60 | +For modules that themselves have submodules, place the module in a separate |
| 61 | +folder (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory. |
| 62 | + |
| 63 | +Note the structure of |
| 64 | +[`std::io`](http://doc.rust-lang.org/std/io/). Many of the submodules lack |
| 65 | +children, like |
| 66 | +[`io::fs`](http://doc.rust-lang.org/std/io/fs/) |
| 67 | +and |
| 68 | +[`io::stdio`](http://doc.rust-lang.org/std/io/stdio/). |
| 69 | +On the other hand, |
| 70 | +[`io::net`](http://doc.rust-lang.org/std/io/net/) |
| 71 | +contains submodules, so it lives in a separate folder: |
| 72 | + |
| 73 | +``` |
| 74 | +io/mod.rs |
| 75 | + io/extensions.rs |
| 76 | + io/fs.rs |
| 77 | + io/net/mod.rs |
| 78 | + io/net/addrinfo.rs |
| 79 | + io/net/ip.rs |
| 80 | + io/net/tcp.rs |
| 81 | + io/net/udp.rs |
| 82 | + io/net/unix.rs |
| 83 | + io/pipe.rs |
| 84 | + ... |
| 85 | +``` |
| 86 | + |
| 87 | +While it is possible to define all of `io` within a single folder, mirroring |
| 88 | +the module hirearchy in the directory structure makes submodules of `io::net` |
| 89 | +easier to find. |
| 90 | + |
| 91 | +#### Top-level definitions |
| 92 | +> **[OPEN]** |
| 93 | +
|
| 94 | +Define or [reexport](http://doc.rust-lang.org/std/io/#reexports) commonly used |
| 95 | +definitions at the top level of your module. |
| 96 | + |
| 97 | +Functionality that is related to the module itself should be defined in |
| 98 | +`mod.rs`, while functionality specific to a submodule should live in its |
| 99 | +related submodule and be reexported elsewhere. |
| 100 | + |
| 101 | +For example, |
| 102 | +[`IoError`](http://doc.rust-lang.org/std/io/struct.IoError.html) |
| 103 | +is defined in `io/mod.rs`, since it pertains to the entirety of the submodule, |
| 104 | +while |
| 105 | +[`TcpStream`](http://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html) |
| 106 | +is defined in `io/net/tcp.rs` and reexported in the `io` module. |
| 107 | + |
| 108 | +### Use internal module hirearchies for hiding implementations |
| 109 | +> **[OPEN]** |
| 110 | +> - Referencing internal modules from the standard library is subject to |
| 111 | +> becoming outdated. |
| 112 | +
|
| 113 | +Internal module hirearchies (including private submodules) may be used to |
| 114 | +hide implementation details that are not part of the module's API. |
| 115 | + |
| 116 | +For example, in [`std::io`](http://doc.rust-lang.org/std/io/), `mod mem` |
| 117 | +provides implementations for |
| 118 | +[`BufReader`](http://doc.rust-lang.org/std/io/struct.BufReader.html) |
| 119 | +and |
| 120 | +[`BufWriter`](http://doc.rust-lang.org/std/io/struct.BufWriter.html), |
| 121 | +but these are re-exported in `io/mod.rs` at the top level of the module: |
| 122 | + |
| 123 | +```rust |
| 124 | +// libstd/io/mod.rs |
| 125 | + |
| 126 | +pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter}; |
| 127 | +/* ... */ |
| 128 | +mod mem; |
| 129 | +``` |
| 130 | + |
| 131 | +This hides the detail that there even exists a `mod mem` in `io`, and |
| 132 | +helps keep code organized while offering freedom to change the implementation. |
0 commit comments