Kotlinv2.4.0

库作者编写信息化文档的最佳做法

您为库提供的文档至关重要。 它可以决定用户是否会调研您的库,是否会在其项目中采用它,以及在遇到困难时是否会坚持使用。 当今的开发者在语言、库、框架和平台之间拥有前所未有的选择余地。 因此,吸引并告知您的用户至关重要;否则,他们可能会转而寻求其他选择。

在库的早期版本中,来自用户的反馈会很稀少。 幸运的是,创建和完善文档可以作为一个反馈循环,大大提高项目的质量。 因此,创建文档绝不应被视为一种负担,也不应在创建库时被推后优先级。

有效的文档不仅能告知用户,还能驱动库的开发和完善。 以下是文档指导开发过程的几种关键方式:

  • 您应该能够用几段话解释您的库是做什么的,谁会从中受益,以及与替代方案相比有哪些优势。如果您做不到这一点,请重新考虑项目的范围和目标。
  • 您应该能够创建一个“快速入门指南”,让潜在用户能够尽快上手运行。所谓“尽快”取决于问题领域,但您可以与其它平台上的同类库进行比较。该指南应将用户带入一个反馈循环,使过程变得越来越简单快捷,同时始终产出可靠的结果。创建此指南将帮助您识别可能阻碍用户进度的难度陡增(cliff edges)。
  • 为函数编写文档的行为会迫使您考虑所有边缘情况,例如输入的有效范围、可能抛出的异常,以及性能随工作量增加而下降的情况。这通常可以改进函数签名和底层实现。
  • 如果初始化库所需的代码量总是超过完成任务所需的代码量,请重新考虑您的配置选项。
  • 如果您无法创建使用标准选项执行基本任务的清晰示例,请考虑针对日常使用优化您的 API。
  • 如果您无法在不使用真实数据源和联机服务的情况下演示如何测试您的库,请考虑为访问网络(以及通常意义上的外部世界)的组件提供测试替身。

您越早为库提供文档,真实用户就能越早对其进行测试。 来自这些测试的反馈随后可用于改进设计。

提供全面的文档

您的库必须提供足够的文档,让用户能够以最小的工作量采用它。 该文档应包括:

  • 快速入门指南
  • 对 API 的深入描述
  • 常见用例的详细示例(也称为指南)
  • 指向博客、文章、在线讲座和会议演讲等资源的链接

快速入门指南应涵盖您的库如何与支持的构建系统集成。 它应包括对最常用实体的简短描述,以及如何使用它们的小示例。 在库与外部世界交互的每个点上,都要指定配置环境的必要步骤,以及如何验证这些步骤是否已成功完成。 如果不需要任何步骤,请显式说明。

如果可能,为您支持的库的每个版本提供单独版本的文档。 这可以防止用户查看过时或过于超前的信息。 如果无法做到这一点,请清楚地标记文档中与已重新设计的 API 部分相关的章节。

为您的用户创建用户画像

在没有明确了解目标受众的情况下创建和评估文档是具有挑战性的。 为阅读您文档的用户类型定义多个用户画像可能会有所帮助。

考虑用户的约束条件,例如他们需要操作的预先存在的软件栈。 文档的审阅者可以采用这些用户画像来使他们的结论更有意义。

当您缺乏关于用户的具体信息时,最好保持谨慎。 例如,不要假设用户精通 Kotlin 的最新或最高级功能。 尽可能保持代码示例简单。

当由于时间、预算限制或保密协议而无法咨询真实用户时,用户画像特别有用。 随着时间的推移,当您对用户有了更好的了解时,请完善用户画像以更准确地匹配他们的需求。

尽可能通过示例编写文档

通过示例编写文档是向用户解释基本概念的最具成本效益的方法之一。 只要有可能,请提供简单明了的代码示例,帮助解释或演示正在讨论的当前主题或概念。

KDoc 文档格式允许您在文档注释中使用 Markdown 内联标记。 在注释中使用内联代码片段来展示 API 的用法。 有关示例,请参阅协程库测试调度器的源代码渲染后的文档

