Elixir 文档:@doc 与 @moduledoc
在 Elixir 中编写清晰、可维护的代码,离不开良好的文档。Elixir 提供了两个内置属性 @doc 和 @moduledoc,用于为函数和模块添加文档字符串。这些文档不仅帮助团队成员理解代码,还能通过工具自动生成漂亮的 HTML 文档。以下是手把手教你如何正确使用它们。
1. 理解 @moduledoc:为整个模块写说明
创建一个新模块时,先用 @moduledoc 描述这个模块是干什么的。
- 在模块定义的最顶部(紧接在
defmodule后)写下@moduledoc。 - 用双引号包裹一段或多段文字,说明模块的用途、设计思路或使用场景。
- 如果模块不需要文档(例如私有工具模块),显式设为
false,避免生成空文档。
示例:
defmodule MathUtils do
@moduledoc """
提供常用的数学计算辅助函数。
当前包含:
- 阶乘计算
- 平方根近似
"""
# 函数定义...
end
若模块仅供内部使用:
defmodule MyApp.InternalHelper do
@moduledoc false
def helper_function(), do: :ok
end
2. 使用 @doc:为每个函数写说明
每个公开函数都应该有对应的 @doc。
- 在函数定义前一行添加
@doc。 - 描述函数作用、参数含义、返回值类型及可能的异常。
- 支持 Markdown 语法,可加粗、列表、代码块等,提升可读性。
- 同样,若函数不应出现在文档中(如测试专用函数),设
@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 文档。
- 在项目根目录的
mix.exs文件中,确保已添加ex_doc依赖:
defp deps do
[
{:ex_doc, "~> 0.30", only: :dev, runtime: false}
]
end
- 运行命令安装依赖并生成文档:
mix deps.get
mix docs
- 打开生成的文档:文档默认输出到
_build/dev/doc/目录,双击index.html即可在浏览器中查看。
生成的页面会按模块组织,点击任一模块即可看到其 @moduledoc 内容,每个函数下方显示对应的 @doc 说明和示例。
4. 最佳实践与常见错误
遵循以下规则,让你的文档更专业、更实用。
- 始终使用完整句子,以大写字母开头,句尾加句号。
- 避免重复模块名:在
@doc中不要写“此函数属于 MathUtils 模块”,读者已经知道上下文。 - 示例必须真实可运行:确保
iex>后的代码在 IEx 中粘贴后能正确执行。 - 不要在文档中写 TODO 或占位符:如“此处待补充”——要么写清楚,要么暂时不写。
- 私有函数通常不加 @doc:除非你希望它出现在文档中(一般不推荐)。
下面是一个对比表,展示良好与不良文档的差异:
| 场景 | 不推荐写法 | 推荐写法 |
|---|---|---|
| 模块说明 | @moduledoc "工具" |
@moduledoc "提供日期解析与格式化的工具函数,支持 ISO8601 与本地化格式。" |
| 函数说明 | @doc "算平方" |
@doc "返回给定数字的平方。\n\n参数x可为整数或浮点数。" |
| 示例代码 | # 返回 4 |
iex> Math.square(2)\n4 |
5. 高级技巧:动态文档与多语言
虽然不常用,但 @doc 和 @moduledoc 支持动态内容。
- 使用字符串插值(谨慎使用):
@version Mix.Project.config()[:version]
@moduledoc "当前版本:#{@version}"
- 从外部文件加载长文档(适合超长说明):
@moduledoc File.read!("README.md")
但注意:这会让文档失去模块上下文,仅在特殊场景(如 DSL 库)中使用。
- 多语言文档? Elixir 官方生态不直接支持,但可通过条件编译实现(不推荐)。通常建议统一使用英文,确保社区通用性。
6. 验证文档质量
Elixir 提供了自动化检查手段。
- 运行 doctest:确保所有
iex>示例能通过测试:
mix test --doctest-modules
- 启用编译器警告:在
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 文件后,重新生成文档,确认所有说明清晰可见。

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