使用包、箱和模块管理不断增长的项目

当您编写大型程序时,组织代码将变得越来越重要。 通过将相关功能分组并使用不同的功能分隔代码,您将清楚地知道在哪里可以找到实现特定功能的代码,以及在哪里可以更改功能的运作方式。

我们到目前为止编写的程序都在一个文件中的一个模块中。 随着项目的增长,您应该通过将其拆分为多个模块,然后再拆分为多个文件来组织代码。 一个包可以包含多个二进制 crate,并可选择一个库 crate。 随着包的增长,您可以将部分内容提取到单独的 crate 中,这些 crate 将成为外部依赖项。 本章涵盖所有这些技术。 对于包含一组相互关联的包的大型项目,这些包会一起演变,Cargo 提供了工作区,我们将在 第 14 章的“Cargo 工作区”章节中介绍。

我们还将讨论封装实现细节,这使您可以在更高的级别重用代码:一旦您实现了操作,其他代码可以通过其公共接口调用您的代码,而无需知道实现的工作原理。 您编写代码的方式定义了哪些部分是公开的,供其他代码使用,以及哪些部分是私有的实现细节,您保留更改的权利。 这是限制您必须记住的细节数量的另一种方法。

一个相关的概念是作用域:编写代码的嵌套上下文具有一组定义为“在作用域内”的名称。 在阅读、编写和编译代码时,程序员和编译器需要知道特定位置的特定名称是指变量、函数、结构体、枚举、模块、常量还是其他项,以及该项的含义。 您可以创建作用域并更改哪些名称在作用域内或在作用域外。 您不能在同一作用域中拥有两个同名的项; 有工具可以解决名称冲突。

Rust 有许多功能可让您管理代码的组织,包括哪些细节被暴露,哪些细节是私有的,以及程序中每个作用域中的名称。 这些功能,有时统称为模块系统,包括

  • 包: 一个 Cargo 功能,可让您构建、测试和共享 crate
  • 箱 (Crates): 产生库或可执行文件的模块树
  • 模块use: 让您控制路径的组织、作用域和隐私
  • 路径: 一种命名项(如结构体、函数或模块)的方式

在本章中,我们将涵盖所有这些功能,讨论它们如何相互作用,并解释如何使用它们来管理作用域。 最后,您应该对模块系统有扎实的了解,并且能够像专业人士一样处理作用域!