近日设计RMI到Infiniband网络的接口,发现如何设计一个好的API是个很有挑战的问题。看了Joshua Bloch的ppt,做了一个总结
API可以成为一个公司很大的资产,因为好的API是可以赢得客户的。而且一旦API被public就很难改变,这也是在Java的包中有很多Deprecated的类和方法,却不能直接被删除。
好的代码应该是模块化的,每个模块都有自己的API;
有用的模块往往是很容易重用的;
对API的设计仔细考虑可以提高代码质量;
好的API的特点:
• Easy to learn
• Easy to use, even without documentation
• Hard to misuse
• Easy to read and maintain code that uses it
• Sufficiently powerful to satisfy requirements
• Easy to extend
• Appropriate to audience
API设计的流程
收集需求-带有一定程度的怀疑
一个简短的规范,这时不要求完备,但是要敏捷;
让尽量多的人参与讨论,听取别人的看法
充实这个规范,一遍coding,一边完善规范
基本规则
功能应该容易解释,设计好的命名,使得可以很容易地进行模块的划分和合并
API应该尽量小,但是不能太小;API只能添加不能删除,合理大小的API要比bulk的API要好,所以应该尝试找到好的 功能体积的比率
实现不能影响API,区分出什么是实现的细节,不要太详细指定方法的行为,一些调优的参数都是应该怀疑的;不要让实现的细节困扰用户,同时也要现在能够改变实现的自由
使任何事情的可访问度都尽量的小,尽量让class和member是private的,public的类不能有public的field,编译时常量除外;这样可以使信息隐藏达到最大,同时允许模块可以独立地被使用,修改,调试和测试。
命名;名字要尽量可以自解释;要有一致性,同样的名字意味着同样的东西,包括整个API,甚至API直接都要保持。尽量保持对称,代码看起来如同散文一样
写好文档。好的API设计和好的文档是实现代码重用的重要技术。
为每个类、接口、方法、构造函数、参数和异常加注释。类要表明一个实例代表什么;方法要描述清楚方法和客户之间的契约,包括前验条件、后验条件和副作用,参数要指明单位、表单和所有权;仔细的对状态空间写好文档。
不好的设计会影响性能:尽量多使用不可变对象;使用静态的工厂方法而不使用构造函数;使用接口而不是具体实现的类
不要歪曲了API来获得好的性能,性能提高了,可能以后会很痛苦,性能应该与设计良好的API保持一致。
Component.getSize()返回一个可变的Dimension对象,这样每个getSize方法都要分配一个Dimension对象,造成了大量无用的Dimension对象分配。在1.2中引入了新的方案(which?)
• Do what is customary
Obey standard naming conventions
Avoid obsolete parameter and return
Mimic patterns in core APIs and language
• Take advantage of API-friendly features
Generics, varargs, enums, default arguments
• Know and avoid API traps and pitfalls
Finalizers, public static final arrays
类设计
最小化可变类的使用。类应该都是不可变的,除非有足够的理由让他可变,这样实现是简单的、线程安全并可重用
如果是可变类,就应该严格限制状态空间的大小,并预先定义好。Date和Calender设计的问题和TimerTask的成功经验
只有在很讲的通的情况下才子类化,因为子类化(继承)意味着可以代换(里氏代换原则),public类不应该为了实现的容易而去继承其他的public类。反面例子Properties、Stack正面例子Set
如果一定要继承,就要做好设计和文档,否则就不准继承,继承后,子类可以看到超类的实现细节,破坏了封装。保守的观点说,所有的类都应该是final的。正面例子AbstractSet, AbstractMap
方法设计
不要让客户做模块应该完成的事情
尽量减少令人惊奇的事情。API使用者不能对API的行为有惊讶,即使减少性能也是可以接受的。
快速失败的API,应该在发生时尽量快的报告错误。最好能在编译的时候报告错误。在运行时,第一个不好的方法调用是最好的。
让程序能够对所有可用数据以String的形式可以访问,不然,客户就要对很长的字符串进行解析。
在重载时要特别留意,多个重载函数不应应用同样的参数,保守派认为尽量不要有同样个数个参数的重载函数
使用合适的参数和返回类型。使用接口而不是使用类可以提高灵活性和性能;使用最具体的可能输入参数类型,将错误从运行时转移到编译时;如果有其他的类型就不要使用String类型,String很麻烦,容易出错而且很慢(?),不要使用浮点数标识Monetary,会造成差错;使用double而不是float,可以保证精确度。
在方法中使用一致的参数调用顺序。
避免使用过长的参数列表,小于等于3个参数是很好的,多了会让用户不得不去参考doc,可以把函数拆小或者将所有的参数放在一个类中,作为参数传递;
避免返回需要参数处理的值,比如,可以返回长度为0的数组或者collection,而不要返回null。
异常设计
不要强迫用户使用异常作为控制流的一部分,但是,也不能在fail时不报告异常;要注意用好checked Exception,避免unchecked Exception的过度使用(不可能发生异常的地方不要catch,也不要throw);
在异常中包含可以用于捕获异常的信息,可以用来诊断、修复或者恢复,对于unchecked Exception可以附加信息,对checked Exception,应该提供访问接口。
重构API设计
参考资料:How to Design a Good API and Why it Matters, Joshua Bloch
相关推荐
How-to-Design-a-Good-API-and-Why-it-Matters The offline pdf already in this repo. ##API的重要性 公司最大的资产 公司最大的负债 ##好的API特征(和一个好的开源框架类似) 易于学习 即使没有文档,易于使用 很难...
We cover practical matters such as how to install and configure Kafka and how to use the Kafka APIs, and we also dedicated space to Kafka’s design principles and reliability guarantees, and explore ...
Dutson shows how to design sites that are responsive “from the start,” while keeping development simple and flexible. Next, he delivers complete technical know-how for transforming responsive ...
Ruby on Rails strips complexity from the development process, ... Dive deep into the Rails 3 codebase and discover why Rails is designed the way it is—and how to make it do what you want it to do.
With this book, you’ll learn how improve your design decisions through data-driven A/B testing, and how you can apply this process to everything from small design tweaks to large-scale UX concepts. ...
Be it a minor tweak on the visual design of a progress bar or a fundamental change in a widget to meet your needs, “jQuery UI Cookbook” covers scenarios both big and small. You can show reminders as...
Consistent, high-quality coding standards improve software quality, reduce time-to-market, promote teamwork, eliminate time wasted on inconsequential matters, and simplify maintenance. Now, two of the...
It serves as a foundation for all branding efforts, guiding the creation of content and design. The positioning statement should clearly convey IABC's purpose, benefits, and target audience. IABC ...
concepts of cryptography and leading to advanced matters such as smartcards and non-repudiation. The book is also comprehensive and timely, with some of the cited papers still in their journal’s ...
17.2 STATIC TYPING: WHY AND HOW 615 17.3 COVARIANCE AND DESCENDANT HIDING 621 17.4 FIRST APPROACHES TO SYSTEM VALIDITY 628 17.5 RELYING ON ANCHORED TYPES 630 17.6 GLOBAL ANALYSIS 633 17.7 BEWARE OF ...
Why Product Management Matters Product Development Processes: Creating Release 1.0 It Isn't Like That The Business Plan Product Development Processes: Creating Release n...