接口设计的几个注意事项

简介: # 本文的“接口” 本文的-"接口",等同于 [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) 类协议/框架中的接口,例如SOAP, Apache Thrift, Apache Avro, Microsoft DCOM, WCF 及集团内最常用的 HSF, Dubbo 等等。此外,还有一些 RESTful 规范/框架(如Jax-

本文的“接口”

本文的-"接口",等同于 RPC 类协议/框架中的接口,例如SOAP, Apache Thrift, Apache Avro, Microsoft DCOM, WCF 及集团内最常用的 HSF, Dubbo 等等。此外,还有一些 RESTful 规范/框架(如Jax-RS),在使用体验上也非常类似于 RPC,虽然通常不被归属于RPC, 但本文中的提到某些原则可能同样适用。

一次典型的RPC 请求/响应包含以下几个步骤:

  • 1) 客户端发起一次方法调用
  • 2) 客户端将调用(接口+方法+参数)进行打包
  • 3) 客户端将打包后的内容发送到服务器端
  • 4) 服务器端收到数据并解析为一次方法调用
  • 5) 服务器端在某对象上执行方法(参数)调用
  • 6) 服务器端将得到调用返回值,并对其打包
  • 7) 服务器端将打包后的返回值发送给客户端
  • 8) 客户端收到响应并解析响应数据
  • 9) 客户端得到方法的返回值

由于 2)~8) 的步骤对客户端是透明的,看似乎是本地方法调用,但远程方法调用是不同于本地调用的,使用时也不应该忽视他们存在着不同。
虽然不少框架没有对接口作出更严格的语法限制,但实际使用起来也不能太过任性,适当遵循一些规则习俗,会减少一些不必要的麻烦。以下就过往使用的经验,列举一些较常见的问题。

“接口”的定义

远程接口调用过程,发生了一次数据交换,即使用参数换得一个返回值或异常,一个普通的接口可能是这样的

public interface DemoService {
    public ResultType doAnything(FooType arg1, BarType arg2) throws MyException;
}

不同于本地方法调用的是,远程方法对参数、返回值、异常的定义限制的越“严格”越好-从某种意义上说,参数、返回值、异常的类型都是应该是 Struct而非 Class,那么区别在哪、又为什么这么说呢?

  • 1) Struct 侧重于字段-值,不可被扩展 - 这意味着Client/Server 每一端都不可能在协商好接口定义后单方面对数据进行“画蛇添足”,也不可能发送对方也许会不知道的数据类型,保证双方对收到的数据不存在产生歧义的可能。
  • 2) Class 侧重于功能-方法,通常允许扩展-这意味着 Client/Server 都有可能向对方发送一个对方并不知道的类。比如Client 向 Server 发送了参数 FooType 的扩展类 FooTypeExt, 而 Server 可能因无法解释 FooTypeExt 而产生意外异常。

一些很可能产生歧义的接口定义:

  • 1) 参数类型限定太宽泛,想返回什么都人合乎语法,无法保证 Server 一定会理解该参数
public int saveData(Object data);
  • 2) 返回类型限定太宽泛,想返回什么都人合乎语法,无法保证 Client 一定会理解返回值
public Object saveData(int id);
  • 3) 使用基础/抽象类型,一方可以随意 override 掉 BaseType 的某些行为而使用对方产生某些意外的效果
public int saveData(BaseType data);
public AbstractType getData(int id);
  • 4) 泛型接口,不应当使用
public interface IMyAPI<T extends BaseType> {
    pulic saveData(T data);
    public T getData(int key);
}

这样的接口定义了啥?

  • 5) 泛型方法,不应使用
public <T> T getData(int key);

这样的接口定义了啥?

由于 Java 不支持 Struct,在实际开发中,理论上应该只使用 final 修饰的 POJO 类作为参数/返回值类型,即使参数/返回类型不是密封类,也要避免使用它们的扩展类;
在需要使用 List, Map 等时,虽然语法允许使用它们的任意扩展类,但最好只使用JRE 包含的类而不要随意扩展。

“接口”的发布

“接口” 是Client/Server 数据交换的契约,接口所在包要被 Client/Server 所共享,因此这个包中最好仅是包含接口以及与接口相关的参数类型、返回值类型、异常类型,及其它公用的常量、枚举、资源等等, 而不应该包含Client或Server功能的具体实现
一个常见的现象是接口类被打包在 xxxx-client.jar 中而发布,这种方式存在以下多种问题。

  • 1) server 上仅为了获得接口类,就需要部署 client.jar 及其全部依赖项,导致引用了很多冗余的包。
  • 2) 接口定义经过双方协商后不会轻易变更,但 xxxx-client.jar 因包含有功能实现而会经常更新,继而引起接口使用方的连锁更新,而实际上又是不必要的。
  • 3) 一些接口测试/分析工具,为了获得接口定义,同样也不得不部署整个的 client.jar 及其依赖项。
    另一个常见现在是接口类被打包在 xxxx-common.jar 中发布,如果 common 库中包含有复杂的功能实现,同样也会引发上面两个问题。

