0Pricing
R Academy · 课时

使用 usethis 和 devtools 组织软件包结构

使用 usethis 辅助工具搭建软件包目录、DESCRIPTION 和 NAMESPACE

使用 usethis 和 devtools 组织软件包结构 是 CoddyKit 上的免费 R Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

为什么要构建 R 程序包

R 程序包是共享可复用代码、数据和文档的标准方式。即使您从不将程序包发布到 CRAN,将代码打包也能促使您遵循良好实践:为函数编写文档、添加单元测试,并使用清晰的命名空间。devtools 和 usethis 让整个过程变得简单明了。

创建程序包骨架

usethis::create_package('~/mypackage') 会创建一个包含所有必需文件的目录:DESCRIPTION、NAMESPACE 和 R/ 目录。它还会自动在 RStudio 中打开新项目。

# library(usethis)
# library(devtools)
#
# usethis::create_package('~/mypackage')
#
# Creates:
# mypackage/
#   DESCRIPTION     <- package metadata
#   NAMESPACE       <- exported symbols (auto-managed by roxygen2)
#   R/              <- your R source files
#   .Rbuildignore   <- files to exclude from package builds

DESCRIPTION 文件

DESCRIPTION 文件是程序包清单。其主要字段包括:

  • Title — 单行描述(使用标题格式,不加句号)
  • Version — 语义化版本号(例如 0.1.0)
  • Author / Authors@R — 程序包作者
  • Depends — 所需的 R 版本
  • Imports — 程序包调用的其他程序包
  • License — 例如 MIT、GPL-3
# DESCRIPTION example:
# Package: mypackage
# Title: Tools for Analyzing Survey Data
# Version: 0.1.0
# Authors@R: person('Alice', 'Smith', email='alice@example.com', role=c('aut','cre'))
# Description: Provides helper functions for cleaning and summarizing survey responses.
# Depends: R (>= 4.1.0)
# Imports: dplyr, stringr
# License: MIT + file LICENSE

使用 use_r() 添加函数

usethis::use_r('my_function') 会创建 R/my_function.R 并打开该文件进行编辑。R/ 中的每个文件应包含一个函数,或一小组关系密切的函数。不要在程序包文件中使用 source() 调用。

# usethis::use_r('add')  # creates R/add.R
#
# Write your function in R/add.R:
# add <- function(x, y) {
#   if (!is.numeric(x) || !is.numeric(y)) stop('x and y must be numeric')
#   x + y
# }
#
# Then document it with roxygen2 comments above the function.

devtools::load_all() — 开发循环

devtools::load_all()(RStudio 中的键盘快捷键为 Ctrl+Shift+L)会模拟安装并加载程序包。它会将 R/ 中的所有文件加载到当前会话中,但不会实际安装程序包。这是迭代开发周期的核心。

# Development loop:
# 1. Edit R/add.R
# 2. devtools::load_all()   # Ctrl+Shift+L
# 3. add(2, 3)              # test interactively
# 4. Go to step 1
#
# load_all() is much faster than install.packages()
# because it skips compilation and installation steps.

devtools::check() — 全面检查

devtools::check()(Ctrl+Shift+E)会运行 R CMD check — CRAN 使用的综合检查套件。它会检查文档、测试、示例、命名空间等内容。请以 0 个 ERROR、0 个 WARNING 以及尽可能少的 NOTE 为目标。

# devtools::check()  # runs R CMD check
#
# Common errors to fix:
# ERROR:   Undocumented function 'add' => add roxygen2 docs
# WARNING: No NAMESPACE file => run devtools::document()
# NOTE:    No examples => add @examples in roxygen2
# NOTE:    Dependencies in DESCRIPTION not used => clean up Imports

R/ 目录结构

所有源文件都放在 R/ 中。常见约定包括:

  • 每个函数族使用一个文件(例如 R/utils.R、R/plot_helpers.R)
  • 使用 R/data.R 编写数据集文档
  • 使用 R/zzz.R 存放 .onLoad() 和 .onAttach() 钩子

R/ 中不能包含子目录 — 所有文件都应直接位于顶层。

