文章分类 | 推荐文章 | 最新文章 | 热点文章 | 最新软件 | 精品软件 | 下载排行 | 推荐下载 | 免费看大片 | WPS | 杀毒软件
清风网络
首 页 软件下载 网络学院 数码学院
QQ 电脑入门 游戏 操作系统 图形处理 办公软件 媒体动画 精文荟萃 工具软件 网络编程 程序开发 网络技术 认证考试 网站建设 文章专栏
当前位置:清风网络学院程序开发IT人生分析:API设计的“不可承受之轻”
精品推荐
特别推荐
·值得回忆的本科四年学习(1-6)
·如何检测内存泄漏——重载new和delete
·Linux IPC小结
·编程初学者的良言警句
·如何用正确的方法写出高质量软件的75条体会
·一个程序员的经典自白
·程序员十大安全技巧
热点TOP10
·网管工作总结--我的网管生活经历
·李纳斯·托沃兹(Linus Torvalds):Linux之父
·华硕员工长篇记实:天堂向左,华硕往右
·将CStdioFile类扩展,读取UNICODE文本文件
·VC++学习方法及书籍推荐
·SP 短信开发-PROVISION接口实现-正向订购实例代码
·从ACM会议看中国大陆计算机科学与国外的差距-- 灵芯
·如何检测内存泄漏——重载new和delete
·用DirectDraw编写动画程序
·七年之后我逃离编程
·dotproject 安装总结
·老程序员十年生涯黯然总结
·回调设计模式
·IT人的酸甜苦辣 女测试工程师的成长
·Linux IPC小结
·一位30岁软件工程硕士的困惑
·值得回忆的本科四年学习(1-6)
·老程序员十年生涯黯然总结(四)
·SP 短信开发-PROVISION接口实现-反向取消实例代码
·世界五大顶级合法黑客和他们的创新故事

分析:API设计的“不可承受之轻”

