当前位置:首页 > 技术文章 > 架构设计原则:选择 SPI 还是 API ?

架构设计原则:选择 SPI 还是 API ?

go1231个月前 (11-01)技术文章97

分享概要 背景 从面向接口编程说起 “接口”位于“调用方”所在的“包”中 “接口”位于“实现方”所在的“包”中 “接口”位于独立的“包”中 需要注意的事项 场景图 一、背景第一次听说 SPI 是阅…

一、背景

第一次听说 SPI 是阅读《软件框架设计的艺术》,以后陆续在 JDBC 和 SpringBoot 中发现了以这种形式组织代码的方式,本位给出为什么要区分 SPI 和 API 的一个思考过程。

二、从面向接口编程说起

我们在“调用方”和“实现方”之间引入了“接口”,上图没有给出“接口”应该位于哪个“包”中,从纯粹的可能性上考虑,我们有三种选择:

  • “接口”位于“调用方”所在的“包”中。

  • “接口”位于“实现方”所在的“包”中。

  • “接口”位于独立的“包”中。

下面让我们依次分析这三种可能性,如果现实中确实有这种可能性,不如我们就为其起个名字以方便交流。

三、“接口”位于“调用方”所在的“包”中

我们先想象一个场景,以仓储的接口为例:

我们将“仓储接口”放置于“领域层”这个“包”中,实现放在一个独立的“包”中,我们看DDD大师的实现都是这样子,现在来思考一下为什么这么做。

“领域层”的“领域服务”会依赖“仓储接口”,“仓储接口”也会依赖“聚合根”,这两者都是除了“实现依赖”之外的依赖关系,如果将“接口”放到“仓储实现”中就丧失了面向接口编程的意义(编译也不会通过),如果放到“独立层”中呢?会编译不通过,出现双向依赖了。

对于类似这种情况下接口,我们将其称为“SPI”,全程为:service provider interface,“SPI”的规则如下:

  • 概念上更依赖调用方。

  • 组织上位于调用方所在的包中。

  • 实现位于独立的包中。

  • 常见的例子是:插件模式的插件。

四、“接口”位于“实现方”所在的“包”中

我们先想象一个场景,以Unity提供的IUnityContainer接口为例,除了维护这个框架的团队之外,我们没有发现谁实现了这个接口,虽然理论上是可以实现这个接口的(如果能实现的话,我们何不自己弄额Ioc容器呢?)。

对于类似这种情况下的接口,我们将其称作为“API”,“API”的规则如下:

  • 概念上更接近实现方。

  • 组织上位于实现方所在的包中。

  • 实现和接口在一个包中。

五、“接口”位于独立的“包”中

这里就不说场景了,如果一个“接口”在一个上下文是“API”,在另一个上下文是“SPI”,那么你就可以这么组织。

六、需要注意的事项

不管是 SPI 或 API,接口都是可以组织到独立的“包”中,这么做是否有意义,自己来做出决定了。

SPI 和 API 也不一定是接口,我这里都是指狭义的具体的接口。

七、场景图

每一次思考都伴随着收获,也离不开和朋友们的交流,天更蓝了。

1、SPI 接口

1)定义 :SPI 是一种服务提供者接口,它允许在运行时加载不同的服务实现。

2)使用场景 :

  • 模块化设计 :当系统需要高度模块化,且希望将核心功能与具体实现分离时。

  • 可插拔架构 :需要支持多种服务实现,并且可以在不修改代码的情况下替换或增加新的服务实现。

  • 服务发现 :在运行时根据配置或服务注册表动态发现和加载服务。

  • 微服务架构 :在微服务架构中,SPI 可用于服务间的动态交互和集成。

3)优点 :

  • 提供了一种机制来在运行时选择和加载服务实现,增加了系统的灵活性和可扩展性。

  • 支持服务的热插拔,无需重启系统即可更换服务实现。


2、API 接口

1)定义 :API 是一组预定义的函数、协议和工具,用于构建软件应用,它定义了软件组件之间交互的契约。

