在设计Java API的时候总是有很多不同的规范和考量。与任何复杂的事物一样,这项工作往往就是在考验我们思考的缜密程度。就像飞行员起飞前的检查清单,这张清单将帮助软件设计者在设计Java API的过程中回忆起那些明确的或者不明确的规范。本文也可以看作为“API设计指南”这篇文章的附录。
我们还准备了一些前后比对的例子来展示这个列表如何帮助你理清设计需求,找出错误,识别糟糕的设计实践以及如何寻找改进的时机。
这个清单使用了如下的语言规范:
要 - 表示必要的设计
建议 - 表示在几个最好的设计中选择一个
考虑 - 表示一个可能的设计上的改进
避免 - 表示一个设计上的缺陷
不要 - 表示一个设计上的错误
1. 包设计清单
1.1. 共通
-
1.1.1. 建议把API和实现放入不同的包
-
1.1.2. 建议把API放进上层包,而把实现放进下层包
-
1.1.3. 考虑把一组大型的API分拆进不同的包
-
1.1.4. 考虑把API和实现打包进不同的jar包
-
1.1.5. 避免API的实现类之间的内部依赖
-
1.1.6. 避免把API分拆了太细
-
1.1.7. 避免把公共实现类放到API的包中
-
1.1.8. 不要在调用者和实现类之间建立依赖
-
1.1.9. 不要把没有关系的API放进同一个包
-
1.1.10. 不要把API和SPI(service provider interface)放进一个包(注:两者不同可以查看这个页面http://stackoverflow.com/questions/2954372/difference-between-spi-and-api )
-
1.1.11. 不要移动或者重命名一个已经发布的公共API
1.2. 命名
-
1.2.1. (一级)包名以公司(或者组织)的根命名空间来命名
-
1.2.2. 使用一个稳定的产品名称或者一个产品系列的名称作为包的二级名称
-
1.2.3. 使用API名称作为包名的(三级名称)结尾
-
1.2.4. 考虑把仅包含实现的包的名称中包含"internal"这个词(注:似乎“impl”更常见一些)
-
1.2.5. 避免使用组合起来的名称
-
1.2.6. 避免包名和包内的类名使用同样的名称
-
1.2.7. 避免在包名称中使用“api”这个词
-
1.2.8. 不要使用营销,计划,组织单元(部门)和地理名称
-
1.2.9. 不要在包名中使用大写字母
1.3. 文档
-
1.3.1. 为每一个包提供一个package.html
-
1.3.2. 遵循标准的javadoc的规范
-
1.3.3. 在API的开始处用一句短小的话来概括(描述)
-
1.3.4. 提供足够多的细节来帮助判断是否需要使用和如何使用该API
-
1.3.5. 指出该API的入口(主要的类或者方法)
-
1.3.6. 包含覆盖主要的,基本功能演示的样例代码
-
1.3.7. 包含一个指向开发者指南的超链接
-
1.3.8. 包含一个指向手册的超链接
-
1.3.9. 指出相关的API集合
-
1.3.10. 包含API的版本号
-
1.3.11. 用 @deprecated 标记出不再使用的API版本
-
1.3.12. 考虑添加一个版权声明
-
1.3.13. 避免过长的包概述
-
1.3.14. 不要在发布的javadoc中包含实现相关的包
2. 类型设计清单(这里的“类型”个人理解为一组Api)
2.1. 共通
-
2.1.1. 确保每种(设计的)类型都有单一明确的目的
-
2.1.2. 确保每种类型代表了(业务)领域的概念,而不是为了(技术上)的抽象
-
2.1.3. 限制类型的总数量
-
2.1.4. 限制类型的大小
-
2.1.5. 设计相关的类型时保持和原有的类型的一致性
-
2.1.6. 建议为多种public的类型提供多种(private)的实现
-
2.1.7. 建议接口的实现类和继承关系的类应该在行为上保持一致性
-
2.1.8. 建议用抽象类而不是接口解耦Api的实现
-
2.1.9. 建议使用枚举而不是常量
-
2.1.10. 考虑使用泛型
-
2.1.11. 考虑在泛型参数上增加约束
-
2.1.12. 考虑使用接口来实现多继承的效果
-
2.1.13. 避免为使用者的扩展(需求)进行设计
-
2.1.14. 避免深度的继承层次
-
2.1.15. 不要使用public内嵌的类型
-
2.1.16. 不要申明public和protected的变量
-
2.1.17. 不要把实现的继承关系暴露给使用者
2.2. 命名
-
2.2.1. 使用名词或者名词词组
-
2.2.2. 使用PascalCasing(驼峰命名法的别称详见http://en.wikipedia.org/wiki/CamelCase )
-
2.2.3. 缩写仅第一个首字母大写
-
2.2.4. 为类型的实际作用使用精确的名称命名
-
2.2.5. 为最常用的类型准备最短最容易记忆的名称
-
2.2.6. 所有异常都以“Exception”结尾
-
2.2.7. 使用名词的单数(比如用Color而不用Colors)来命名枚举类型
-
2.2.8. 考虑较长的名称
-
2.2.9. 考虑派生类用基类的名称结尾
-
2.2.10. 考虑为抽象类名称使用“Abstract”开头
-
2.2.11. 避免使用缩略语
-
2.2.12. 避免太通用的名词
-
2.2.13. 避免同义词
-
2.2.14. 避免在相关的Api中使用类型的名称
-
2.2.15. 不要使用仅大小写不同的名称
-
2.2.16. 不要使用前缀
-
2.2.17. 不要以“I”作为接口的名称开头
-
2.2.18. 不要(重复)使用Java核心包中的名称
2.3. 类
-
2.3.1. 最小化实现使用的依赖
-
2.3.2. 先列出public方法
-
2.3.3. 申明实现方法为private(这里是笔误吗?)
-
2.3.4. 为一个public抽象类定义至少一个public的shi
-
2.3.5. 为基本的使用情况提供足够的缺省实现
-
2.3.6. 设计基本上不变的类
-
2.3.7. 把无状态,访问器,扩展(mutator个人理解为多种参数形式的方法)方法集合到一起
-
2.3.8. 把扩展方法的数量控制到最少
-
2.3.9. 考虑设计一个默认的无参的构造方法
-
2.3.10. 考虑重写equal,hashCode方法
-
2.3.11. 考虑实现Comparable接口
-
2.3.12. 考虑实现Serializable接口
-
2.3.13. 考虑使类可以容易的扩展
-
2.3.14. 考虑申明类为final
-
2.3.15. 考虑为类的实例化提供一个public的构造方法
-
2.3.16. 考虑使用自定义的类型来增强类的不可变性
-
2.3.17. 考虑设计不可变的类
-
2.3.18. 避免静态类
-
2.3.19. 避免使用Cloneable
-
2.3.20. 不要向静态类中添加实例duixi
-
2.3.21. 不要为使用者不应扩展的public抽象类提供public的构造方法
-
2.3.22. 不要滥用初始化
2.4. 接口
-
2.4.1. 为每一个public接口提供至少一个实现类
-
2.4.2. 为每一个public接口设计至少一个消费方法
-
2.4.3. 不要对一个已经发布的public接口添加新的方法
-
2.4.4. 不要使用标记接口(标记接口详见http://en.wikipedia.org/wiki/Marker_interface_pattern )
-
2.4.5. 不要把public接口设计成常量的容器(这个实在很常见啊……)
2.5. 枚举
-
2.5.1. 考虑为枚举类型指定一个0值(“NONE”或者“Unspecialized”等等)
-
2.5.2. 避免只有一个值的枚举
-
2.5.3. 不要使用枚举实现开放式的值集合
-
2.5.4. 不要为将来可能增加的值设计枚举
-
2.5.5. 不要为已经发布的版本增加新的枚举值
2.6. 异常
-
2.6.1. 确保自定义的异常可以被序列化
-
2.6.2. 考虑为每种类型定义一个不同的异常
-
2.6.3. 考虑为代码访问提供更多的异常信息
-
2.6.4. 避免深层的异常继承
-
2.6.5. 不要从Exception和RuntimeException以外的类派生自定义异常
-
2.6.6. 不要直接从Throwable派生异常
-
2.6.7. 不要在异常信息内包含敏感信息
2.7. 文档
-
2.7.1. 为每种类型(的Api)配上概述
-
2.7.2. 遵循标准Javadoc的约定
-
2.7.3. 每种类型开头以一句短小的话概述
-
2.7.4. 为是否使用以及如何使用该类型提供足够的细节来帮助做决定
-
2.7.5. 解释如何实例化一个类型
-
2.7.6. 为一个类型的主要的使用情景提供样例代码
-
2.7.7. 包含指向到开发指南的链接
-
2.7.8. 包含指向手册的链接
-
2.7.9. 显示相关的类型
-
2.7.10. 用@deprecated标签申明过时的类型
-
2.7.11. 文档类具有不可变性
-
2.7.12. 避免冗长的类概述
-
2.7.13. 不要为私有方法生成Javadoc
3. 方法设计清单
3.1. 共通
-
3.1.1. 确保每个方法实现一个目的
-
3.1.2. 确保相关的方法都是一个粒度级别的
-
3.1.3. 确保没有混合调用方法的公共代码
-
3.1.4. 使所有方法的调用具有原子性(原子性:http://jiangyongyuan.iteye.com/blog/364010)
-
3.1.5. 设计protected方法时要像public方法一样慎重
-
3.1.6. 限制扩展方法的数量
-
3.1.7. 设计扩展方法需要具有较强的稳定性
-
3.1.8. 建议为一系列重载的方法设计一个泛型的方法
-
3.1.9. 考虑使用泛型方法
-
3.1.10. 考虑设计方法对,即两个方法的作用是相反的
-
3.1.11. 避免“helper”方法
-
3.1.12. 避免长时间执行的方法
-
3.1.13. 避免调用者在普通使用中需要手动写循环
-
3.1.14. 避免可选的参数影响方法的行为
-
3.1.15. 避免不可重复调用的方法
-
3.1.16. 不要删除一个已经发布的方法
-
3.1.17. 不要在没有提供替换方法前把一个已经发布的方法标记为过时
-
3.1.18. 不要修改一个已经发布的方法的签名
-
3.1.19. 不要修改一个已经发布的方法的可观测行为(也许指的是输出之类)
-
3.1.20. 不要增加一个已经发布方法的调用条件
-
3.1.21. 不要减少一个已经发布方法的调用结果
-
3.1.22. 不要为已经发布的public接口新增方法
-
3.1.23. 不要为已经发布的Api新增重载
3.2. 命名
-
3.2.1. 用给力的,有表达力的动词作为名称起始
-
3.2.2. 使用驼峰命名法(好奇怪,前面写的是PascalNaming)
-
3.2.3. 为JavaBean的私有属性预留“get”“set”“is”等访问方法
-
3.2.4. 使用对调用者熟悉的词语
-
3.2.5. 尽量使用英语口语
-
3.2.6. 避免使用缩略语
-
3.2.7. 避免使用一般的动词
-
3.2.8. 避免同义词
-
3.2.9. 不要使用“黑话”
-
3.2.10. 不要依靠参数的名称和类型判断方法的意义
3.3. 参数
-
3.3.1. 为参数选择最合适的类型
-
3.3.2. 在相关方法的调用中对参数为null值的处理保持一致性
-
3.3.3. 在相关方法中参数的名称,类型和顺序需要保持一致
-
3.3.4. 在参数列表中把输出的参数放到输入参数之后
-
3.3.5. 为重载的方法省略常用的默认参数以提供一个较短的参数列表
-
3.3.6. 在无关的类型中为相同语义的操作提供重载方法
-
3.3.7. 建议使用接口而不是具体类作为参数
-
3.3.8. 建议使用集合而不是数组作为参数和返回值
-
3.3.9. 建议使用一般集合而不是原始(无类型)集合
-
3.3.10. 建议使用枚举而不是Boolean或者Integer作为参数
-
3.3.11. 建议把单个的参数放到集合或者数组参数之前
-
3.3.12. 建议把自定义类型的参数放大Java标准类型参数之前
-
3.3.13. 建议把对象类型的参数方法值类型的参数之前
-
3.3.14. 建议使用接口而不是具体类作为返回值
-
3.3.15. 建议把空的集合而不是null作为返回值
-
3.3.16. 建议把返回值设计成可以作为其他方法的合法输入参数
-
3.3.17. 考虑为不可变参数设计一个副本
-
3.3.18. 考虑在内部存储弱引用的对象
-
3.3.19. 避免参数数量变更
-
3.3.20. 避免参数长度太长(超过3个)
-
3.3.21. 避免连续的同类型的参数
-
3.3.22. 避免用作输出或者输入输出的参数
-
3.3.23. 避免方法重载
-
3.3.24. 避免参数类型暴露实现细节
-
3.3.25. 避免boolean参数
-
3.3.26. 避免返回null
-
3.3.27. 除了Java核心Api,避免把类型作为不相关的Api的返回值
-
3.3.28. 避免把可变的内部对象作为返回值来引用
-
3.3.29. 不要把预先设置的常量作为整型值参数使用
-
3.3.30. 不要为将来的(扩展设计)考虑预留参数
-
3.3.31. 不要在重载方法中改变参数的名称的顺序
3.4. 异常处理
-
3.4.1. 只有在异常情况下才抛出异常
-
3.4.2. 只需要为可恢复的错误抛出已确认的异常
-
3.4.3. 为了通知Api使用错误而抛出运行时异常
-
3.4.4. 在适当的抽象层次抛出异常
-
3.4.5. 进行运行时预置条件的检查
-
3.4.6. 为一个被不能为null的参数抛出空指针异常
-
3.4.7. 为一个除为null以外异常值的参数排除非法参数异常
-
3.4.8. 为一个错误上下文环境中的方法调用抛出非法状态异常
-
3.4.9. 在错误信息中显示出参数的预置条件
-
3.4.10. 确保失败的方法调用不会产生单向的后果
-
3.4.11. 为回调方法中的禁止使用的Api提供运行时检查
-
3.4.12. 建议优先使用Java标准异常
-
3.4.13. 建议提供抛出异常的条件的查询方法
3.5. 重写
-
3.5.1. 使用@Override注解
-
3.5.2. 维持或弱化预置条件
-
3.5.3. 维持或者加强后置条件(不好翻译,大概output+effect的意思)
-
3.5.4. 维持或者加强不可变性
-
3.5.5. 不要抛出新增的运行时异常
-
3.5.6. 不要更改方法的类型(无状态,访问器或者扩展方法等)
3.6. 构造方法
-
3.6.1. 最小化构造方法中的工作
-
3.6.2. 为所有的属性设置合理的默认值
-
3.6.3. 仅把构造方法的参数作为一种设置参数的快捷方法
-
3.6.4. 校验构造方法的参数
-
3.6.5. 以参数相应的属性为其命名
-
3.6.6. 当提供了多个构造方法时,遵循指南对其进行重载
-
3.6.7. 建议使用构造方法而不是静态的工厂方法
-
3.6.8. 考虑使用无参的构造方法
-
3.6.9. 如果不是总需要新的实例,考虑使用静态的工厂方法
-
3.6.10. 如果你需要在运行时决定一个合适的类型,考虑使用静态的工厂方法
-
3.6.11. 如果你需要访问外部的资源,考虑使用静态的工厂方法
-
3.6.12. 当面临非常多的参数的时候,考虑使用生成器(builder)
-
3.6.13. 当需要回避直接实例化类的时候使用考虑private的构造函数
-
3.6.14. 避免创建非必需的对象
-
3.6.15. 避免finalizer
-
3.6.16. 不要从无参的构造方法中抛出异常
-
3.6.17. 不要向一个已经发布的类中添加显示的构造方法
3.7. Setters和getters
-
3.7.1. 以get开头命名一个返回值不为boolean的访问属性的方法
-
3.7.2. 以is,can开头命名一个返回值为boolean的访问属性的方法
-
3.7.3. 以set开头命名一个更新本地变量的方法
-
3.7.4. 校验setter方法的参数
-
3.7.5. 最小化getter和setter方法的工作
-
3.7.6. 考虑从一个getter方法中返回不可变的集合
-
3.7.7. 考虑实现一个private接口的集合替代public的集合属性
-
3.7.8. 考虑只读的属性
-
3.7.9. 设置可变类型的属性时考虑Defensive Copy(Defensive Copy详见:http://www.javapractices.com/topic/TopicAction.do?Id=15 )
-
3.7.10. 当返回可变类型的属性时考虑Defensive Copy
-
3.7.11. getter方法避免返回数组
-
3.7.12. 避免根据方法内信息无法完成的校验
-
3.7.13. 不要从getter方法中抛出异常
-
3.7.14. 不要设计只能set的属性方法 (仅有public的setter而没有public的getter)
-
3.7.15. 不要依赖属性设置的顺序
3.8. 回调
-
3.8.1. 设计时使用最严密的预置条件
-
3.8.2. 设计时使用最弱的后置条件
-
3.8.3. 考虑传递引用对象的方法中把回调接口作为第一个参数
-
3.8.4. 避免有返回值的回调方法
3.9. 文档
-
3.9.1. 为每个方法提供Javadoc注释
-
3.9.2. 遵循标准的Javadoc约定
-
3.9.3. 每个方法以一句短小的话作为概述
-
3.9.4. 申明相关的方法
-
3.9.5. 用@deprecated标签申明过时的类型
-
3.9.6. 显示所有过时方法的替换方法
-
3.9.7. 避免冗长的zhus
-
3.9.8. 包含常用的使用模式
-
3.9.9. (如果允许的话)包含null值的确切含义
-
3.9.10. 包含方法的类型 (无状态,访问器或者扩展)
-
3.9.11. 包含方法的预置条件
-
3.9.12. 包含算法实现的性能特征
-
3.9.13. 包含远程方法调用
-
3.9.14. 包含访问外部资源的方法
-
3.9.15. 包含哪些API可以在回调中使用
-
3.9.16. 考虑为了描述方法的行为而包含单元测试
英文原文:http://theamiableapi.com/2012/01/16/java-api-design-checklist/
相关推荐
本文详细介绍了PHP的基本语法、变量类型、运算符号以及文件上传和发邮件功能的实现方法,适合初学者了解和掌握PHP的基础知识。
公司金融整理的word文档
Prometheus Python客户端Prometheus的官方 Python 客户端。安装pip install prometheus-client这个包可以在PyPI上找到。文档文档可在https://prometheus.github.io/client_python上找到。链接发布发布页面显示项目的历史记录并充当变更日志。吡啶甲酸
DFC力控系统维护及使用
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
2019-2023GESP,CSP,NOIP真题.zip
博文链接 https://blog.csdn.net/weixin_47560078/article/details/127712877?spm=1001.2014.3001.5502
包含: 1、jasminum茉莉花 2、zotero-style 3、greenfrog 4、zotero-reference 5、translate-for-zotero 用法参考:https://zhuanlan.zhihu.com/p/674602898
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
python技巧学习.zip
2023 年“泰迪杯”数据分析技能赛 A 题 档案数字化加工流程数据分析 完整代码
echarts 折线图数据源文件
Visual Studio Code 的 Python 扩展Visual Studio Code 扩展对Python 语言提供了丰富的支持(针对所有积极支持的 Python 版本),为扩展提供了访问点,以无缝集成并提供对 IntelliSense(Pylance)、调试(Python 调试器)、格式化、linting、代码导航、重构、变量资源管理器、测试资源管理器等的支持!支持vscode.devPython 扩展在vscode.dev (包括github.dev )上运行时确实提供了一些支持。这包括编辑器中打开文件的部分 IntelliSense。已安装的扩展Python 扩展将默认自动安装以下扩展,以在 VS Code 中提供最佳的 Python 开发体验Pylance - 提供高性能 Python 语言支持Python 调试器- 使用 debugpy 提供无缝调试体验这些扩展是可选依赖项,这意味着如果无法安装,Python 扩展仍将保持完全功能。可以禁用或卸载这些扩展中的任何一个或全部,但会牺牲一些功能。通过市场安装的扩展受市场使用条款的约束。可
Centos6.x通过RPM包升级OpenSSH9.7最新版 升级有风险,前务必做好快照,以免升级后出现异常影响业务
5 总体设计.pptx
Python 版 RPAv1.50 • 使用案例• API 参考 • 关于 和制作人员 • 试用云 • PyCon 视频 • Telegram 聊天 • 中文 • हिन्दी • 西班牙语 • 法语 • বাংলা • Русский • 葡萄牙语 • 印尼语 • 德语 • 更多..要为 RPA(机器人流程自动化)安装此 Python 包 -pip install rpa要在 Jupyter 笔记本、Python 脚本或交互式 shell 中使用它 -import rpa as r有关操作系统和可选可视化自动化模式的说明 -️ Windows -如果视觉自动化有故障,请尝试将显示缩放级别设置为推荐的 % 或 100% macOS -由于安全性更加严格,请手动安装 PHP并查看PhantomJS和Java 弹出窗口的解决方案 Linux -视觉自动化模式需要在 Linux 上进行特殊设置,请参阅如何安装 OpenCV 和 Tesseract Raspberry Pi - 使用此设置指南在 Raspberry Pies(低成本自
原生js识别手机端或电脑端访问代码.zip
浏览器
内容概要:本文介绍了基于Spring Boot和Vue开发的旅游可视化系统的设计与实现。该系统集成了用户管理、景点信息、路线规划、酒店预订等功能,通过智能算法根据用户偏好推荐景点和路线,提供旅游攻略和管理员后台,支持B/S架构,使用Java语言和MySQL数据库,提高了系统的扩展性和维护性。 适合人群:具有一定编程基础的技术人员,特别是熟悉Spring Boot和Vue框架的研发人员。 使用场景及目标:适用于旅游行业,为企业提供一个高效的旅游推荐平台,帮助用户快速找到合适的旅游信息和推荐路线,提升用户旅游体验。系统的智能化设计能够满足用户多样化的需求,提高旅游企业的客户满意度和市场竞争力。 其他说明:系统采用现代化的前后端分离架构,具备良好的可扩展性和维护性,适合在旅游行业中推广应用。开发过程中需要注意系统的安全性、稳定性和用户体验。