Framework Design Guidelines是微软对于好api设计的一个指导,当然针对的是.NET,其中对于Android/Java有裨益的记录一下。
命名
大小写
- 首字母大写:class、interface。对于IO这种缩写,所有字母都大写,例如IOStream
- 驼峰:其他所有。对于缩写,保持大小写一致,例如ioStream,fileIOStream
- xml中下划线:Android的xml里会用到下划线,按系统的逻辑,下划线是手动命名空间的分割线,例如layout_toLeftOf,layout是命名空间,toLeftOf是名字,中间用下划线分隔
- 类中下划线:非private的static变量都应该用全大写字母+下划线
命名内容
- 按正常语序排列单词
- 别怕长,说明白事情,少用缩写
- 避免匈牙利命名
- 是否使用语言强相关名称,比如getInteger。如果是有上下文语义的(getLength)不使用;如果是一个基础语言类函数(IntegerWrapper#getInteger),就应该使用
- 升级接口时,命名尽量接近,尽量用后缀来标示(方便自动完成),推荐直接使用版本号
包名
- 避免把公司组织架构带到包名中,组织架构太不靠谱了
- 包名合理的时候用复数
- 包名和包内类名不能重复
类名
- 类名用名词,interface用形容词组,I开头
- interface的默认实现,应该是interface名去掉I
- 泛型名用T,如果T不好使,就用以T开头的命名,例如
ISessionChannel<TSession>
- 如果继承自通用系统类(Map、Collection)最好加上相应的后缀(HashMap)
- 枚举用单数,除非是bitSet这种能够并存(取或)的
方法和成员变量
- 方法名用动词,避免get、set等易混名
- boolean型的命名都用正面形式,不要有don’tXxx
- .NET不推荐有类型前缀,但是Android官方比较推荐mFoo(member)和sBar(static)的写法
- 对于资源,命名要有层次结构。见xml中下划线
类结构设计
抽象类(abstract)
- 构造函数应该是protected而不是public的
- 应该有一个抽象类的实现,来考察设计合理性
静态类
- 工具类或者全局Context
Interface
- 避免空interface,宁肯使用一个成员变量来标示(之前用过IProguardKeep来简化proguard文件,不知道算不算)
- 有一个实现,有一个使用的地方
- 一旦暴露就不应该再改动
- 推荐抽象类而不是interface,除非有多继承或者设计模式上的需求,最好不要用interface,否则会有api升级的问题
Enum和内部类
- Enum分为常量和位操作(Java似乎不支持)
- Android不推荐使用Enum
- 内部类应该是对外不可见的,Android系统基本只有interface的声明会出现外部可见的内部类的情况
可扩展性
- 继承机制,最方便,但是应该限制于叶子类型(View)或者有替换能力的中间类型(Handler)。否则继承是没有效用的
- protected成员变量在继承过程中与public一样,避免过度暴露实现机制。特别是成员变量,还是private+protected getter setter比较好,封装一层(本人教训)
- 回调,用以插入逻辑(模板方法)或者改变整体行为(带返回的回调)
- 回调不能保证性能,因为被插入的逻辑不可知
- 回调尽量用lamda表达式,一定要预防未知异常
- 合理使用final来修饰方法,让继承更多的用于扩展而非修改基类
- 用多实现层次的基类来简化接入(Android中的Adapter系列)。对于不希望直接使用的类,即使不是抽象的也一定要用abstract。最好放到独立的包中
异常
- 不要使用error code
- Tester-Doer模式和Try-Parse模式,见
系统接口
- 接口中尽量用更抽象的Collection类
- 注意接口中变量的可变性
- 接口中泛型的类型一定要明确
- 接口中不要出现Iterator
- 在getCollection类接口中,不要返回null,返回空集合
- 要仔细考察CopyOnWrite的应用场景