日期:2007年9月12日 作者: 查看:[大字体 中字体 小字体]


  本文转自infoq,文中内容不代表本站观点,仅提供参考

  API的设计影响着所有的开发者。有些API用起来很舒服,而有些则用起来让人焦头烂额,更有甚者,让人完全丧失了继续用这套API来做开发的勇气。但它们的区别在哪里呢?是哪种品质会让一套API易用而另一套复杂难解?ACM Queue最近刚发布了Michi Henning的一篇有关API设计的文章,作者在文中剖析了API的好坏之分,并指出了API对生产力的影响。

  当我们开始用API的时候,我们就能知道它是好是坏。好的API会让人心情愉悦,用起来得心应手:当你想调用某个特定的任务时,最合适的方法会在最恰当的时候出现在你面前,容易发现,易于记忆,文档说明详尽,接口设计符合人的思维习惯,而且正确的处理了边界条件。

  那为什么现在还有这么多垃圾API呢?其主要原因在于,对于每一种正确的API设计方式而言,都同时伴随有很多种错误的设计方式。简单来说,设计一种坏的API要比设计好的API容易的多。即使是很微不足道的、无伤大雅的设计上的小小缺陷,最终也会被放大成巨大的阴影,因为API只需要提供一次,但是却会被调用很多次。如果一个设计缺陷会导致笨拙或是低效的代码,那么这个问题就会在API每次被调用的时候都显现出来。而且,有些设计缺陷单独看起来很小,但是却会以令人讶异的破坏性的方式来相互影响,从而很快就会导致不计其数的间接性破坏。

  Michi在给出自己对API设计的建议之前,先举了一个反例为证。他对.NET框架中的Select()方法调用进行了分析,展示了很多API中都存在的共通问题。

  Select() 方法中传入的参数是需要进行监控的socket列表。在大多数应用程序中,所使用的socket不会常常变化,所以这些列表基本上在很长一段时间内都是不变的。但是:

  因为Select()方法对参数进行了重写,所以调用者在把每一个列表传入Select()方法之前必须要保留一个备份。这就给用户带来了很大的不便,而且不宜扩展应用的规模:服务器常常都要监控上百个socket,而在每一次循环中,调用Select()方法前都要复制所有的列表。

  因为socket会进入等待或是阻塞状态,所以Select()还接受一个时间参数用来标识超时,如果在参数所指定的时间内没有任何socket可用,那么方法就会返回。但是,因为这方法是void类型,所以没有很便捷的方式可以标明Select()方法是因为有了可用的socket而返回,还是因为超时返回的。

  为了判断是否有可用的socket,调用者必须要对方法参数中的三个列表各自的长度进行测试;如果三个列表长度都是零,那么就是没有可用的socket。如果调用者碰巧很关心这一点的话,那就要写一个相当别扭的测试了。更有甚者,如果没有socket就绪而发生超时,那么该方法就会销毁调用者传入的参数,所以就算是什么事情都没有发生,调用者还是必须要在每一个循环中对这三个列表进行备份!

  而且,在API文档中,也没有明确的指出该怎样无限期地等待socket就绪。Michi还是通过自己的试验才发现,如果超时参数为0或是负数,那么该方法就会立刻返回,而且也没有任何办法可以让该方法等待的时间超过35分钟。这就逼着他只好自己实现了一个Wrapper,来完成持续性等待的功能。

  在写这个Wrapper的时候,Michi又发现了API设计中新的潜在问题:

  Select()方法的另一个问题就是它接受的参数是socket列表。列表中可以允许同一个socket多次出现,但是这样做一点意义都没有:从概念上讲,传入的应该是由socket组成的set。那么为什么Select()会使用列表(List)呢?原因很简单:.NET容器类中没有包括对set的抽象。使用IList来对set建模是让人徒呼奈何的一件事情:它会带来语义上的冲突,因为list允许出现重复的元素。(Select()方法遇到重复的socket会发生什么样的行为大家只能瞎猜,因为没有明确的文档记录;而要实际去检测它的真实行为也是没有意义的,没有文档说明,我们怎么知道实现会不会在什么时候突然改变?)

  一个劣质的API设计所带来的问题就是,差不多每个用这套API的开发人员都要设法去弥补其中的缺陷。该API的用户群越大,开发人员浪费的时间也就越多。

  劣质的API不但会带来更多的编码,而且代码结构也会更加复杂,潜藏bug的地方也就越多。

  不过设计错误所发生的位置不同,其后果也会有所差异。

  在抽象层次中,如果API缺陷出现的位置越低,其后果也就越严重。如果我在自己的代码中错误地设计了一个函数,那么影响到的人就只有我自己而已,因为我是这个函数的唯一调用者。如果我在我们的项目库中错误地设计了一个函数,那么或许所有的同事都会遭罪。如果我在一个广泛采用的代码库中错误的设计了一个函数,那么或许就会有成千上万的程序员开始诅咒了。

  任何大面积流行的公共代码库或多或少都会被认为是不可变的。这种类型的API的任何变化都有可能破坏向后的兼容性,引起大量问题。方法声明的变化会导致客户端无法编译或是崩溃,方法行为的变化会导致无可预计的微妙错误。即使是修复bug也会有问题,因为会有些既有的代码是依赖于原始的有bug的行为的。

  在动态链接库的世界中,客户端代码就更容易受到API变化的影响了。哪怕采用了版本机制,客户端代码又怎样判断库文件版本号的小小变化是否会影响到当前任何对API行为的假定呢?

  即使API自身的变化会让框架变得更好,但是每一个用户也都要为升级付出一定的代价。当然,也有的变化不会引起客户端哪怕一行代码的改动,可就算这样,每一个客户端也不得不进行重新编译,以防止出现崩溃的情况,因为源码不变的情况下,二进制码也会发生变化。


[1] [2] 下一页 




上一篇:调查:四成以上黑客在研究“免杀”病毒

下一篇:安装CooCare酷越 即使菜鸟也能玩转驱动程序

分析:API设计的“不可承受之轻” 相关文章:
·不可错过:激励人生的五句话
·3DS Max 7卧室效果图设计:建模篇
·VB+Access设计图书管理系统
·如何建立一个网站?规划、设计、目的、原则、宣传
·飞机订票系统设计
·不可以不看的一些网站
·华北水利水电学院新校区校园网规划与设计
·校园网网络方案设计及分析
·Java图形用户界面设计
·C语言的常用库函数使用方法分析及用途
分析:API设计的“不可承受之轻” 相关软件:
·美工设计教程
·Dreamweaver 网页设计
·C语言程序设计
·Photoshop CS中文版平面设计师标准案例教程
·Photoshop CS经典创意设计200例
·Photoshop 7.0 平面 广告 装帧设计100例
·Windows环境下32位汇编语言程序设计
·远潮自我形象设计系统
·PhotoShop7 设计百例 + 经典实例教程 + 滤镜教学
·建筑抗震设计规范GB50011-2001

特别声明:本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
[打印本页] [关闭窗口] 转载请注明来源:http://www.viphot.com
| 帮助(?) | 版权声明 | 友情连接 | 关于我们 | 信息发布
Copyright 2007 www.viphot.com All Rights Reserved. 鄂ICP备05000083号Powered by:viphot