关于注释。
复用性说起来容易做起来难,要想做到不仅要有好的接口设计,还需要非常优秀的文档。
josh 推荐注释每一个类、接口、方法、构造函数、参数和异常,这些注释 Java 源代码中比比皆是。
关于 API 性能。
错误的决定会消耗性能。比如:让类型可变、暴露构造器而不是静态工厂、使用具体的类型而不是接口。
不要「扭曲」API 设计来获得性能提升。性能问题总会得到改善,但是恶心的 API 设计会伴你永远。优秀的设计随之而来的是出色的性能。
类设计。
让可变性最小。如果没有足够的理由,类都应该是不可变的。优点:简单,线程安全,可以复用。缺点:每一个值都是不同的对象。
继承。
子类意味着可置换性。只有是is a关系的时候才用继承,否则用组合。
一个类不应该仅仅因为容易实现就去继承另一个类,错误示范:Properties extends Hashtable,Stack extends Vector。优秀示范:Set extends Collection。
继承违反了封装性,子类对父类的具体实现敏感,相当于有不止一个被修改的原因。
如果定义的类允许被继承,用文档标明。
保守策略,将具体的类声明为 final 类型,不可被继承。
方法设计。
模板能实现的功能,尽量不让客户端实现。减少样板文件,这些文件通常是复制粘贴而来,丑陋、烦人并且容易出错。
不要违反最小惊讶原则
快速失败,当异常出现时,尽快体现出来。
编译期最优,比如泛型。
在运行时,第一个错误方法执行时是最优的。
对所有可用数据以字符串的形式提供可编程式访问途径。作者举的是 Throwable 的例子,这样的返回数据对客户端比较友好。
谨慎重载
避免有歧义的重载。最好不要有参数数量相同的重载。
仅仅是因为这样做也可以,并不意味着这样做是对的。更好的办法是给方法重新命一个更易懂的名称。顺便提一句,Go 语言压根就不允许重载。这也在一定程度上说明重载不是一个好的设计。
如果你一定要提供有歧义的重载,务必确保相同的参数有相同的行为。
使用更合适的参数和返回值
入参支持接口类型而不是类
尽可能使用最确切的入参类型,将异常从运行期挪到编译期。(可以这样理解:如果你的方法参数声明成 Object 类型,那么在编译期,是无法识别出错误的,但如果你声明成更具体的 Student 类型,非 Student 类型就无法通过编译了)
如果其它类型更适合,避免使用字符串类型。字符串使用麻烦、容易出错并且执行速度慢。
在货币计算中,不要使用 float。
使用 double 而不是 float。性能损失有限,但是精度损失确实真实存在的。
按照习惯的参数顺序设计方法。作者举了 c 语言的例子,两个库函数,dest 和 src 的顺序不一致,容易让使用者产生困惑。通常习惯都是 src 在前,dest 在后。Java 就是这样设计的。
避免长参数列表。
两到三个参数是最理想的。多的话用户就得去参考文档了。
相同类型的参数列表有毒。如果程序员误把参数顺序弄错,程序依然能够正常编译运行,但是结果完全错了。这种是最危险的。
两个缩短参数列表的方法。1. 将方法拆分。2. 创建 helper 类型去保存参数。作者的代码实例如下,我貌似也写过这种,罪过,还好只是方法内部自己用的,只恶心自己。
避免返回需要特殊处理的值,返回零长度的数组或者 empty collection
领取专属 10元无门槛券
私享最新 技术干货