提供此类示例可以避免编写关于预期输入、可能输出和失败模式的冗长描述。 但是,每个示例的上下文以及适用的环境都需要明确。 仅提供一个未加注释的示例程序文件夹并不算作文档。

详尽记录您的 API

每个受支持的 API 入口点都应使用 KDoc 进行记录。

Kotlin 的文档引擎 Dokka 在默认情况下仅在其输出中包含公共声明。正如 简洁性 章节中所讨论的,您应该尽量减少公共 API,并移除不希望用户访问的公共入口点。如果有无法通过控制可见性来向用户隐藏的 API,请使用 suppress 指令 将其从文档中排除。

在描述入口点时,首先要对其功能进行清晰、高层次的描述。 避免仅用自然语言重复签名。

例如,不要说“接受一个 String 并返回一个 Connection”,而应说“尝试连接到由输入字符串指定的数据库,成功则返回一个 Connection,否则抛出 ConnectionTimeoutException”。

指定每个输入的预期值以及不同输入下的行为。 解释有效值的范围以及提供无效值时会发生什么。 例如,如果字符串输入应该是 URL,请描述当字符串为空、无效、使用不受支持的协议或引用不存在的位置时会发生什么。

记录 API 入口点可能抛出的每个异常。在一般描述中讨论故障条件,并将异常部分留给详细信息。这可以增强可读性并帮助读者集中注意力。相反,应将这些信息有机地整合到一般描述中。只要有可能就提供用法示例,这也有助于用户理解如何正确使用 API。

我们建议学习技术写作以提高文档的清晰度和有效性。 考虑探索相关资源,例如 Google 的这门课程(第一部分第二部分)。

记录 lambda 参数

当 API 入口点接受 lambda 时,用户正在提供您的库将代表他们执行的某些功能。 这至少需要在两个方面提供额外的文档。

首先,记录如果 lambda 抛出异常会发生什么。考虑解决以下问题:

  • 这是否会导致立即失败,lambda 是否会被重复调用,或者是否存在回退行为?
  • 如果调用函数需要退出,它会重新抛出 lambda 抛出的异常还是抛出一个不同的异常?
  • 如果异常不同,它是否会包含原始异常?

此外,除非函数被声明为内联,否则请记录与并发相关的任何特殊行为。 确保涵盖以下内容:

  • lambda 是否会在与调用者相同的线程中被调用?
  • 如果 lambda 不在与调用者相同的线程中被调用,它将在哪个线程(或线程池)中被调用?
  • lambda 的多个副本是否可以并行运行?
  • 还有哪些其他作业可能正在使用该线程?
  • 用户是否可以指定库要使用的线程?
  • 在调用多个 lambda 的情况下,对于顺序提供了哪些保证?

在文档中使用显式链接

API 入口点完全独立于库中其他功能的情况非常罕见。 通常,必须按特定顺序进行调用,执行特定任务有多种选择,并且执行相关任务的入口点以类似方式使用。 例如,像 formatparse 这样的函数彼此镜像。

使用 @see 标签或 内部链接 使这些关系在您的文档中显式化。 这可以通过使用户能够将信息块状化(chunk),构建更完整的库心理图谱,从而为读者提供帮助。

尽可能保持自包含

在描述什么是有效输入时,很容易仅仅引用相关标准,例如由 W3C、IEEE 或 Unicode 联盟制定的标准。 虽然提供这些链接会有所帮助,但不应强迫读者查阅外部规范来发现基本信息,例如空白字符集。

文档应尽可能保持自包含。 它应该提供足够的信息,让用户了解每个 API 入口点的典型用法。 对于在普通使用中不会发生的边缘情况,您可以引导用户参考外部文档。

使用简单的英语

在创建文档时,使用简单明了的英语非常重要。 这可以确保您的内容能够被全球受众访问,包括那些母语不是英语的人。 避免使用可能使读者感到困惑的复杂词汇、行话、拉丁语短语或习语。 相反,请使用直截了当的语言和简洁的句子。

简单的英语也使文档在需要时更容易翻译。 清晰、无歧义的文本降低了误解的风险,并提高了整体可读性。

下一步

如果您还没有看过,请考虑查看以下页面: