rustbook/04.md

1142 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 第四章 结构化工程:模块与包
## 4.1 模块系统概述
随着项目规模增长代码组织变得至关重要。Rust的模块系统提供了强大的工具帮助开发者构建清晰、可维护的代码结构。本章将探索如何使用模块、包和工作空间来组织大型Rust项目。
### 为什么需要模块化?
模块化设计带来的核心优势:
- **代码组织** - 逻辑相关的代码集中在一起
- **封装** - 隐藏实现细节,只暴露必要接口
- **命名空间** - 避免名称冲突
- **可重用性** - 促进代码复用
- **可测试性** - 更容易为独立模块编写测试
### Rust模块系统的核心概念
| 概念 | 描述 | 关键字/文件 |
|------|------|------------|
| 模块(Module) | 代码的命名空间单元 | `mod` |
| 包(Package) | 一个或多个crate的集合 | `Cargo.toml` |
| Crate | 编译单元,生成库或可执行文件 | `lib.rs`/`main.rs` |
| 工作空间(Workspace) | 多个相关包的集合 | `[workspace]` |
## 4.2 mod层级设计构建代码树
### 模块声明与组织
Rust中的模块可以嵌套形成树状结构
```rust
// lib.rs
mod front_desk; // 前台模块
mod cataloging; // 编目模块
mod user_services; // 用户服务模块
// 嵌套模块示例
mod user_services {
mod registration {
// 用户注册相关功能
}
mod borrowing {
// 借阅相关功能
}
}
```
### 模块文件组织策略
Rust提供两种组织模块的方式
1. **内联模块**:在同一文件中定义
```rust
// lib.rs
mod config {
pub const MAX_BOOKS: usize = 5;
pub fn get_loan_duration() -> u32 {
14 // 默认借阅期为14天
}
}
```
2. **文件模块**:在单独文件中定义
```
lib.rs // 声明模块
└── config.rs // 实现模块
```
```rust
// lib.rs
mod config; // 声明模块实现在config.rs中
// config.rs
pub const MAX_BOOKS: usize = 5;
pub fn get_loan_duration() -> u32 {
14
}
```
### 子模块文件组织
对于更复杂的模块结构,可以使用目录:
```
lib.rs // 声明顶层模块
├── user_services.rs // 声明user_services子模块
└── user_services/ // 子模块目录
├── registration.rs
└── borrowing.rs
```
```rust
// user_services.rs
pub mod registration; // 声明子模块
pub mod borrowing; // 声明子模块
```
### 模块路径与引用
使用`use`关键字简化模块路径:
```rust
// 不使用use
fn main() {
crate::user_services::registration::register_new_user("Alice");
}
// 使用use
use crate::user_services::registration::register_new_user;
fn main() {
register_new_user("Alice");
}
```
**路径别名**
```rust
use crate::user_services::registration::register_new_user as register;
fn main() {
register("Alice");
}
```
**批量导入**
```rust
use crate::user_services::registration::{register_new_user, validate_email};
```
## 4.3 pub权限控制接口与实现分离
### 可见性规则
Rust中的所有项默认是私有的使用`pub`关键字使其公开:
```rust
mod library {
pub struct Book { // 公开结构体
pub title: String, // 公开字段
isbn: String, // 私有字段
}
impl Book {
pub fn new(title: &str, isbn: &str) -> Self { // 公开方法
Self {
title: title.to_string(),
isbn: isbn.to_string(),
}
}
fn validate_isbn(&self) -> bool { // 私有方法
!self.isbn.is_empty()
}
}
}
```
### 可见性级别
Rust提供多种可见性级别
| 关键字 | 可见范围 | 用途 |
|--------|---------|------|
| (默认) | 仅当前模块及其子模块 | 隐藏实现细节 |
| `pub` | 任何引入该模块的代码 | 公开API |
| `pub(crate)` | 仅当前crate | 内部API |
| `pub(super)` | 仅父模块 | 限制子模块暴露 |
| `pub(in path)` | 指定路径 | 精细控制可见性 |
示例:
```rust
mod library {
pub(crate) struct Catalog { // 仅在crate内可见
// ...
}
pub(super) fn internal_helper() { // 仅对父模块可见
// ...
}
}
```
### 接口设计最佳实践
1. **最小公开原则**只公开必要的API
2. **抽象泄漏控制**:使用私有字段防止实现细节泄漏
3. **API稳定性**:谨慎公开可能变化的内容
```rust
// 良好的接口设计
pub struct Library {
// 私有实现细节
books: Vec<Book>,
users: HashMap<UserId, User>,
}
impl Library {
// 公开稳定API
pub fn new() -> Self { /* ... */ }
pub fn add_book(&mut self, book: Book) { /* ... */ }
pub fn borrow_book(&mut self, user_id: UserId, book_id: BookId) -> Result<(), BorrowError> { /* ... */ }
// 私有辅助函数
fn find_available_copy(&self, book_id: BookId) -> Option<&Book> { /* ... */ }
}
```
## 4.4 workspace多crate管理扩展到大型项目
### 工作空间基础
工作空间允许管理多个相关包:
```toml
# Cargo.toml (根目录)
[workspace]
members = [
"library-core",
"library-api",
"library-cli"
]
```
目录结构:
```
library-workspace/
├── Cargo.toml # 工作空间配置
├── library-core/ # 核心功能crate
├── library-api/ # API服务crate
└── library-cli/ # 命令行工具crate
```
### 工作空间依赖管理
工作空间内的crate可以相互依赖
```toml
# library-api/Cargo.toml
[dependencies]
library-core = { path = "../library-core" }
```
### 工作空间命令
在工作空间根目录执行命令会应用到所有成员:
```bash
# 构建所有crate
cargo build
# 测试特定crate
cargo test -p library-core
# 运行特定crate
cargo run -p library-cli
```
### 共享依赖优化
工作空间中的共享依赖只编译一次,提高构建效率:
```toml
# 在各crate的Cargo.toml中
[dependencies]
serde = "1.0" # 在多个crate中使用的依赖只编译一次
```
## 4.5 文档测试:代码即文档
### 文档注释类型
Rust支持两种文档注释
1. **外部文档注释**:用于项的文档
```rust
/// 表示图书馆中的一本书
///
/// # 示例
/// ```
/// let book = Book::new("Rust编程", "978-1234567890");
/// assert_eq!(book.title(), "Rust编程");
/// ```
pub struct Book {
// ...
}
```
2. **内部文档注释**用于模块或crate整体文档
```rust
//! # 图书馆管理系统
//!
//! 这个模块提供图书馆管理的核心功能,包括:
//! - 图书编目
//! - 用户管理
//! - 借阅流程
```
### 文档测试
文档中的代码块默认会作为测试运行:
```rust
/// 计算借阅的逾期费用
///
/// # 参数
/// * `days_overdue` - 逾期天数
///
/// # 返回值
/// 应付的逾期费用(元)
///
/// # 示例
/// ```
/// use library::calculate_overdue_fee;
/// assert_eq!(calculate_overdue_fee(5), 5.0); // 5天逾期收费5元
/// assert_eq!(calculate_overdue_fee(0), 0.0); // 未逾期,无费用
/// ```
pub fn calculate_overdue_fee(days_overdue: u32) -> f64 {
days_overdue as f64
}
```
运行文档测试:
```bash
cargo test --doc
```
### 文档测试特殊标记
控制文档测试行为:
```rust
/// ```
/// # use library::Book; // 这行在文档中隐藏,但测试时执行
/// let book = Book::new("Rust编程", "978-1234567890");
/// ```
///
/// ```no_run
/// // 编译但不运行的代码
/// let book = fetch_from_database("978-1234567890");
/// ```
///
/// ```compile_fail
/// // 应该编译失败的代码
/// let book: Book = "不是书";
/// ```
///
/// ```ignore
/// // 完全忽略的代码
/// let x = 非法语法;
/// ```
```
## 4.6 实例项目:图书馆管理系统
让我们应用所学知识,构建一个模块化的图书馆管理系统。
### 项目结构设计
```
library/
├── Cargo.toml
└── src/
├── lib.rs # 主模块和公共API
├── models/ # 数据模型
│ ├── mod.rs
│ ├── book.rs
│ └── user.rs
├── services/ # 业务逻辑
│ ├── mod.rs
│ ├── catalog.rs
│ └── lending.rs
└── utils/ # 工具函数
├── mod.rs
└── validation.rs
```
### 实现核心模块
**1. 主模块 (lib.rs)**
```rust
//! # 图书馆管理系统
//!
//! 一个模块化的图书馆管理系统,提供图书编目、用户管理和借阅服务。
pub mod models;
pub mod services;
mod utils; // 内部工具模块,不对外暴露
// 重新导出核心类型,简化用户导入
pub use models::{Book, User};
pub use services::{catalog::Catalog, lending::LendingService};
/// 系统版本号
pub const VERSION: &str = "0.1.0";
/// 创建一个新的图书馆实例
pub fn new_library() -> services::Library {
services::Library::new()
}
```
**2. 模型模块 (models/mod.rs)**
```rust
//! 系统中使用的数据模型
pub mod book;
pub mod user;
pub use book::Book;
pub use user::User;
```
**3. 图书模型 (models/book.rs)**
```rust
//! 图书相关的数据模型
use std::fmt;
/// 表示图书馆中的一本书
#[derive(Debug, Clone, PartialEq)]
pub struct Book {
title: String,
author: String,
isbn: String,
available: bool,
}
impl Book {
/// 创建一本新书
///
/// # 示例
/// ```
/// use library::Book;
/// let book = Book::new("Rust编程艺术", "张三", "978-1234567890");
/// assert_eq!(book.title(), "Rust编程艺术");
/// assert!(book.is_available());
/// ```
pub fn new(title: &str, author: &str, isbn: &str) -> Self {
Self {
title: title.to_string(),
author: author.to_string(),
isbn: isbn.to_string(),
available: true,
}
}
/// 获取书名
pub fn title(&self) -> &str {
&self.title
}
/// 获取作者
pub fn author(&self) -> &str {
&self.author
}
/// 获取ISBN
pub fn isbn(&self) -> &str {
&self.isbn
}
/// 检查书是否可借
pub fn is_available(&self) -> bool {
self.available
}
/// 标记为已借出
pub(crate) fn mark_borrowed(&mut self) {
self.available = false;
}
/// 标记为已归还
pub(crate) fn mark_returned(&mut self) {
self.available = true;
}
}
impl fmt::Display for Book {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} by {} (ISBN: {})", self.title, self.author, self.isbn)
}
}
**4. 用户模型 (models/user.rs)**
```rust
//! 用户相关的数据模型
use std::fmt;
/// 用户ID类型
pub type UserId = u32;
/// 表示图书馆的一名用户
#[derive(Debug, Clone, PartialEq)]
pub struct User {
id: UserId,
name: String,
email: String,
active: bool,
borrowed_books: Vec<String>, // 存储已借阅书籍的ISBN
}
impl User {
/// 创建一个新用户
///
/// # 示例
/// ```
/// use library::User;
/// let user = User::new(1, "李四", "lisi@example.com");
/// assert_eq!(user.name(), "李四");
/// assert!(user.is_active());
/// ```
pub fn new(id: UserId, name: &str, email: &str) -> Self {
Self {
id,
name: name.to_string(),
email: email.to_string(),
active: true,
borrowed_books: Vec::new(),
}
}
/// 获取用户ID
pub fn id(&self) -> UserId {
self.id
}
/// 获取用户名
pub fn name(&self) -> &str {
&self.name
}
/// 获取用户邮箱
pub fn email(&self) -> &str {
&self.email
}
/// 检查用户是否激活
pub fn is_active(&self) -> bool {
self.active
}
/// 获取用户已借阅的书籍ISBN列表
pub fn borrowed_books(&self) -> &[String] {
&self.borrowed_books
}
/// 记录用户借阅了一本书
pub(crate) fn borrow_book(&mut self, isbn: &str) {
self.borrowed_books.push(isbn.to_string());
}
/// 记录用户归还了一本书
pub(crate) fn return_book(&mut self, isbn: &str) -> bool {
if let Some(pos) = self.borrowed_books.iter().position(|b| b == isbn) {
self.borrowed_books.remove(pos);
true
} else {
false
}
}
/// 停用用户账户
pub(crate) fn deactivate(&mut self) {
self.active = false;
}
/// 重新激活用户账户
pub(crate) fn activate(&mut self) {
self.active = true;
}
}
impl fmt::Display for User {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} (ID: {}, Email: {})", self.name, self.id, self.email)
}
}
```
**5. 服务模块 (services/mod.rs)**
```rust
//! 图书馆业务服务模块
pub mod catalog;
pub mod lending;
use std::collections::HashMap;
use crate::models::{Book, User, UserId};
/// 图书馆主服务
pub struct Library {
catalog: catalog::Catalog,
lending: lending::LendingService,
}
impl Library {
/// 创建一个新的图书馆实例
pub fn new() -> Self {
Self {
catalog: catalog::Catalog::new(),
lending: lending::LendingService::new(),
}
}
/// 获取目录服务
pub fn catalog(&self) -> &catalog::Catalog {
&self.catalog
}
/// 获取可变目录服务
pub fn catalog_mut(&mut self) -> &mut catalog::Catalog {
&mut self.catalog
}
/// 获取借阅服务
pub fn lending(&self) -> &lending::LendingService {
&self.lending
}
/// 获取可变借阅服务
pub fn lending_mut(&mut self) -> &mut lending::LendingService {
&mut self.lending
}
}
impl Default for Library {
fn default() -> Self {
Self::new()
}
}
```
**6. 目录服务 (services/catalog.rs)**
```rust
//! 图书目录管理服务
use std::collections::HashMap;
use crate::models::Book;
use crate::utils::validation;
/// 图书目录错误类型
#[derive(Debug)]
pub enum CatalogError {
/// ISBN已存在
DuplicateIsbn(String),
/// ISBN不存在
IsbnNotFound(String),
/// ISBN格式无效
InvalidIsbn(String),
}
/// 图书目录服务
pub struct Catalog {
books: HashMap<String, Book>,
}
impl Catalog {
/// 创建一个新的目录服务
pub fn new() -> Self {
Self {
books: HashMap::new(),
}
}
/// 添加一本新书到目录
///
/// # 错误
/// 如果ISBN已存在或无效返回错误
///
/// # 示例
/// ```
/// use library::{Book, services::catalog::Catalog};
///
/// let mut catalog = Catalog::new();
/// let book = Book::new("Rust编程", "张三", "978-1234567890");
///
/// // 首次添加成功
/// assert!(catalog.add_book(book.clone()).is_ok());
///
/// // 重复添加失败
/// assert!(catalog.add_book(book).is_err());
/// ```
pub fn add_book(&mut self, book: Book) -> Result<(), CatalogError> {
let isbn = book.isbn();
// 验证ISBN格式
if !validation::is_valid_isbn(isbn) {
return Err(CatalogError::InvalidIsbn(isbn.to_string()));
}
// 检查ISBN是否已存在
if self.books.contains_key(isbn) {
return Err(CatalogError::DuplicateIsbn(isbn.to_string()));
}
// 添加图书
self.books.insert(isbn.to_string(), book);
Ok(())
}
/// 根据ISBN查找图书
pub fn find_by_isbn(&self, isbn: &str) -> Option<&Book> {
self.books.get(isbn)
}
/// 根据ISBN查找可变图书引用
pub(crate) fn find_by_isbn_mut(&mut self, isbn: &str) -> Option<&mut Book> {
self.books.get_mut(isbn)
}
/// 根据标题查找图书
pub fn find_by_title(&self, title: &str) -> Vec<&Book> {
self.books.values()
.filter(|book| book.title().contains(title))
.collect()
}
/// 根据作者查找图书
pub fn find_by_author(&self, author: &str) -> Vec<&Book> {
self.books.values()
.filter(|book| book.author().contains(author))
.collect()
}
/// 获取所有图书
pub fn all_books(&self) -> Vec<&Book> {
self.books.values().collect()
}
/// 获取可用图书数量
pub fn available_count(&self) -> usize {
self.books.values()
.filter(|book| book.is_available())
.count()
}
/// 获取总图书数量
pub fn total_count(&self) -> usize {
self.books.len()
}
}
impl Default for Catalog {
fn default() -> Self {
Self::new()
}
}
```
**7. 借阅服务 (services/lending.rs)**
```rust
//! 图书借阅管理服务
use std::collections::HashMap;
use crate::models::{Book, User, UserId};
use crate::services::catalog::Catalog;
/// 借阅记录
#[derive(Debug)]
pub struct LoanRecord {
user_id: UserId,
isbn: String,
loan_date: chrono::DateTime<chrono::Utc>,
due_date: chrono::DateTime<chrono::Utc>,
}
/// 借阅错误类型
#[derive(Debug)]
pub enum LendingError {
/// 用户不存在
UserNotFound(UserId),
/// 图书不存在
BookNotFound(String),
/// 图书不可用(已借出)
BookUnavailable(String),
/// 用户账户未激活
UserInactive(UserId),
/// 用户已达到最大借阅限制
BorrowLimitReached(UserId),
/// 借阅记录不存在
LoanNotFound,
}
/// 借阅服务
pub struct LendingService {
users: HashMap<UserId, User>,
active_loans: Vec<LoanRecord>,
max_loans_per_user: usize,
loan_duration_days: i64,
}
impl LendingService {
/// 创建一个新的借阅服务
pub fn new() -> Self {
Self {
users: HashMap::new(),
active_loans: Vec::new(),
max_loans_per_user: 5,
loan_duration_days: 14,
}
}
/// 设置每位用户的最大借阅数量
pub fn set_max_loans_per_user(&mut self, max: usize) {
self.max_loans_per_user = max;
}
/// 设置借阅期限(天数)
pub fn set_loan_duration(&mut self, days: i64) {
self.loan_duration_days = days;
}
/// 添加用户
pub fn add_user(&mut self, user: User) {
self.users.insert(user.id(), user);
}
/// 查找用户
pub fn find_user(&self, user_id: UserId) -> Option<&User> {
self.users.get(&user_id)
}
/// 查找可变用户引用
fn find_user_mut(&mut self, user_id: UserId) -> Option<&mut User> {
self.users.get_mut(&user_id)
}
/// 借阅图书
pub fn borrow_book(
&mut self,
user_id: UserId,
isbn: &str,
catalog: &mut Catalog
) -> Result<(), LendingError> {
// 检查用户是否存在
let user = self.find_user_mut(user_id)
.ok_or(LendingError::UserNotFound(user_id))?;
// 检查用户是否激活
if !user.is_active() {
return Err(LendingError::UserInactive(user_id));
}
// 检查用户是否达到借阅上限
if user.borrowed_books().len() >= self.max_loans_per_user {
return Err(LendingError::BorrowLimitReached(user_id));
}
// 检查图书是否存在并可借
let book = catalog.find_by_isbn_mut(isbn)
.ok_or_else(|| LendingError::BookNotFound(isbn.to_string()))?;
if !book.is_available() {
return Err(LendingError::BookUnavailable(isbn.to_string()));
}
// 更新图书状态
book.mark_borrowed();
// 更新用户借阅记录
user.borrow_book(isbn);
// 创建借阅记录
let now = chrono::Utc::now();
let due_date = now + chrono::Duration::days(self.loan_duration_days);
self.active_loans.push(LoanRecord {
user_id,
isbn: isbn.to_string(),
loan_date: now,
due_date,
});
Ok(())
}
/// 归还图书
pub fn return_book(
&mut self,
user_id: UserId,
isbn: &str,
catalog: &mut Catalog
) -> Result<(), LendingError> {
// 检查用户是否存在
let user = self.find_user_mut(user_id)
.ok_or(LendingError::UserNotFound(user_id))?;
// 检查图书是否存在
let book = catalog.find_by_isbn_mut(isbn)
.ok_or_else(|| LendingError::BookNotFound(isbn.to_string()))?;
// 更新用户借阅记录
if !user.return_book(isbn) {
return Err(LendingError::LoanNotFound);
}
// 更新图书状态
book.mark_returned();
// 移除借阅记录
let loan_index = self.active_loans.iter()
.position(|loan| loan.user_id == user_id && loan.isbn == isbn)
.ok_or(LendingError::LoanNotFound)?;
self.active_loans.remove(loan_index);
Ok(())
}
/// 获取用户的所有借阅
pub fn get_user_loans(&self, user_id: UserId) -> Vec<&LoanRecord> {
self.active_loans.iter()
.filter(|loan| loan.user_id == user_id)
.collect()
}
/// 获取所有逾期借阅
pub fn get_overdue_loans(&self) -> Vec<&LoanRecord> {
let now = chrono::Utc::now();
self.active_loans.iter()
.filter(|loan| loan.due_date < now)
.collect()
}
}
impl Default for LendingService {
fn default() -> Self {
Self::new()
}
}
```
**8. 工具模块 (utils/mod.rs)**
```rust
//! 内部工具函数
pub mod validation;
```
**9. 验证工具 (utils/validation.rs)**
```rust
//! 数据验证工具
/// 检查ISBN是否有效
///
/// 简化版实现,仅检查基本格式
pub fn is_valid_isbn(isbn: &str) -> bool {
// 移除所有连字符和空格
let isbn = isbn.replace(['-', ' '], "");
// ISBN-13应为13位数字
if isbn.len() != 13 {
return false;
}
// 检查是否全为数字
isbn.chars().all(|c| c.is_ascii_digit())
}
/// 检查邮箱格式是否有效
pub fn is_valid_email(email: &str) -> bool {
// 简化版邮箱验证
email.contains('@') && email.split('@').count() == 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid_isbn() {
assert!(is_valid_isbn("978-1234567890"));
assert!(is_valid_isbn("9781234567890"));
}
#[test]
fn test_invalid_isbn() {
assert!(!is_valid_isbn("978-12345")); // 太短
assert!(!is_valid_isbn("978-1234567890X")); // 包含非数字
}
#[test]
fn test_valid_email() {
assert!(is_valid_email("user@example.com"));
}
#[test]
fn test_invalid_email() {
assert!(!is_valid_email("user@"));
assert!(!is_valid_email("user"));
assert!(!is_valid_email("user@domain@example"));
}
}
```
### 示例应用程序
让我们创建一个简单的命令行应用程序,展示如何使用我们的图书馆管理系统:
**10. 主程序 (main.rs)**
```rust
//! 图书馆管理系统示例应用
use library::{Book, User, new_library};
fn main() {
println!("=== 图书馆管理系统 ===");
// 创建图书馆实例
let mut library = new_library();
// 添加图书
let books = [
Book::new("Rust编程艺术", "张三", "978-1234567890"),
Book::new("系统设计实践", "李四", "978-0987654321"),
Book::new("数据结构与算法", "王五", "978-5432109876"),
];
for book in &books {
match library.catalog_mut().add_book(book.clone()) {
Ok(_) => println!("添加图书: {}", book),
Err(e) => println!("添加图书失败: {:?}", e),
}
}
// 添加用户
let users = [
User::new(1, "赵六", "zhaoliu@example.com"),
User::new(2, "钱七", "qianqi@example.com"),
];
for user in &users {
library.lending_mut().add_user(user.clone());
println!("添加用户: {}", user);
}
// 借阅图书
let user_id = 1;
let isbn = "978-1234567890";
match library.lending_mut().borrow_book(user_id, isbn, library.catalog_mut()) {
Ok(_) => println!("用户 {} 成功借阅图书 {}", user_id, isbn),
Err(e) => println!("借阅失败: {:?}", e),
}
// 查看用户借阅情况
if let Some(user) = library.lending().find_user(user_id) {
println!("用户 {} 已借阅的图书:", user.name());
for isbn in user.borrowed_books() {
if let Some(book) = library.catalog().find_by_isbn(isbn) {
println!(" - {}", book);
}
}
}
// 归还图书
match library.lending_mut().return_book(user_id, isbn, library.catalog_mut()) {
Ok(_) => println!("用户 {} 成功归还图书 {}", user_id, isbn),
Err(e) => println!("归还失败: {:?}", e),
}
// 查看图书馆统计信息
println!("\n=== 图书馆统计 ===");
println!("总图书数: {}", library.catalog().total_count());
println!("可借图书数: {}", library.catalog().available_count());
}
```
### 项目配置
**11. 包配置 (Cargo.toml)**
```toml
[package]
name = "library"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
description = "A modular library management system"
[dependencies]
chrono = "0.4"
[dev-dependencies]
criterion = "0.5"
[lib]
name = "library"
path = "src/lib.rs"
[[bin]]
name = "library-cli"
path = "src/main.rs"
```
## 4.7 总结
在本章中我们探索了Rust的模块系统学习了如何组织和结构化大型项目。我们讨论了以下关键概念
1. **模块层级设计**:使用`mod`关键字创建模块树,通过文件系统组织代码
2. **可见性控制**:使用`pub`及其变体控制API的暴露范围
3. **工作空间管理**使用工作空间组织多个相关crate
4. **文档测试**:编写可执行的文档,确保代码示例始终有效
通过图书馆管理系统的实例项目,我们实践了这些概念,构建了一个模块化、可维护的系统。这种结构化方法不仅提高了代码的可读性和可维护性,还促进了团队协作和代码重用。
### 关键要点回顾
- 使用模块组织相关功能,形成清晰的代码结构
- 遵循"最小公开原则"只暴露必要的API
- 利用文件系统组织模块,使代码结构直观
- 使用工作空间管理大型项目中的多个crate
- 编写文档测试,确保文档与代码同步
### 实践建议
1. **模块设计**:先设计模块结构,再编写实现代码
2. **API设计**:谨慎考虑哪些项应该公开,哪些应该保持私有
3. **文档优先**:编写文档和测试,然后实现功能
4. **渐进式重构**:随着项目增长,不断调整模块结构
在下一章中我们将探索Rust的并发安全特性学习如何利用所有权系统编写高效、安全的并发代码。