# Typical R/ directory for a small package:
# R/
#   add.R          <- add() function + documentation
#   subtract.R     <- subtract() function
#   utils.R        <- internal helpers (not exported)
#   data.R         <- documentation for bundled datasets
#   package.R      <- @docType package documentation

man/ 目录

man/ 包含 .Rd 帮助文件,每个导出的函数对应一个文件。您绝不应手动编辑这些文件 — 它们由 devtools::document() 根据 roxygen2 注释生成。请将它们与源代码一起提交。

# man/ is auto-generated:
# man/
#   add.Rd         <- generated from @title, @param etc. in R/add.R
#   subtract.Rd    <- generated from R/subtract.R
#
# Regenerate with:
# devtools::document()  # also updates NAMESPACE
#
# Never edit .Rd files directly -- changes will be overwritten
cat('Always edit roxygen2 comments, never man/*.Rd files directly
')

tests/ 目录

usethis::use_testthat() 会创建 tests/testthat/ 目录,并将 testthat 添加到 DESCRIPTION 中。在该目录内创建名为 test-*.R 的测试文件。使用 devtools::test()(Ctrl+Shift+T)运行所有测试。

# Set up testing:
# usethis::use_testthat()
#
# Creates:
# tests/
#   testthat.R            <- runner script (do not edit)
#   testthat/
#     test-add.R          <- your test file
#
# Run tests:
# devtools::test()
# devtools::test_file('tests/testthat/test-add.R')

正确添加依赖项

绝不要在程序包源文件中使用 library(pkg)。请改用以下方式:

  • 使用 usethis::use_package('dplyr') 将程序包添加到 DESCRIPTION 的 Imports 中
  • 使用 pkg::function() 调用函数,或在 roxygen2 中添加 @importFrom pkg function
  • 对于仅在示例或测试中需要的程序包,使用 Suggests
# Add a dependency:
# usethis::use_package('stringr')           # adds to Imports
# usethis::use_package('ggplot2', 'Suggests') # adds to Suggests
#
# In R/my_function.R:
# clean_names <- function(x) {
#   stringr::str_to_lower(stringr::str_trim(x))  # use pkg:: prefix
# }

程序包开发工作流总结

R 程序包开发的标准迭代周期如下:

  1. create_package() — 仅创建一次骨架
  2. use_r('name') — 创建源文件
  3. 编写函数并为其编写文档(roxygen2)
  4. load_all() — 将程序包加载到会话中,以便交互式测试
  5. document() — 重新生成 man/ 和 NAMESPACE
  6. test() — 运行单元测试
  7. check() — 执行完整的 R CMD check

快速检查:DESCRIPTION 字段

DESCRIPTION 中的哪个字段列出了您的程序包直接调用的 R 程序包(硬依赖项)?

程序包结构回顾

R 程序包开发中的关键文件和命令:

  • usethis::create_package() — 创建包含 DESCRIPTION、NAMESPACE 和 R/ 的骨架
  • DESCRIPTION — Title、Version、Imports 和 License 元数据
  • usethis::use_r('name') — 向 R/ 添加源文件
  • devtools::load_all() — 快速迭代式重新加载(Ctrl+Shift+L)
  • devtools::document() — 根据 roxygen2 重新生成 man/
  • devtools::check() — 完整的 R CMD check,目标是 0 个错误和警告
  • 不要在程序包源代码中放置 library() — 请使用 pkg::fn()

常见问题解答

「使用 usethis 和 devtools 组织软件包结构」课时是免费的吗?

是的 — 「使用 usethis 和 devtools 组织软件包结构」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「使用 usethis 和 devtools 组织软件包结构」这节课中我会学到什么?

使用 usethis 辅助工具搭建软件包目录、DESCRIPTION 和 NAMESPACE 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「使用 usethis 和 devtools 组织软件包结构」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 usethis 和 devtools 组织软件包结构
  2. 使用 roxygen2 编写函数文档
  3. 使用 testthat 进行单元测试
  4. CRAN 提交与软件包维护
← 返回 R Academy