summary refs log tree commit diff
path: root/src/doc/style/features/modules.md
blob: 04aae226f72b59414c635ccd763f26ac0a245edb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
% Modules

> **[FIXME]** What general guidelines should we provide for module design?

> We should discuss visibility, nesting, `mod.rs`, and any interesting patterns
> around modules.

### Headers [FIXME: needs RFC]

Organize module headers as follows:
  1. [Imports](../style/imports.md).
  1. `mod` declarations.
  1. `pub mod` declarations.

### Avoid `path` directives. [FIXME: needs RFC]

Avoid using `#[path="..."]` directives; make the file system and
module hierarchy match, instead.

### Use the module hirearchy to organize APIs into coherent sections. [FIXME]

> **[FIXME]** Flesh this out with examples; explain what a "coherent
> section" is with examples.
>
> The module hirearchy defines both the public and internal API of your module.
> Breaking related functionality into submodules makes it understandable to both
> users and contributors to the module.

### Place modules in their own file. [FIXME: needs RFC]

> **[FIXME]**
> - "<100 lines" is arbitrary, but it's a clearer recommendation
>   than "~1 page" or similar suggestions that vary by screen size, etc.

For all except very short modules (<100 lines) and [tests](../testing/README.md),
place the module `foo` in a separate file, as in:

```rust
pub mod foo;

// in foo.rs or foo/mod.rs
pub fn bar() { println!("..."); }
/* ... */
```

rather than declaring it inline:

```rust
pub mod foo {
    pub fn bar() { println!("..."); }
    /* ... */
}
```

#### Use subdirectories for modules with children. [FIXME: needs RFC]

For modules that themselves have submodules, place the module in a separate
directory (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory.

Note the structure of
[`std::io`](http://doc.rust-lang.org/std/io/). Many of the submodules lack
children, like
[`io::fs`](http://doc.rust-lang.org/std/io/fs/)
and
[`io::stdio`](http://doc.rust-lang.org/std/io/stdio/).
On the other hand,
[`io::net`](http://doc.rust-lang.org/std/io/net/)
contains submodules, so it lives in a separate directory:

```
io/mod.rs
   io/extensions.rs
   io/fs.rs
   io/net/mod.rs
          io/net/addrinfo.rs
          io/net/ip.rs
          io/net/tcp.rs
          io/net/udp.rs
          io/net/unix.rs
   io/pipe.rs
   ...
```

While it is possible to define all of `io` within a single directory,
mirroring the module hirearchy in the directory structure makes
submodules of `io::net` easier to find.

### Consider top-level definitions or reexports. [FIXME: needs RFC]

For modules with submodules,
define or [reexport](http://doc.rust-lang.org/std/io/#reexports) commonly used
definitions at the top level:

* Functionality relevant to the module itself or to many of its
  children should be defined in `mod.rs`.
* Functionality specific to a submodule should live in that
  submodule. Reexport at the top level for the most important or
  common definitions.

For example,
[`IoError`](http://doc.rust-lang.org/std/io/struct.IoError.html)
is defined in `io/mod.rs`, since it pertains to the entirety of `io`,
while
[`TcpStream`](http://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
is defined in `io/net/tcp.rs` and reexported in the `io` module.

### Use internal module hirearchies for organization. [FIXME: needs RFC]

> **[FIXME]**
> - Referencing internal modules from the standard library is subject to
>   becoming outdated.

Internal module hirearchies (i.e., private submodules) may be used to
hide implementation details that are not part of the module's API.

For example, in [`std::io`](http://doc.rust-lang.org/std/io/), `mod mem`
provides implementations for
[`BufReader`](http://doc.rust-lang.org/std/io/struct.BufReader.html)
and
[`BufWriter`](http://doc.rust-lang.org/std/io/struct.BufWriter.html),
but these are re-exported in `io/mod.rs` at the top level of the module:

```rust
// libstd/io/mod.rs

pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
/* ... */
mod mem;
```

This hides the detail that there even exists a `mod mem` in `io`, and
helps keep code organized while offering freedom to change the
implementation.