IT技术博客大学习 共学习 共进步

评判浏览器API好坏的标准是什么

为之漫笔 2011-01-27 22:57:02 浏览 3,464 次

    Original Post:What makes a good browser API?

    Nicholas C. Zakas,2009年11月24日

    翻译完成:2010年1月22日,最后更新:2010年1月22日

    上个月,我又参加了Mozilla公司组织的一次研讨会,这一次讨论的是Web数据库。虽然研讨会的议题很有意思,但我觉得会议期间大家对另一个问题的争论似乎更值得关注。争论中,与会者针对浏览器到底应该为JavaScript提供什么样的API分成两派。一派坚持认为原生的JavaScript API应该尽量保持低级化,然后由库开发者在低级API基础上再去构建更好用的接口。另外一派,也是我所在的阵营,则认为中级API才是大势所趋。没有人认为浏览器应该向开发人员提供高级API。所谓低级、中级、高级到底都是什么意思呢?

低级API

    低级API仅为提供基本功能而设计。由于只要能实现相应功能即可,因此这种API不需要很直观或者很好理解。有时候,低级API确实会给初级甚至中级开发人员造成理解上的困难。这样一来,借由人们频繁使用来发现相应API问题的机会就大为减少了。大家都会指望库开发者在这些低级API基础上实现直观、好用的API,以便于普通开发人员使用。doument.cookie就是说明低级API最好的一个例子。

    作为JavaScript开发人员操作cookie的唯一接口,document.cookie可谓有史以来最难使用的一个API。关于cookie,我专门写过一篇文章,还探讨过它的安全性问题,其中都涉及到如何在JavaScript中使用它们;因此,这里只能算是一个简单的介绍了。要设置cookie,必须以正确的cookie格式来设置document.cookie属性,例如:

    document.cookie = “name=Nicholas; domain=nczonline.net; path=/; expires=Sat, 02 May 2009 23:38:25 GMT

    要取得cookie,则需要读取document.cookie,返回的字符串是如下列所示的名值对格式:

    name1=value1; name2=value2; name3=value3; name4=value4

    而为了得到想要的值,必须先从这个字符串中查找相应的名字,然后再解析出相应的值。

    之所以把这种API归类为低级API,是因为其实现要求你必须先了解cookie的内部格式,然后才能使用它。实际上,document.cookie属性只是在简单地模仿Set-Cookie和Cookie这两个对开发人员不可见的HTTP首部。为了写cookie,必须要理解字符串的确切格式,这涉及到其中的名和值必须采用URI编码形式,而其他片段之间必须以一个分号和一个空格来分隔,此外还必须知道设置过期日期的正确日期格式。反过来也一样,在读cookie时,你同样需要知道返回的字符串是什么格式,然后才能从中解析出想要的数据。这就是所谓的“遇繁不简,遇简也不简”。一句话,这种API对于不了解cookie的人根本没有用。

    如果大多数开发人员都不会直接使用某个API,你就可以说它是低级API。不用,是因为使用它们所需的知识储备(Cognitive Overhead)太多了。绝大多数开发人员在使用JavaScript读写cookie时,最终都会求诸于一个JavaScript库例如YUI中的Cookie工具(YUI2YUI3),这些工具把那些令人讨厌的实现细节都隐藏起来了。

    这正是那些低级API的支持者所愿意看到的:浏览器应该只提供基本功能,而基于这些功能开发易用API的任务应该交给开发人员社区。这些人支持低级API有一个主要的理由,即围绕基本功能可以实现任何层次的抽象,开发人员也会因此获得更多选择,从而更好地利用基本功能。

    低级API的问题在于浪费时间。如果你创建了低级API,那结果就是潜在用户的数量会很少。至于什么时候能够出现好用的抽象工具,只能指望某一天这些用户中有(一个或几个)人会意识到确实有必要去做这件事,以便其他社区人员更好地利用该API。如果你想让新API尽快地被别人使用,你就会明白应该怎样去改进它,低级API根本不合适。

    提示:大多数服务器端语言(如 ASP.NETJSPPHP)都提供了读写cookie的原生抽象,但JavaScript始终都没有。

高级API

    这一争论的另一个极端是高级API。高级API设计出来就是为了让开发人员直接使用的,并且一般都非常直观。这种API不仅要考虑提供某种功能,而且还要提供使用相应功能的友好、易用的接口。高级API设计首先考虑的是开发人员的方便,因而通常需要对开发人员使用API的方式从理论上作出归纳。显然,这又是一个问题:谁能确切地知道某个人希望怎么去使用一个API呢?因此,在浏览器中提供原生的高级API几乎就是一个不可能完成的任务。

    各式各样的JavaScript库就是高级API的典型例子。这些库都面向相同的浏览器,但为实现相同功能而提供的接口却差别很大。使用jQuery的方式与使用YUI截然不同;这是件好事,因为开发人员可以选择。可是,如果你告诉YUI开发人员必须使用jQuery语法写代码――因为只能使用一种语法;或者相反,会怎么样呢?相信对此提出抗议的开发人员一定会成群结队。强迫人们必须以某种方式开发是不幸之源。只有抽象,或者说只有随时都可以提高和降低抽象级别,才会让开发充满乐趣,也才能激励开发人员不断地创新。

    高级API要求的知识储备非常低,因此开发人员无需了解太多就可以直接使用。但值得高兴的是,没有人认为浏览器应该提供高级AIP。大家都希望有所选择,都希望不同程度的抽象。

中级API

    折衷方案是中级API。以我的观点来看,中级API是浏览器所应该研究和实现的。顾名思义,中级API处于低级和高级之间,兼具二者之长。所谓中级API,(我的定义)就是针对最常见的应用提供简单的接口,同时能够通过扩展实现更强大的操作和对不常见应用的支持。第一部分,常用的接口,是非常简单、无需抽象即可直接使用的。而不常用接口可以更复杂一些,甚至可以“让人摸不着头脑”,因为很少会有人用。

    XMLHttpRequest是不错的中级API中最出色的例子。使用它最常见的情形就是发送一次GET请求,然后取得XML数据。实现这个过程的代码不多:

    var xhr = new XMLHttpRequest();

    xhr.open(“get”, “/somexml”, true);

    xhr.onreadystatechange = function(){

     if (xhr.readyState == 4){

     if (xhr.status == 200){

     process(xhr.responseXML.getElementsByTagName(“item”));

     }

     }

    };

    xhr.send(null);

    虽然有人会说onreadystatechange这个事件处理程序看起来有点麻烦,但实际上,你要做的不过是检查一点信息,以确定是否接收到了正确的数据。可是,所有必需的信息都已经各就各位了,而且也已经转换成了方便访问的格式:HTTP状态就在那摆着,而XML也已经转换成了DOM格式。为了给你提供这些数据,API已经做了不少的工作了。

    另一种不太常见的用法就是在URL中包含提交的表单数据。虽然代码难看点,但仍然可以接受:

    var xhr = new XMLHttpRequest();

    xhr.open(“post”, “/add”, true);

    xhr.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);

    xhr.onreadystatechange = function(){

     if (xhr.readyState == 4){

     if (xhr.status == 200){

     signalComplete();

     }

     }

    };

    xhr.send(encodeURIComponent(name) + “=” + encodeURIComponent(value));

    除此之外,你当然还可以把XMLHttpRequest对象用于更复杂的处理中,例如Comet。问题的关键在于,它在常用情形下很简单,而且还能轻易地支持更复杂、更不常见的用例。这样一来,JavaScript库也容易在后台构建一个比较好用的接口,帮我们处理那些复杂应用下的琐碎细节。尽管每个JavaScript库在如何发起Ajax通信方面各有各的方式,但XMLHttpRequest接口的设计能够很好地适应所有方式。

    注意:有些人认为XMLHttpRequest也属于低级API。我承认它不是最清晰的API,但在常见用例中它确实非常简便易行。不要忘了,最初在设计这个对象的时候,常见用例就是从服务器上取得XML数据。从那个时候到现在,常见用例已经变了,但人们照样还在使用同一个API。在我看来,这恰恰表明了它是一个不可多得的中级API。

总结

    我主张浏览器应该原生提供中级API,这样才能自如地应对常见用例,同时还可以为不常见的用例留下扩展的空间。API的抽象程度太低,不利于广泛流传,更不容易引起开发社区的重视;API的抽象程度太高,由于限制的用例太专,人们要么能用,要么根本就用不了。目前来看,较新的API似乎有低级化的倾向,如此一来,开发人员在实际使用它们之前,往往需要有第三方来实现一些必要的抽象。我希望能够阻止这种趋势,好让常见用例实现起来更简单,以便人们能够立即使用它们,同时还可以对它们加以扩展。而中级API能够同时满足这两个条件。

建议继续学习

  1. 浏览器的工作原理:新式网络浏览器幕后揭秘 (阅读 22,827)
  2. 浅析http协议、cookies和session机制、浏览器缓存 (阅读 17,203)
  3. 从输入 URL 到页面加载完成的过程中都发生了什么事情? (阅读 15,704)
  4. 好的API设计 (阅读 12,283)
  5. 浏览器的渲染原理简介 (阅读 8,165)
  6. 程序员眼里IE浏览器是什么样的 (阅读 7,863)
  7. 各种浏览器审查、监听http头工具介绍 (阅读 7,725)
  8. 图说浏览器战争:火狐、微软、谷歌那些事 (阅读 7,342)
  9. 浏览器缓存机制 (阅读 7,100)
  10. [译]Google Chrome中的高性能网络 (阅读 6,502)