文章目录

Elixir 文档:@doc 与 @moduledoc

发布于 2026-04-03 23:13:09 · 浏览 2 次 · 评论 0 条

Elixir 文档:@doc 与 @moduledoc

在 Elixir 中编写清晰、可维护的代码,离不开良好的文档。Elixir 提供了两个内置属性 @doc@moduledoc,用于为函数和模块添加文档字符串。这些文档不仅帮助团队成员理解代码,还能通过工具自动生成漂亮的 HTML 文档。以下是手把手教你如何正确使用它们。


1. 理解 @moduledoc:为整个模块写说明

创建一个新模块时,先用 @moduledoc 描述这个模块是干什么的。

  1. 在模块定义的最顶部(紧接在 defmodule 后)写下 @moduledoc
  2. 用双引号包裹一段或多段文字,说明模块的用途、设计思路或使用场景。
  3. 如果模块不需要文档(例如私有工具模块),显式设为 false,避免生成空文档。

示例:

defmodule MathUtils do
  @moduledoc """
  提供常用的数学计算辅助函数。

  当前包含:
  - 阶乘计算
  - 平方根近似
  """

  # 函数定义...
end

若模块仅供内部使用:

defmodule MyApp.InternalHelper do
  @moduledoc false

  def helper_function(), do: :ok
end

2. 使用 @doc:为每个函数写说明

每个公开函数都应该有对应的 @doc

  1. 在函数定义前一行添加 @doc
  2. 描述函数作用、参数含义、返回值类型及可能的异常
  3. 支持 Markdown 语法,可加粗、列表、代码块等,提升可读性。
  4. 同样,若函数不应出现在文档中(如测试专用函数),设 @doc false

示例:

defmodule MathUtils do
  @moduledoc "提供数学工具函数"

  @doc """
  计算非负整数的阶乘。

  ## 参数
  - `n`: 一个非负整数 (`integer >= 0`)

  ## 返回
  - `integer`: n 的阶乘结果

  ## 示例
      iex> MathUtils.factorial(5)
      120

      iex> MathUtils.factorial(0)
      1
  """
  def factorial(0), do: 1
  def factorial(n) when n > 0 do
    n * factorial(n - 1)
  end

  @doc false
  def private_helper(), do: :secret
end

注意:示例代码写在 iex> 提示符下,这是 Elixir 文档的标准写法,ExUnit 可自动将其作为 doctest 运行。


3. 生成并查看文档

写好 @doc@moduledoc 后,可通过 ExDoc 工具生成 HTML 文档。

  1. 在项目根目录的 mix.exs 文件中,确保已添加 ex_doc 依赖:
defp deps do
  [
    {:ex_doc, "~> 0.30", only: :dev, runtime: false}
  ]
end
  1. 运行命令安装依赖并生成文档:
mix deps.get
mix docs
  1. 打开生成的文档:文档默认输出到 _build/dev/doc/ 目录,双击 index.html 即可在浏览器中查看。

生成的页面会按模块组织,点击任一模块即可看到其 @moduledoc 内容,每个函数下方显示对应的 @doc 说明和示例。


4. 最佳实践与常见错误

遵循以下规则,让你的文档更专业、更实用。

  1. 始终使用完整句子,以大写字母开头,句尾加句号。
  2. 避免重复模块名:在 @doc 中不要写“此函数属于 MathUtils 模块”,读者已经知道上下文。
  3. 示例必须真实可运行:确保 iex> 后的代码在 IEx 中粘贴后能正确执行。
  4. 不要在文档中写 TODO 或占位符:如“此处待补充”——要么写清楚,要么暂时不写。
  5. 私有函数通常不加 @doc:除非你希望它出现在文档中(一般不推荐)。

下面是一个对比表,展示良好与不良文档的差异:

场景 不推荐写法 推荐写法
模块说明 @moduledoc "工具" @moduledoc "提供日期解析与格式化的工具函数,支持 ISO8601 与本地化格式。"
函数说明 @doc "算平方" @doc "返回给定数字的平方。\n\n参数x可为整数或浮点数。"
示例代码 # 返回 4 iex> Math.square(2)\n4

5. 高级技巧:动态文档与多语言

虽然不常用,但 @doc@moduledoc 支持动态内容。

  1. 使用字符串插值(谨慎使用):
@version Mix.Project.config()[:version]
@moduledoc "当前版本:#{@version}"
  1. 从外部文件加载长文档(适合超长说明):
@moduledoc File.read!("README.md")

但注意:这会让文档失去模块上下文,仅在特殊场景(如 DSL 库)中使用。

  1. 多语言文档? Elixir 官方生态不直接支持,但可通过条件编译实现(不推荐)。通常建议统一使用英文,确保社区通用性。

6. 验证文档质量

Elixir 提供了自动化检查手段。

  1. 运行 doctest:确保所有 iex> 示例能通过测试:
mix test --doctest-modules
  1. 启用编译器警告:在 mix.exs 中配置,让编译器提醒缺失文档:
def project do
  [
    # ...
    dialyzer: [flags: [:missing_return, :extra_unused_vars]],
    elixirc_options: [warnings_as_errors: true]
  ]
end

虽然 Elixir 编译器本身不强制文档,但配合 Credo 或 Dialyzer 可设置规则,要求所有 public 函数必须有 @doc

例如,在 .credo.exs 中添加:

%{
  check_for_doc_in_module: true,
  check_for_doc_in_public_functions: true
}

这样,提交代码前运行 mix credo 就能发现遗漏。


保存你的 .ex 文件后,重新生成文档,确认所有说明清晰可见。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文