插件框架初想
前言
网上已经有很多关于插件设计的文章,但大多数都是比较粗浅的介绍了一些插件框架的基本原理,甚至有些只是说明了插件框架的一些加载接口。
我准备在本文中,尝试去理清插件框架背后的依据与逻辑。
UI与数据
从一个应用来说,可以简单分为数据与视图两个方面,数据是应用的内在表达,视图是数据的外在表现。这个道理是很浅显的,所以我觉得插件框架至少应该提供一种数据订阅机制,由视图UI或者其他逻辑模块来订阅某类数据的变化,从而进行数据的更新。
UI的扩展
一个功能的添加,除了进行数据的处理,往往需要提供数据的展示扩展。扩展意味着某个插件提供了扩展点,为了描述方便,将定义了扩展点的插件称为扩展点插件,实现扩展点扩展的插件称为扩展插件。
例如,有一个插件提供了菜单机制,但没有提供具体菜单,那么菜单就是扩展点,另外的插件可以扩展菜单扩展点,菜单扩展点插件根据扩展信息,对扩展的菜单进行展示。
插件需要提供一个扩展机制。
数据的扩展
一个功能的添加,除了进行视图的扩展展示,往往更主要是提供数据的定义扩展与数据处理扩展。
数据类型定义的扩展,一般指项目数据类型的扩展。例如,项目支持不同类型的数据,文件,图片,资源描述文件,cpp源码文件,xml文件等等。项目提供数据类型扩展点,定义了数据类型扩展点应该具备的接口,例如可能定义新建、编辑、显示等等接口。
数据处理的扩展,往往定义了针对某类数据的数据操作,往往通过右键菜单展示这些扩展的逻辑处理,或者是另外形式的数据扩展处理,可能通过流程管理工具进行扩展处理的组织。
数据处理还可以有另外的方式,服务。服务,可以是一种很通用的数据处理,例如XML解析服务,插件提供服务时 ,可能并没有插件使用,容许先提供服务,后进行服务使用的方式。而扩展,一般是明确了使用目的、场景,然后定义了扩展点,然后才进行了扩展实现。
插件应该具备的机制
通过以上两个章节的初步讨论,插件框架应该具备数据订阅、扩展与服务三个机制。扩展是先明确了使用场景,定义了扩展点,扩展插件对扩展点进行实现。服务是没有具体使用场景,可以服务于通用的场景,可以先进行服务提供,然后再有具体的使用需求。
对于扩展机制来说,框架应该能够将扩展实现通知给扩展点插件,当扩展点插件卸载时,可以通知扩展点插件。
对于服务机制,服务需求插件可以注册需求服务信息,当服务可用时,框架通知需求该服务的插件,当服务提供者卸载时,框架通知需求该服务器的插件。
数据订阅机制类似于服务机制,但又有所不同,通过一种事件机制进行订阅,一个数据或者状态或者动作都可以触发出一个事件,事件订阅者可以关注某类事件的发生。常见的事件有插件加载、插件卸载、APP启动、APP退出等、项目新建、项目打开、项目关闭等。
插件框架基础
扩展点
扩展点应该包含以下信息:
- 名称
- 扩展点接口
扩展点这两个信息可以被打包在插件中,并且通过命令能够导出插件的扩展点信息,从而方便扩展点实现。
扩展
扩展是对扩展点的具体实现,定义了实现的扩展点名称,实现的扩展点接口。
服务
服务应该包含服务名称,属性值定义,服务实现。并且服务提供插件应该包含服务的说明文档,有框架命令可以打开服务接口说明,方便服务的使用者进行服务接口调用。
事件
有一些事件是框架提供的,更多的事件就是插件提供的。事件应该包含,名称、事件数据结构定义。同样的,插件应该打包事件的定义信息,并能够通过命令导出事件定义说明。
基础功能包
一种基础辅助功能库,用于服务插件的实现。例如,为了实现服务的监控与注销,提供了一个服务监控实现,该实现在需要的服务有效时,记录该服务,插件使用时直接获取该服务使用。
插件依赖
功能往往由一组插件才能实现,所以插件之间存在一定的依赖关系,安装某个插件时,应该支持自动安装依赖插件。
项目数据
根据应用种类的不同,项目的定义也不相同。对于一个文本编辑应用,项目代表一个目录,或者代表一个文件。插件一般与某种类型相关相关,与项目完全无关的插件其实很少。
为了应用在某些方面可以有更好的兼容性,项目数据可以考虑使用通用结构组织。项目数据在一个插件中定义,定义数据扩展点,项目的组织管理基本概要,其他插件定义数据的扩展实现。对于需要进行序列化的项目,扩展实现需要负责具体的序列化与反序列化。
项目数据应该通过服务的形式提供。其他插件可以关注项目数据相关事件进行项目数据的处理,也可以主动通过服务获取项目数据,对项目数据进行遍历访问。
另外,根据本章项目数据的相关想法,未来插件可以按项目类型进行组织,可以关联在某个具体项目下,也可以关联在通用项目下。基于项目的后续插件管理,也是一个复杂的工程。
插件上下文
插件上下文是插件体系资源访问的中介。通过插件上下文可以获取插件信息、服务信息、扩展点信息、扩展信息等等。并且,插件上下文也是插件基础机制的提供者,提供了基础的扩展机制、服务机制、订阅机制。
插件加载
每一个插件是一个包形式,加载插件就是解压包,并对插件初始化文件进行加载。就应用而言,一般会有一个插件状态记录文件,记录插件是否加载的设置。
插件加载预期分为两个过程,插件描述读取,插件实现加载。插件描述读取,用来读取插件的基本信息,依赖关系信息,以及插件注册的相关信息。而插件实现加载,用来实现具体注册信息的实例化,并且进行相关的通知。
插件管理
插件通过包的形式发布,通过远程仓库进行包的管理,本地应用管理安装到本地的插件。
在插件框架中,通过插件上下文管理注册信息与提供基础的机制。插件加载框架主要负责对所有的有效插件进行加载,并执行入口APP插件。
APP入口插件
插件框架定义了一个入口扩展点,也就是APP扩展点,实现了个扩展点的所有扩展实现,都能被作为应用启动执行,但只有一个能被执行。
后续
后期会按照本文的想法,通过python实现一套插件框架,该框架预期主要针对桌面应用。希望通过这套框架能够让桌面应用在跨平台开发方面更加简单。