11月阅读周·编写可测试的JavaScript代码:复杂度之注释篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出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畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)