第二十五天:用 dokka 产生 API 文件

当我们在写函式库或框架的时候,通常表示这段逻辑很常用到,希望藉由抽取成函式库或框架来重复使用,减少重造轮子、也更好维护。而身为函式库或框架的作者,当然会希望有愈多使用者愈好,让自己的作品能发挥更大的价值与影响力。不过现实状况是,要吸引愈多人用,文件是最基本的条件,毕竟至少要让别人知道怎麽用吧?

以函式库或框架来说,文件有两种:一种是指南的型式,比较像教学文件,以情境导向的型式,向使用者说明要怎麽使用;另一种是 API 文件,型式比较像规格说明,会明确地把函式库或框架里的每一个类、方式都详细的列表,清楚说明其可接受的输入及输出等规格细节。两种文件型式及用途各有不同,开发者可依情境选择使用。指南通常都是在初学时入门上手用,主要的目标是学会常见的用法;API 文件的用法比较像目录或食谱,通常会依照想要了解的类别及方法直接查询其规格,不会一页一页地翻。

不过同样身为开发者的我们都知道,工程师都讨厌别人不写文件,但其实自己也不喜欢写文件。所以若文件可以在程序码写好的时候就自动产生,是不是就太美妙了?或者说,就算没时间好好写教学指南型的文件,至少也要提供 API 这种规格说明书的文件吧?

KDoc 文件语法

其实在程序码里以注解的型式描述规格,再用工具产生 API 文件的这种作法已经行之有年,各个程序语言也都多有这种工具。以 Java 来说,JavaDoc 就是标准的例子。而 Kotlin 当然也有对应的设计,写在程序码里的语法就叫 KDoc,而依据 KDoc 产生 API 文件的工具就叫 Dokka。

KDoc 的在区块标记上基本上与 JavaDoc 相同,多支援了一些 Kotlin 独有的语法设计,并新增支援 Markdown 语法的行内标记。KDoc 将文件内容放在注解内,其以 /** 开头并以 */ 结尾,每一行注解都以 * 开头。一般照惯例,注解的第一行文字是摘要,空一行後的第二段则是详细描述。再空一行後才开始用 @ 字元开头来标记类别或方法的型别和说明。

以我们的 ShoppingCart 类别为例,可以标记成这样:

/**
 * ShoppingCart class
 *
 * A simple shopping cart class that could add product, count the number of products, sum for total price
 *
 * @property products A mutable list that contain all products
 * @constructor Create an empty cart
 */
class ShoppingCart {
  private val products = mutableListOf<Product>()

  /**
   * Add a [product] in shopping cart
   *
   * @param product
   * @return unit
   */
  fun add(product: Product) {
    products.add(product)
  }

  /**
   * Calculate products' price
   *
   * @return The sum of [products] prices
   */
  fun totalPrice(): Int {
    return products.sumOf { it.price }
  }

  /**
   * Calculate the quantity of products
   *
   * @return The quantity of [products]
   */
  fun count(): Int {
    return products.count()
  }

  /**
   * Dummy integer generator
   *
   * @return Random integer
   */
  fun dummyInt(): Int {
    return Random.nextInt()
  }

  /**
   * Dummy boolean generator
   *
   * @return Random boolean
   */
  fun dummyBoolean(): Boolean {
    return Random.nextBoolean()
  }
}

在这边介绍几个常用的 @ 标记:

  • @constructor:描述类别主要建构子
  • @property name:描述类别属性,其格式为 @property 属性名 描述
  • @throws class@exception class:描述方法会抛出的例外
  • @return name:描述方法回传值

Dokka 文件引擎

当我们用 KDoc 语法在程序码上纪录文件後,接着我们就可以用 Dokka 这个工具来爬取这些文件标记,然後产生可借阅览的文件。Dokka 支援同时混合 Java 及 Kotlin 的专案,也就是说它会用 JavaDoc 来分析 Java 档、用 KDoc 来分析 Kotlin 档。Dokka 也支援多种格式的输出,包括:

  • html:HTML 网页是预设的输出格式
  • javadoc:输出成 JDK 的 Javadoc 的型式,Kotlin 的类别会被转译成 Java
  • gfm:GitHub 风格的 Markdown
  • jekyll:Jekyll 相容的 Markdown

我们接下来会示范如何产生 HTML 格式的文件。

安装 Dokka 引擎

因为 Dokka 预设就提供 CLI、Gradle、Maven 等多种使用方式,所以要在 Kotlin 专案里安装 Dokka 引擎很简单,只需打开 build.gradle.kts 套用 Dokka Plugin 即可。

plugins {
    // ...
    id("org.jetbrains.dokka") version "1.5.30"
}

老样子,设定好 Plugin 後别忘了 Reload,让 IntelliJ IDEA 帮我们把 Dokka 引擎载入进 Gradle,完成後就会在 documentation 群组底下看到多了 dokkaHtmldokkaJavadocdokkaGfmdokkaJekyll 等指令可以使用。

以 Dokka 产生文件

有了 Dokka Plugin 後要产生文件就变得非常简单,直接点选 Gradle 面板里 dokkaHtml Task 即可!(依据输出需求的不同可以选择不同的格式指令)

指令跑完後,HTML 版的文件就会被产生在 ./build/dokka/html,我们可以直接把网页用浏览器打开来,就看会到像下图这样的文件网页:

小结

今天我们介绍了 KDoc 及 Dokka 这两个跟产生文件有关的语法及文件引擎,像这样使用文件引擎产生文件提供给使用者查阅几乎已经是开放原始码圈的起手式,身为开发者就算懒得写文件,至少也要懂得如何自动产生文件,体贴使用者也是作者负责任的表现。虽然这两个都是 Kotlin 开发生态系的工具,但同样的概念也可以应用到不同的程序语言,读者可以用「程序语言的名称」+「文件引擎」等关键字做搜寻,应该就会找到适合自己的工具,希望看完今天的教学後对您有帮助。

当然,在本机产生文件只是整个 DevOps 流程的第一步,接下来我们就要透过 TeamCity 让这个环节自动在 CI 流程里发生,敬请期待!

参考资料


<<:  Day16 RTCPeerConnection: Offer / Answer

>>:  [铁人赛 Day15] 如何分析 memoization 的成效呢?Profiler API

MVC 架构

MVC 分别是 Model, View, Controller, 是一种软件架构, View 负责使...

后续说明

很遗憾,由于假期原因,没能够及时更新,中断了更新。 不过这个系列还是会继续更新下去的,直到结束。 未...

Day30 ATT&CK for ICS - Inhibit Response Function(2)

T0804 Block Reporting Message 攻击者尝试阻止回报封包,这些封包内容可能...

在线传单制作工具介绍

让我们谈谈如何制作成功的商业传单进行促销。宣传传单的主要目的是吸引注意力。无论您是要开设商店还是想吸...

Day25. Blue Prism让你远离挑灯夜战的日子 –BP自动登打订单

昨天加班加的凶, 到现在为止都还在挑灯夜战, 不过,在不景气的日子人就要想着变通, 才会有机会的到来...