11月阅读周·编写可测试的JavaScript代码:复杂度之注释篇

举报
叶一一 发表于 2024/11/20 10:15:09 2024/11/20
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读十个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读十个月。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》、《JavaScript异步编程设计快速响应的网络应用》

当前阅读周书籍编写可测试的JavaScript代码

注释

对于可测试的JavaScript,所有即将要测试的函数或方法前面都有相应的注释。根据这些注释,我们(或其他人)可以知道如何进行测试以及测试什么内容。维护代码时,函数(特别是公有函数)前面的注释可以让维护者理解它的意图。大家可能认为测试更重要,或许想用测试取代正确的注释,但我不同意这样做。编写有效的注释并保持更新是开发人员必须要做的一部分日常工作。借助注释理解代码是一个更直接的方法,而不是依赖(或阅读)测试。方法的注释是最重要的,对难以理解的代码所做的任何注释,对于程序员来说都是无价的。重要的是,注释解释了为什么要有该方法、如何构建该方法,利用结构化的注释,也可以很容易地将其转换成HTML文档供大家浏览。

注释和测试不应该是非此即彼的命题。作为一名专业的程序员,应该编写测试并维护注释,至少所有公有方法都应该这样做。对于方法内部不太清楚的上下文环境,只能用注释的方式来解释。如果在函数上编写注释,保证这些注释实时更新是非常重要的。没有注释远远好于错误的注释。

YUIDoc

