写点什么

Rust 从 0 到 1- 代码组织 - 模块

用户头像
关注
发布于: 2021 年 04 月 23 日
Rust从0到1-代码组织-模块

模块(Modules)让我们可以对一个 crate 中的代码进行组织,以提高可读性与重用性。模块还可以控制代码私有性,即代码是可以被外部代码使用的(即公开的),还是作为一个内部实现,不能被外部代码使用(即私有的)。

下面我们将以一个提供餐馆相关功能的 library crate 来作为例子说明(仅演示代码的组织方式,不关注具体功能逻辑)。餐馆中一般会分前台(front of house)和后台(back of house)。前台是招待顾客的地方,在这里,店主可以为顾客安排座位,服务员接受顾客下单和付款,调酒师会制作饮品。后台则是厨师烹饪,洗碗工洗碗,以及经理做行政工作的地方。

为了让 crate 结构与实际的餐厅结构相同,我们可以参照餐厅的组织结构将代码放置到对应的模块中。首先通过执行 cargo new --lib restaurant,来创建一个新的名为 restaurant 的 lib crate;然后在 src/lib.rs 中来定义模块和函数:

mod front_of_house {    mod hosting {        fn add_to_waitlist() {}        fn seat_at_table() {}    }
mod serving { fn take_order() {} fn serve_order() {} fn take_payment() {} }}
复制代码

我们通过 mod 关键字定义一个模块,并指定模块的名字(如 front_of_house)。在模块内,我们还可以定义其他的模块,如例子中的 hosting 和 serving 模块。模块中也可以定义其他内容,如结构体、枚举、常量、特性、或者函数。

通过使用模块,我们可以将相关的代码组织到一起,并给他们起一个好名字(即高内聚)。组织良好(包括命名)的代码不仅具有更高的可读性,方便其他人使用代码,可以方便的通过模块名称找到他们需要的代码,并且在给代码增加新功能时,也可以清楚的知道,新的代码应该放在哪里。

在前面我们提到了 src/main.rs 和 src/lib.rs 叫做 crate root。之所以这样叫它们的原因是,这两个文件定义了以“crate 模块”(crate 在这里是模块的名字)作为根的模块结构,即模块树(module tree):

crate └── front_of_house     ├── hosting     │   ├── add_to_waitlist     │   └── seat_at_table     └── serving         ├── take_order         ├── serve_order         └── take_payment
复制代码

这个树不仅展示了模块之间的嵌套关系(例如,hosting 嵌套在 front_of_house 中);还展示了模块之间的兄弟关系,即它们定义在同一模块中(例如,hosting 和 serving 被一起定义在 front_of_house 中)。如果一个模块 A 被包含在模块 B 中,我们将模块 A 称为模块 B 的子模块,模块 B 则是模块 A 的 父模块。注意,整个模块树的根默认为“crate 模块” 。

模块树很容易让大家想到文件系统的目录树;官方认为这是一个非常恰当的类比!就像用文件系统的文件目录组织文件,我们可以使用模块来组织我们的代码。

将不同模块放到单独的文件中

前面的例子是一个文件中定义多个模块。随着代码的增加,模块变多变大时,我们会想要将它们的放到到单独的文件中,以代码的可读性。

还以前面餐馆的例子举例,我们将 front_of_house 模块放到属于它自己的文件 src/front_of_house.rs 中,src/lib.rs:

mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() { hosting::add_to_waitlist(); hosting::add_to_waitlist(); hosting::add_to_waitlist();}
复制代码

src/front_of_house.rs

pub mod hosting {    pub fn add_to_waitlist() {}}
复制代码

在 mod front_of_house 后使用分号,而不是花括号,意味着模块的定义在同名的文件中。继续对例子进行重构,将 hosting 模块也提取到其自己的文件中,src/front_of_house.rs:

pub mod hosting;
复制代码

src/front_of_house/hosting.rs

pub fn add_to_waitlist() {}
复制代码

虽然我们做了以上的重构,但是模块树依然保持相同,eat_at_restaurant 中的函数调用可以无需修改。这让我们可以在模块代码增长时,对代码进行重新组织,而尽量不影响代码的使用者。

以上方法同样适用于以 src/main.rs 为 crate root 的 binary crate。

发布于: 2021 年 04 月 23 日阅读数: 11
用户头像

关注

公众号"山 顽石"欢迎大家关注;) 2021.03.23 加入

IT老兵,关注Rust、Java、前端、架构、大数据、AI、算法等;平时喜欢美食、旅游、宠物、健身、篮球、乒乓球等。希望能和大家交流分享。

评论

发布
暂无评论
Rust从0到1-代码组织-模块