小结:接口定义与期所在的包是同命运的,接口不更新则包不应该更新,包若更新则是表示接口已变。因此,在打包和发布接口时,尽量遵循以下

  • a) 把接口类及期附属的参数/返回值/常量/资源等发布在一个 xxxx-api.jar (xxx-service/interface.jar等)包中;
  • b) 不要在这个包中发布Client/Server 上的功能实现类;
  • c) 如果有 Client/Server 共同的功能类,那么把它打包在另一个 xxxx-common.jar(xxxx-shared.jar等) 中;
目录
相关文章
|
算法 Python
LightGBM高级教程:自动调参与超参数优化
LightGBM高级教程:自动调参与超参数优化【2月更文挑战第5天】
1802 2
|
2月前
ABCDEF题重磅更新|2025年华为杯|研究生数学建模|思路、代码、论文|持续更新中....
ABCDEF题重磅更新|2025年华为杯|研究生数学建模|思路、代码、论文|持续更新中....
220 3
|
1月前
|
人工智能 搜索推荐 机器人
07_大模型未来趋势:2025年AI技术前沿展望
2025年,人工智能技术正站在一个新的历史节点上。经过过去几年的爆发式发展,大语言模型(LLM)已从实验室走向各行各业,成为推动数字化转型的核心力量
|
2月前
|
缓存 安全 C++
C盘爆满电脑卡?3个简单技巧+1个便捷工具,小白也能轻松清理
电脑使用久了,C盘常因系统文件、软件安装和临时缓存堆积而空间不足,导致运行卡顿甚至蓝屏。本文教你识别C盘“隐形垃圾”,并提供3个手动清理技巧和1个实用工具(CCleaner),轻松释放空间,提升电脑速度,延长使用寿命。定期清理C盘,让电脑始终保持流畅运行。
679 0
|
SQL 关系型数据库 MySQL
如何查看本地公网 IP 地址?
如何找到本地的公网IP?这篇文章帮到你。
971 3
|
存储 Java 关系型数据库
“代码界的魔法师:揭秘Micronaut框架下如何用测试驱动开发将简单图书管理系统变成性能怪兽!
【9月更文挑战第6天】Micronaut框架凭借其轻量级和高性能特性,在Java应用开发中备受青睐。本文通过一个图书管理系统的案例,介绍了在Micronaut下从单元测试到集成测试的全流程。首先,我们使用`@MicronautTest`注解编写了一个简单的`BookService`单元测试,验证添加图书功能;接着,通过集成测试验证了`BookService`与数据库的交互。整个过程展示了Micronaut强大的依赖注入和测试支持,使测试编写变得更加高效和简单。
257 4
|
消息中间件 缓存 监控
Kafka性能优化策略综述:提升吞吐量与可靠性
Kafka性能优化策略综述:提升吞吐量与可靠性
1892 0
|
人工智能 安全 Android开发
OPPO召开AI战略发布会,联发科天玑芯构建AI手机时代计算底座
近期,OPPO举办AI战略发布会,会上正式推出了由OPPO AI超级智能体与AI Pro智能体开发平台共同构建的OPPO 1+N智能体生态战略。与此同时,OPPO与联发科展开深度合作,展示了双方在AI手机领域的创新成果,以共同推进“AI手机(AI Smartphone)”的发展,为广大用户带来更为智能、便捷和高效的下一代AI体验。
|
Python
python while true的语法和用法
python while循环语句的一般形式是while后面跟一个条件表达式,当该表达式的返回值为True,或经过布尔转换会返回True,比如1转换为bool布尔类型会为True,那么就执行一次while的循环。while True,即直接把表达式设置为True,那么无论如何,代码都将进行一次while的循环,直到遇到退出的条件,
738 4
|
数据安全/隐私保护 流计算
【计算机网络】数据链路层 : ALOHA 协议 ( 纯 ALOHA 协议 | 时隙 ALOHA 协议 )
【计算机网络】数据链路层 : ALOHA 协议 ( 纯 ALOHA 协议 | 时隙 ALOHA 协议 )
1884 0