这是Node.js聊天代码的片段和Opa中对应的部分。
2.Opa vs Node.js:出现错误了怎么办?
Opa vs Node.js:出现错误了怎么办?
众所周知,写代码并不是编程的最后一步——有趣的事往往发生在测试和调试的时候。因此,只有看看这两者在此情况下的对比才算真正公平。实际上,我们需要考虑三方面的问题:语言如何检测错误;对调试的支持;对测试的支持。本文中我们不看测试方面,因为两者在这方面实在太接近了。下面我们从调试功能入手。
在Node.js中开发者用JavaScript同时为客户机和服务器编写代码。而在Opa中,客户机端的JavaScript是从更简洁的Opa代码自动生成的。用户可以选择node-inspector或V8 debugger——Eclipse中Google Chrome开发者工具的一部分,来调试Node.js程序。Opa的情况更加复杂一点,因为现在还没有一款专用的调试工具。而且客户端的代码是自动生成JavaScript,因而,代码的可读性会更低(尽管编译器中有缓解这一问题的选项)。
另一方面,多亏它的编译器提供的静态类型(和很多不需要程序员注释的静态类型不同,Opa有完整的类型推断)和静态分析,Opa才能就错误检测作出承诺。原则上,那意味着它要能够在运行程序之前就检测出大量的错误。为了实际检验,我们在Node.js和Opa的代码上做了很多试验。我们添加了一些常见的错误并观察发生了什么。
我们从函数名这种简单错误开始。Node.js程序中,我们在一个显示当前在线用户数的函数中用lenght代替了length。然后我们重新运行了这个程序,发现直到代码被执行时错误才被检测出来——本例中是当用户进入或离开聊天室调用上述函数时才出现。我们由此可以联想到在不常被调用的函数中,这样的错误是不容易被发现的。错误在JavaScript调试器中只显示为:
- GET http://localhost:8001/join?_=1327952561187&nick=akoprowski 400 (Bad Request)
并指向相应Ajax请求发生的地方。要想将这个错误和错误代码联系起来不花点时间,没有一定调试经验的人恐怕是难以完成的。
接着我们又在Opa的代码中安排了同样的错误,Opa不让我们运行这个有错误的程序并报告了如下错误:
- File "src/main.opa", line 152, characters 21-28Expression has a record type incompatible for access to field lenght. […]Hint: Perhaps you meant length or merge?
我们又试了一些用户自定义数据类型,在Node.js和Opa定义的聊天信息中用txt代替text。结果是一样的:在Node中显示运行错误,没有指出错误所在;Opa中却是详细的错误信息。
然后我们决定看看错误的HTML会发生什么,这是两种语言在界面上的重要构件。在Node.js显示聊天信息的表格中,我们用“,”代替第二个封闭标签,结果程序照样工作但显示却出现偏差(现代的浏览器非常善于“修复”标记错误)。我们还尝试了其他类似的标记错误,其中的一些在输出结果中很难找到缺陷。
在Opa的例子中,我们没有用表格,但却在服务器/客户端区分和通信这段代码中植入了这个错误,得到了一下清楚的错误信息:
- Hint: File "src/test.opa", line X, characters X-XOpen and close tag mismatch
在尝试其他变量错误时也得到了类似的编译时期错误。
最后,我们试了一下算术错误。在Node.js和Opa中都有计算内存使用的函数,简单起见,我们将第二次出现的数字1024用字符串“1024”代替。结果很类似,Ajax中不确定的运行时期错误和Opa中如下的编译错误:
- File "src/main.opa", line 91, characters 28-41.Function was found of type 'a, 'a -> 'a but application expects it to be of type int, string -> 'b.Types int and string are not compatible.
尽管对于从未使用过Opa的人来说上面的错误信息也许还不够明确,但对于熟悉的人来说,简直就是清楚地不能再清楚了。
总的来说,我们认为这些结果是很令人吃惊的。一大类Node.js中需要花大精力去测试和调试的程序错误在Opa中都被自动检测出来了,并且都报告出有用的错误信息(大部分时候)。我们还只是停留在表面,因为Opa实际上可以检测出更多除了上面讨论过的错误。
这点不应当被忽略,因为它可能是区分Opa最重要的特性。它还反应了Haskell程序员多年前就知道的事实:采用一种设计完善的语言可以一次性就写出几乎全对的代码,并在测试和调试环节省下大量的时间。
3.结论
Node.js和Opa都统一了客户机和服务器编码,它们的持续流行表明现在的Web实在是太复杂了,编程模型需要重新定义和简化。尽管Node.js是在现存流行的JavaScript语言上的创新,但Opa给那些想要花时间学习一门新语言的人提供了帮助。