考虑有这样的一个函数,这个函数会异步地连接到一个IPv4地址的TCP端口。我们通过例子来看文档怎么写:
~~~
/*
* Make a TCP connection to the given IPv4 address. Arguments:
*
* ip4addr a string representing a valid IPv4 address
*
* tcpPort a positive integer representing a valid TCP port
*
* timeout a positive integer denoting the number of milliseconds
* to wait for a response from the remote server before
* considering the connection to have failed.
*
* callback invoked when the connection succeeds or fails. Upon
* success, callback is invoked as callback(null, socket),
* where `socket` is a Node net.Socket object. Upon failure,
* callback is invoked as callback(err) instead.
*
* This function may fail for several reasons:
*
* SystemError For "connection refused" and "host unreachable" and other
* errors returned by the connect(2) system call. For these
* errors, err.errno will be set to the actual errno symbolic
* name.
*
* TimeoutError Emitted if "timeout" milliseconds elapse without
* successfully completing the connection.
*
* All errors will have the conventional "remoteIp" and "remotePort" properties.
* After any error, any socket that was created will be closed.
*/
function connect(ip4addr, tcpPort, timeout, callback)
{
assert.equal(typeof (ip4addr), 'string',
"argument 'ip4addr' must be a string");
assert.ok(net.isIPv4(ip4addr),
"argument 'ip4addr' must be a valid IPv4 address");
assert.equal(typeof (tcpPort), 'number',
"argument 'tcpPort' must be a number");
assert.ok(!isNaN(tcpPort) && tcpPort > 0 && tcpPort < 65536,
"argument 'tcpPort' must be a positive integer between 1 and 65535");
assert.equal(typeof (timeout), 'number',
"argument 'timeout' must be a number");
assert.ok(!isNaN(timeout) && timeout > 0,
"argument 'timeout' must be a positive integer");
assert.equal(typeof (callback), 'function');
/* do work */
}
~~~
这个例子在概念上很简单,但是展示了上面我们所谈论的一些建议:
* 参数,类型以及其它一些约束被清晰的文档化。
* 这个函数对于接受的参数是非常严格的,并且会在得到错误参数的时候抛出异常(程序员的失误)。
* 可能出现的操作失败集合被记录了。通过不同的”name“值可以区分不同的异常,而”errno“被用来获得系统错误的详细信息。
* 异常被传递的方式也被记录了(通过失败时调用回调函数)。
* 返回的错误有”remoteIp“和”remotePort“字段,这样用户就可以定义自己的错误了(比如,一个HTTP客户端的端口号是隐含的)。
* 虽然很明显,但是连接失败后的状态也被清晰的记录了:所有被打开的套接字此时已经被关闭。
这看起来像是给一个很容易理解的函数写了超过大部分人会写的的超长注释,但大部分函数实际上没有这么容易理解。所有建议都应该被有选择的吸收,如果事情很简单,你应该自己做出判断,但是记住:用十分钟把预计发生的记录下来可能之后会为你或其他人节省数个小时。