GitHub 上的好玩文章:正交的 Koishi

今天也在 GitHub 搜 Koishi,搜到了这个,看起来也不是官方发的,但是感觉好好玩,就转载过来了。

我感觉这篇文章里讲的东西是很有道理而且已经用上了的,非常厉害。

1 个赞

正交的 Koishi

正交性最为最核心的 Koishi 开发哲学,是许多其他设计模式的基础。

一、定义

正交性并非 Koishi 提出,而是早已普遍应用的软件开发范式。在 Koishi 开发哲学中,正交性特指一切能够被复用的行为都应该被插件独立控制。与传统解释的区别在于,正交的 Koishi 并非实现范式而是设计范式,其目的是赋予用户最大的自主权和创造性,同时确保插件生态的一致性和可逆性。

二、设计动机

实现了「正交的 Koishi」的项目会拥有以下优点:

2.1 细粒度控制

即便一个插件没有提供任何配置项,用户也能控制插件的大量行为,包括但不限于权限管理、速率控制、文本替换、上下文过滤等。

2.2 一致性

用户得以通过统一的页面配置不同插件的行为,降低了学习成本和心智负担。

2.3 可逆性

正交性可以让各项功能得以有效解耦,从而允许服务开发者设计出自回收的 API。

三、生态现状

目前的 Koishi 生态普遍依赖此模式。

3.1 控制台页面

Koishi 官方的控制台插件提供的不同页面恰好管理了不同的功能:

  • 指令管理:给指令更名、权限管理、速率控制、调整层级关系
  • 本地化:覆盖任意输出文本
  • 插件管理:提供统一的配置界面
  • 数据库:查看和编辑数据库
  • 下载管理:管理插件的下载资源 (WIP)

一个插件可能同时访问多种服务所提供的资源,而用户在访问控制台时,既可以基于插件又可以基于服务进行配置。两者之间还通过跳转按钮建立了联系。

3.2 抽象服务

Koishi 依照正交性原则设计了许多抽象服务,即某个功能同时被多个插件实现:

  • database:数据库服务
  • assets:资源管理服务
  • cache:缓存服务
  • translator:翻译服务
  • censor:内容审查服务

3.3 大型插件的拆分

许多大型插件也依照正交性原则进行了有效的拆分:

  • koishi-plugin-dialogue
  • koishi-plugin-nonebot

四、实现原理

Koishi 基于 Cordis 开发,后者作为 AOP 框架,提供了多种方式实现正交性。尽管这已经是软工领域熟知的话题,但具体到 Koishi 的实现上还是有一些值得介绍的地方。

4.1 模块扩张与声明合并

Koishi 是少有的不通过 DI 实现 AOP 的框架。得益于 TypeScript 优秀的 模块扩张 (Module Augmentation)声明合并 (Declaration Merging) 机制,Koishi 得以实现服务类型的自动导入,并通过更多的服务践行正交化的开发。

4.2 事件和插件系统

事件和插件是 AOP 的传统开发范式。Koishi 扩展了 Node.js 原生的 EventEmitter,既实现了更丰富的触发形式,又为所有的 API 确保了可逆性。在插件系统方面,Koishi 按依赖关系决定插件的加载顺序,解决了服务类插件面临的难题。

4.2 配置混入

在轻量级和贴近用户的场景下,部分功能也会使用配置混入的方式实现正交化。这其中最普遍的是对指令配置的使用。

五、对比

5.1 正交与可逆

为了确保服务 API 的可逆性,通常需要对服务进行正交化设计。

5.2 正交与其他特性

正交性设计将大量代码从插件转移到服务中,使得插件的可迁移性增加。只要从少数服务入手就能实现 Koishi 的零占用、零状态和 0dt。

2 个赞

我总感觉在哪里看过差不多的文章 :face_with_monocle:

1 个赞

怎么绘世呢 :face_with_monocle::face_with_monocle::face_with_monocle:

框架要拆,插件要拆,文章也要拆,这才能称得上 Koishi 人

3 个赞