========第一部分理论与理由=========
发明,设计与编写API的过程,既可以看作是艺术创作,也可以当作是科学实践;
可以把一个API架构看作是一个努力改变实践的艺术家,也可以看作是一个架设桥梁的工程师;
保持API的一致性是非常难得,肯定要求设计组的各个成员都有着很好的默契,合作无间;还需要方法论知道大家如何来实现最终目标。
综上所述,为了避免术语上的混淆,本部分会建立一个术语库,并分析API设计的常见内容,首先要简历一个基本的术语库,描述整个API出现的原由,并概述设计过程的主要目标。
本部分,主要围绕三个问题?
(1)为什么要有API?
(2)什么是API?
(3)如何设计API?
第一章软件开发的艺术
软件开发的历史很短,从有人编写和执行第一个计算机程序至今,也不足百年,尽管历史并不悠久,但其影响力不亚于任务一种开创性的发明。有人把计算机科学历史发展史与人类认识真实世界的历史放在一起加以比较,这非常有意思,我们也借此来理解为什么软件开发需要优秀的API。
(1)理性主义、经验主义、无绪
在文艺复兴时期,现代科学产生了两大重量级理论,表现在哲学方法则为理性主义和经验主义。
理性主义的起源来自于伽利略的自由落体实验;在英吉利海峡的另一边又诞生了经验主义;
但是站在今天来看来,如果孤立地基于两种极端的方式来看待问题,或者观察问题,就会出现严重的偏离事实。
从理性到无绪
为国际受众设计API与创建书籍都是比较困难得事情。个人喜好和文化差异都会影响我们处理问题的方式,理性主义更喜欢谈论理论,了解现实对象背后的联系,而后再创建实例将理论应用到现实世界中来,而经验主义者则正好相反,先想尽各种办法获取实践经验,最终才会对事物的联系作出判断。
从针对性无绪(selectivecluelessness)的角度来解释如何设计API。我们将API看作一种可以将无绪极大化又能得到可靠结果的完美工具,正确理解无绪的真正含义是十分必要的。
(2)软件的演变过程
在20世纪40年代和50年代初期,编写代码是非常困难的事,不得不学习机器语言,同时还要知道寄存器的大小和数量,有时候,情况不妙,还要拿起螺丝刀亲自上场,去链接计算单元的信号线。人们的精力不在于思考一个算法,而放在将算法写成可执行的程序上,这是一种枯燥有机械的工作。
所以前期出现了FORTRAN语言,可算是程序员的福音,所以让程序员只
并非所有的人喜欢经验主义,然后理性主义者以约翰.麦卡锡发明了LISP语言,认为万事万物都应该是合理的。。。。
(3)巨大的组件
在20世纪的前10年中,大部分软件系统都可以用脏乱差来形容。没有哪个软件的设计配的上优雅这个词。这个主要是因为开发的时候,大家的目标就是用尽可能的低成本来实现某个功能,就会引入一些可以复用的半成品框架组件来完成,而不在乎这些组件的重量程度已经远远超过了自己的需求部分。
(4)漂亮、真理和优雅
现在这样的重量级开发形式,最后会把一个程序变成垃圾堆,那怎么有一种开发方式可以优雅的表达出来?如此丑陋的应用怎么能力保证其正确性?其实答案是肯定的,我们只需要仔细看一下我们大部分人现在所担心的事情。
对于真理和美这个起源于古希腊。对于古希腊哲学家,最有价值的科学知识其定义是非常简明的,其意义清楚明白,绝不含糊,于是几何学就成为了科学中最具有价值的。
古希腊人的几何学世界和现实世界的一个重要区别在于重要性。
几何学的物体会因为其复杂性而产生改变。
在文艺复现时期,古希腊风格一级古希腊人对于比例,美丽及和谐的思想,在艺术和科学方面可谓是无所不在。
。。。。
计算机科学和软件工程其实也不例外,他们也需要美丽和合理,然而,应该牢记一点,软件的首要目标是在发布给客户以后能够可靠的运行,已提供客户需要的功能,在软件正式发布前的冲刺阶段,所有的软件工程师根本不会想到美丽这个词,而是把精力集中在修复bug上,严格地说是绕开严重bug上,然后按计划发布软件产品,事实上,这个时候,简单和优雅根本不是工作的目标,虽然大家都会感觉应该做这件事,但已无暇顾及,现在我们既然认识到这一点,就可以记起无绪开发这样的大旗,作为从今往后开发方法论。
(5)更好的无绪
所谓的无绪,其实就在试实现一个系统的时候,或者开发一个软件,只需要了解怎么实现就ok,不管是当中用了多少组件和插件,只要能满足需求,开发出貌似没有bug的结果也是ok的。
“无绪”这个词并不是一个贬义词,我们只是用它来区分两种层次的理解水平,有一种理解可以称为“浅层理解”,同理还有一种“深层理解”浅层理解,它是指对一种事物的了解程度只限于掌握使用方法结果,也就是知其然而不知其所以然,还有一种就是,知其然而知其所以然;
其实在软件开发当中,我们大部分情况下,我们只要做到“浅层理解”,就可以了,“针对性无绪”,这个词用在这里只是提醒大家,有些内容需要深入了解,而有些内容则无需如此,所以针对性无绪是个彻底褒义的词。
第二章设计API的动力之源
设计API并不容易,而且代价也不菲,开发一款不需要API的软件,比开发API相比而言容易很多。
(1)分布式开发
API可以被看作是对功能和组件内部实现的一个抽象,通常来说,外部人员并不需要了解内部实现情况,只需要通过定义好的API操作说明即可调用操作。
分布式开发自有其特殊之处,最大的不同就是,整个程序的源代码已经不再完全处于开发人员的控制下,而是散布于世界各地。与完全基于内容代码仓库中的源代码来构建一个程序相比,这种构建软件的方式是明显不同的。
在这种开发模式下,产品的开发进度是无法全面掌握的,软件的源代码和开发人员散步在全世界,而且开发人员各自有自己的安排,所以项目经理无法全面掌握,作为一个项目经理,超过50人的团队,其实他自己也很清楚,无法全面的掌握每个人的开发情况。
事实上,要设计良好的API,开源并不是唯一的驱动力。
(2)模块化应用程序
模块化应用程序是有分布式团队开发出来的独立组件组成的。
在设计API时,第一课也是非常重要的,就是给自己API的组件起一个不错的名字,尽量做到用户闻其名知其意,比如netbeans平台上的一个支持项目结果组件,org.netbeans.api.projects,这个名字堪称完美。
在知道如何为自己所开发的组件命名以后,还要看一下每一个组件运行的环境,没有一个程序是在真空中运行的,他需要从其他周围的环境中获取相应的服务,所以每一个组件还需要考虑运行的环境。
(3)交流互通才是一切
应用程序应该基于无绪原则来开发,尽量让最终负责集成的相关人员不需要深入了解系统页可以把集成工作做好,所以,我们理想的应用程序应该基于模块化架构来开发,可以由散步在世界各地的开发人员分别编写相应的模块,他们可以按照自己的日程来安排,已到达最终目标,但是这种做法却存在一个重要的问题,那就是模块间的关联关系。
大多数模块并不能孤立存在,他们要依赖于其他模块提供的环境,只是少数模块才可能完成不依赖其他模块而独立对外提供功能,实际上,大部分模块化的组件都需要其他组件为其提供服务,这就意味着这些模块的开发人员需要去发现和了解如何使用外部模块提供的API,而这样的模块也是有其他开发人员编写的,所以还会出现一个隐藏的问题,即该模块又依赖于另外的模块。
API不是给计算机用的,而是人,是我们这些开发人员,API往往包含了大量的内容,还有相应的说明文档,其实对于要运行程序的计算机来说根本不需要这些东西。
API最重要的作用就是分解(separation),要做到分解,就需要为设计和维护API制定相应的规则,如果不能分解,那么整个产品就是紧耦合的。一旦这个程序开发完了,也就是不需要对外提供一个API了,但在现实生活当中,往往以模块化的方式进行的,所以我们开发完的模块,会被其他模块所运用,这样就需要一个稳定的契约,来保证这种沟通的有效性。
(4)经验主义编码方式
经验主义编程方式也就是先用一个API做实验,如果不成功,就再试下一个,经验第一,然后才是深入了解,不过有时候,并不需要深入了解。
API应该是自描述, 即用户无需任何文档就可以正确使用该API,这样的API能够引导用户利用其提供的各种功能和元素来轻松的完成任务,用在编写代码的时候,就很容易找到解决方案。
(5)开发第一个版本通常比较容易
事实上,第一个版本几乎从来没有完美的,但不能说这是因为第一次设计,所以设计上做的不好,这不应该成为一个借口,对于第一版本来说,设计起来总是比较容易的,而在后续版本中加以改进则比较困难,所以在第一个版本中,要尽量将其设计做到完美,同时不要忘记,今天看来完美的设计,明天可能就变得非常差,改变迟早都会出现。
如果在设计API时就考虑到未来改进,而预先留出相应的空间,那么即使出现升级的情况,也不会给其他用户添加额外的工作。
因为开发人员不喜欢那些不必要的工作,特别是因为库的开发商考虑不全面,最终使得库无法兼容,进而为开发人员带来一些不必要的工作,所以在开发可供他人使用的组件时,必须要考虑在组件改进的时候还能保持兼容。
第三章评价API好坏的标准
为什么开发一个API?
其根本原因在于:我们希望能够将大块的构建模块“无绪”地集合成应用程序,这些构建模块,包括共享类库,框架,预先定义好的应用程序结构,以及这些内容的组合,我们相信如果每一个程序员都可以很好地完成自己所负责的模块,也就是说他们设计的API完全正确,那么程序的集成工具就会变得非常简单,集成人员不需要花费时间进行调试,阅读源代码,打补丁,更不用去考虑他人到底是如何来设计和开发一个模块的,一句话,我们完全可以在“无绪”的状态下来完成集成工作。
(1)方法和字段签名
(2)文件及其内容
开发中还有一项内容是经常被人们所忽略的,但他确实非常重要的,那就是应用程序执行时要读写的文件以及这些文件的格式;
先来简单说下一个例子,现在有一个telnet程序,分析一下他是怎么与一个支持kerboros验证系统进行交互的,这两个组件是不同的人员开发的,因为编写加密代码和处理套接字链接属于两个不同技术领域的范畴,但只要一个文件API就可以将两个组件相互协作,所以文件,和字符串是所有语言和系统支持的解析方式。
telnet协议是TCP/IP协议组中的一员,是因特网远程登录服务的标准协议和主要方式,他为用户提供了本地计算机上完成远程主机工作的能力
Kerberos协议主要用于计算机网络的身份鉴别(Authentication),其特定是登录kerberos服务之后就可以获取到票据(ticket),只需要登录验证一次,即SSO,单点登录原理,由于每个客户和服务之间建立了共享秘钥,使得该协议具有相当的安全性。
(3)环境变量和命令行选项
(4)文本信息也是API
Unix有一个很大的特点,就是它使用了“管道”技术。很多程序不仅仅可以通过环境变量和命令行参数进行控制,还可以向一个程序输入一段文本作为参数并取得一个返回值。在任何Unix系统中,可以用管道技术吧很多程序串在一起变成一个程序。这种功能非常强大,而且易于理解,对于很多unix系统用户来说,这已经是unix系统上常用的一个功能了。同样,如果一个程序有输入值和输出值,那它就是一个API。
(5)协议
协议是针对文本内容的API,它们用来定义网络传输中的信息格式,所以非常重要。所以在软件升级过程中,版本1,版本2先做一个握手交互,是非常重要的。
(6)行为
(7)国际化支持和信息国际化
(8)API的广泛定义
关于“API定义”这个问题,现在看起来可能已经很清楚了,所谓的API远远不止于是类、方法、函数和签名这些东西,为了有利于在“无绪”的状态下吧一个大的系统以组件集成的方式拼装出来,从这个角度来看,APi的定义就非常广泛,从简单的文本信息到哪些复杂的或者难以控制的组件行为,都可以算出是API。
(9)如何检查API的质量
《1》可理解性
《2》一致性
一致性包括两方面:a、API多个版本间保持一致,b、对外提供功能一致,比如注册工厂都应该用registerFactory,不能有的写registerFactory,有些写addFactory。
《3》可见性
《4》简单的任务应该有简单的方案
一般API常用的方案:则是将一个API分解成两个或者多个组成部分,一部分针对调用功能的开发人员,一部分则放在独立的包中,供开发人员进行扩展,还有一种就是扩展系统功能的开发人员;
API:例如:javax.naming,javax.naming.event,javax.naming.spi
《5》保护投资
对于API设计者来说,首要的任务就是要保护其用户投入的资源。
《未完待续~~~》
白巅峰专科医院那里好北京治白癜风医院哪家比较好