YUIDoc(https://yui.github.io/yuidoc/)是可以通过npm安装的Node.js包。安装非常简单:

npm -g install yuidocjs

安装之后,可执行文件yuidoc可以将所有的注释转换为HTML。本节,我们讨论的是0.3.28版本,是截止到撰写本文时最新的版本。

YUIDoc注释遵循Javadoc的惯例,以/**开始,并且以*/结束。事实上,任何语言,只要使用/*和*/这种格式的注释,都可以使用YUIDoc生成相应的文档。

YUIDoc提供了7个主标签。每个注释块必须且只能包含一个这样的主标签;这里(https://yui.github.io/yuidoc/syntax/index.html#primary-tags)提供了这些标签的详细列表。

理想情况下,利用函数或者方法的YUIDoc文档,就应该能够编写单元测试了。

使用yuidoc命令行工具生成YUIDoc文档非常简单。然而,YUIDoc生成的文档是多目录的,不像JSDoc(稍后讨论),无法使用YUIDoc生成一个单独的JavaScript文档。除非在代码里调试YUIDoc文档,但一般很少这么做。

典型的命令行如下:

yuidoc -o yuidoc src/yuidoc.json src

这里的yuidoc是输出所有HTML的目录名称,src是JavaScript文件的根目录,以此目录进行遍历从而生成文档。yuidoc.doc配置文件可以是一个空JSON对象:

cat src/yuidoc.json
{}

如下是一个使用YUIDoc标记法进行注释的JavaScript文件:

/**
 * Provides some mathematical functions
 *
 * @class math
 **/
/**
 * This function accepts two operands, 'a' and 'b' and room returns
 * their sum (or concatenation if they are strings)
 *
 * @method sum
 * @param {Number or String} a first operand
 * @param {Number or String} b second operand
 * @return {Number or String} The 'summed' value
 */
exports.sum = function (a, b) {
  return a + b;
};

/**
 * This function accepts two operands,'a' and 'b' and returns
 * their product
 *
 * @method product
 * @param {Number} a first operand
 * @param {Number} b second operand
 * @return {Number} the product
 */
exports.mult = function (a, b) {
  return a * b;
};

YUIDoc可以生成更好的模板(带搜索功能!),并且其标签库在JavaScript方面比JSDoc更友好。当然,我们可以随意试用这些工具,然后再决定哪个才最适合用于项目。

JSDoc

JSDoc(https://code.google.com/p/jsdoc-toolkit/)和YUIDoc类似。它利用了一套类似但更大的标签集(https://code.google.com/p/jsdoc-toolkit/wiki/TagReference)。

Google的Closure Compiler利用了JSDoc标签进行精简、优化,并编译代码,一举两得,是个不错的选择。

JSDoc的设置略显愚笨。它是一个Java程序,并且依赖它的JAR文件位置以及模板文件。下载并解压后,可以很容易地设置两个环境变量,JSDOCDIR和JSDOCTEMPLATEDIR。JSDOCDIR是jsrun.jar所在的目录,在解压文件夹的jsdoc-toolkit目录内。对于新手——或许永远都是,除非为了使用JSDoc创建自己的HTML模板——JSDOCTEMPLATEDIR需要指向$JSDOCDIR/templates/jsdoc目录,以便使用该目录提供的默认模板。

一旦设置了这两个环境变量,就可以使用该工具提供的jsrun.sh这个shell脚本了,其位置位于$JSDOCDIR。至此,生成JSDoc文件的命令行就可以像如下这样使用了:

/bin/sh $JSDOCDTR/jsrun.sh -d=<outputput dir><JavaScript file>

上述命令将生成一组HTML文件,并输出到<output dir>。如下这个JSDoc友好的JavaScript文件中,注意一下JSDoc标签和上一小节YUIDoc标签之间的细微差别:

/**
 * This function accepts two operands, 'a' and 'b' and room returns
 * their sum (or concatenation if they are strings)
 *
 * @name sum
 * @function
 * @param {Number or String} a first operand
 * @param {Number or String} b second operand
 * @return {Number or String} The 'summed' value
 */
exports.sum = function (a, b) {
  return a + b;
};

/**
 * This function accepts two operands,'a' and 'b' and returns
 * their product
 *
 * @name product
 * @function
 * @param {Number} a first operand
 * @param {Number} b second operand
 * @return {Number} the product
 */
exports.mult = function (a, b) {
  return a * b;
};

Docco/Rocco

根据官方网站介绍,“Docco是一个能够快速上手、仅百行代码且具有编程风格的文档生成器”——就像一口就能吞下的豆腐。Docco(https://jashkenas.github.io/docco/)是所有都做同样事情的程序家族的前辈,即:从代码中解析出Markdown风格的注释,在生成的HTML注释文档中,将其左列中的内容匹配到右列中的内容,并高亮显示所匹配的代码。最好理解的一个例子是,由Docco生成的Docco网站。

Rocco是使用Ruby编写的Docco克隆版本,比较奇怪的是,它的JavaScript代码的格式化功能(使用CoffeeScript编写)比Docco更智能。令人惊奇的是,Rocco的网站也是由Rocco生成的。

如果还没安装Ruby的话,使用Rocco的最大障碍就是安装Ruby。另外一个依赖项是Pygments,它是一个使用Python编写的语法高亮显示工具。如果没有安装的话,Rocco将会尝试使用Pygments web service,但你可能会质疑,不太愿意将自己的代码通过Pygments web service进行语法高亮显示。Pygments依赖于Python,所以一旦安装了Python,Pygments就可以使用如下命令进行安装:

sudo easy_install Pygments

Rocco也需要Markdown解析器,可以使用rdiscount:

sudo gem install rdiscount

最后,安装Rocco:

sudo gem install rocco

现在可以在代码上运行Rocco了:

rocco myJavascript.js

默认情况下,会在当前目录下产生一个与JS文件同名的html文件。可以使用-o选项修改保存html文件的目录。

所有的注释都会从源码中解析出来,并放置在Web页面的左侧,所生成HTML页面的右侧显示的是与此对应的代码。

如下是基本的JavaScript代码:

/**
 * This function accepts two operands, 'a' and 'b' and room returns their
 * sum (or concatenation if they are strings)
 */
exports.sum = function (a, b) {
  return a + b;
};

/**
 * This function accepts two operands,'a' and 'b' and
 * returns their product
 */
exports.mult = function (a, b) {
  return a * b;
};

总结

YUIDoc、JSDoc、Rocco三种工具各有所长,根据自身需求进行选择。


作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。