深入浅出制作全自动Mud机器人-组件化
-
在全自动Mud机器人开发,以及长期的运维更新时,我觉得引入组件化是一件非常重要的底层架构。
组件化,看起来是一个和模块化接近的概念。但本质完全不同。
在我眼里,模块化是将相关的代码进行组织和封装,对外提供统一接口的一种代码组织形式。
组件化的确要依赖于模块化是实现功能。但更重要的是,组件化的目标是
可替代可废弃性。
随着Mud的更新,代码不应该进行大幅度的调整,还是废弃部分组件,新建部分组件,调整部分组件。这样,机器可以先将重点组件进行调整,然后临时禁用不重要的组件,甚至部分影响不大的组件带病工作,实现机器的边开发边运行。
既将代码根据易变程度分为不同的组织,确保核心代码的稳定性,然后组件中可以用各种快速/不健全/临时性的机制确保特殊状态下机器的可用性,以及确保机器处于一种可以从小到大,逐渐成长的状态。
为了实现这个目的,组件化需要实现的功能是
组件标准化
同一类的组件,应该有相同的接口和核心代码进行交互。这样,核心代码才能在调整主键时不需要关注细节和深入。
以我的newhelljs为例,使用了多种组件
- 角色准备阶段的提案组件
通过通用的Submit参数,实现判断是否进入某个准备阶段 - 任务本身的[Quest组件](https://github.com/hellclient-scripts/newhelljs/blob/main/script/src/core/quests.js
通过Ready参数,Cooldown属性,OnHUD/OnSummary|OnReport等接口,实现了人物与核心代码的隔离 - 配置的Condition组件
使得是否接任务/是否使用某个技能等等,都与核心代码无关,完全通过定义新的Condition实现。
很明显,组件标准化和能区分组件代码和核心代码的前提。如果不对组件进行标准化,则可扩展性可维护性也成了无根之水。
控制反转
控制反转(IOC)是一个常见的程序开发思路。
所谓的反转,就是将** 主程序创建类后,初始化类** 反转为 ** 主程序只负责创建类,类自行初始化)
实现了控制反转后,才能实现组件的封装,将组件与核心代码分离。
核心代码只负责两件事情:
如果你随手搜索一下,可能会发现一大堆依赖注入,工厂模式什么的复杂东西。
不用管那些,那些主要是对强OOP,静态编译的Java强调的东西。
对于js/lua的实现,参考我上面的例子中,都会传入一个函数作为参数就可以了。
把初始化函数放在组件的制定位置,核心代码创建组件后,把配置作为参数带入初始化函数就可以了。
这里说的控制反转,只是提醒一下,不要在核心端去设置组件,让组件自包含。
全局注册
全局注册很简单,就是建立一个全局的object/table变量,给每一个组件起一个唯一的字符串主键,将组件或者组件的生成函数都放在里面就行。
全局注册的目的是
- 在进行组件的替换/更新甚至顺序调整时,无需调整核心代码,只需要调整某个配置即可。
- 通过同一的调用方式,确保不会有其他位置的代码来直接调用组件内的代码,避免组件修改时出现全局问题。
- 方便的管理方式,能很容易的明白有多少个可用模块,不用去各个代码目录里寻找。
使用全局注册要注意的点是
- 只通过 注册的表 与组件交互,不建立直接处理的代码
- 在多个组件交互时,可以通过给组件加接口/全局事件/核心组里注册特殊毁掉的方式来处理。
重要的点
使用组件模式,其实是按照我们最初的目的来使用,也就是
- 将代码分为干净的核心代码,和脏(与业务更接近)的组件代码。确保代码指令控制在一个基本的可用度上。
- 通过配置,设置,能动态的调整激活的模块,实现更复杂的功能。
技术只是手段,代码如何处理,不一定要强求某个模式,还是为了实际目的服务。
- 角色准备阶段的提案组件
-
J jarlyyn 被引用 于这个主题