2)使用场景 :

  • 客户端和服务器交互 :当需要设计客户端和服务器之间的通信协议时。

  • 库和框架 :提供给开发者使用的库或框架的公共接口。

  • 第三方集成 :需要与第三方系统或服务进行集成。

  • 内部组件通信 :在大型系统中,不同组件或模块之间的交互。

3)优点 :

  • 为开发者提供了清晰的接口文档和规范,易于理解和使用。

  • 有助于保持系统的稳定性,因为 API 变更需要遵循版本控制和兼容性规则。

  • 促进了代码的重用和模块化。

3、如何选择?

选择使用 SPI 还是 API 的考虑因素:

  • 扩展性 :如果需要在不修改代码的情况下扩展功能,SPI 更合适。

  • 交互性 :API 更适合定义系统内部或系统之间的稳定交互接口。

  • 动态性 :SPI 允许在运行时动态发现和加载服务,而 API 通常在编译时就已经确定。

  • 安全性和稳定性 :API 由于其稳定性和可预测性,通常更受青睐。SPI 虽然灵活,但可能引入运行时错误。

  • 版本控制和兼容性 :API 变更需要考虑版本控制和向后兼容性,而 SPI 可以通过服务版本协商来处理兼容性问题。

架构是“取舍”,而非“银弹”。

来源:dbaplus社群

声明:本站所有内容均为自动采集而来,如有侵权,请联系删除
标签: SPI

相关文章

Redis连环五十二问!看谁顶得住?

Redis连环五十二问!看谁顶得住?

基本 1.说说什么是Redis? Redis是一种基于键...

用 PHP 处理 10 亿行数据!

用 PHP 处理 10 亿行数据!

今天,我将带大家一起走进“挑衅十亿行“数据的世界。当然,这个事情是依据GitHub上的一个“十亿行挑衅”(1brc)运动而来,现在正在进行,如果你没有听说过,可查看Gunnar Morlings 的 1brc 存储库。https://github.com/gunnarmorling/1brc我之所以...

2024 年的最佳 PHP 框架

2024 年的最佳 PHP 框架

在本文中,我们将预测在 2024 年持续风行的最佳 PHP 框架。我们首先将看看PHP框架是什么,什么时候该斟酌应用PHP框架,以及应用PHP框架的重要长处都是什么。我还会介绍最合适初学者的 PHP 框架以及用于 Web 开发的最佳框架。什么是PHP框架?     &...

一文读懂多家厂商的大模型训练、推理、部署策略

一文读懂多家厂商的大模型训练、推理、部署策略

4 月 20 日,第 102 期源创会在武汉胜利举行。本期邀请来自武汉人工智能研讨院、华为、MindSpore、京东云、Gitee AI 的人工智能专家,环绕【大模型竞技与性能优化】主题发表演讲。接下来就一起看看本期运动的出色瞬间吧!大合影 get ✅披萨和礼物不能少!接下来进入主题演讲回想环节。可...

请立刻停止编写 Dockerfiles 并使用 docker init

请立刻停止编写 Dockerfiles 并使用 docker init

您是那种认为编写 Dockerfile 和 docker-compose.yml 文件很苦楚的人之一吗?我承认,我就是其中之一。我总是想知道我是否遵守了 Dockerfile、 docker-compose 文件的最佳编写实践,我畏惧在不知不觉中引入了安全破绽。但是现在,我不必再担忧这个问题了,感激...

服务器为什么大多用 Linux 而不是 Windows ?

服务器为什么大多用 Linux 而不是 Windows ?

前几天在知乎看到一个话题很有意思,且很有讨论意义。“服务器为什么大多用 Linux”,除了开源、好用等原因,回答也代表了各种不同人需求和看法,摘取一些分享给大家,也欢迎留言讨论。来自知乎好友“熊大你又骗俺”的回答首先在20年前,windows server+iis+asp+access 的方案,还是...