决策流程这个场景,适合树而不是层。树是前后依赖的,层是前后不依赖的、每一层是通用的。规则引擎天生就是规则流,前后有依赖,所以写规则配置就是树的方式。

现象

树的方式对人是友好的,非常直观、快速理解。

如果我想知道我们是否支持 xxx + xxx 的组合,从左到右很快能得到答案。

如果是层,那么你需要知道每一层的逻辑,同时你还需要知道层与层之间的关联。

所以,决策流程这个场景,适合树,而不是层。

我们的场景

我们的场景是通过环境信息(cpu 架构、型号、qemu 版本等)设置 xml 配置。

这个场景推荐用树的方式,核心原因是架构(arm/x86)是"分支决定性条件",后续逻辑完全依赖该分支,树结构能天然贴合独立流程、降低耦合。

  1. 逻辑贴合度高:你的需求本质是"架构分流 → 各自校验 qemu 版本 → 各自输出结果",树结构的"分支独立"特性和这个流程完全匹配;
  2. 维护成本更低:后续若扩展(比如 arm 新增"内存≥4G"条件、x86 修改 qemu 版本要求为 > 5.0),树结构可直接在对应分支修改,不影响另一分支;
  3. 可读性更强:树结构能直观呈现"arm 线"和"x86 线"的完整流程,排查问题时可直接定位到对应分支。

还有关键一点,我们的场景每个流程线能复用的层比较少,比如 arm 直接就是 passthrough,后面流程都是针对 x86 设计的。

树 vs 层

如果是无依赖的过滤,反而适合写代码,比如 k8s apiserver 里的 webhook。

如果是决策流程,其实是规则流程,就适合规则引擎。

因为规则引擎天生的逻辑就是上一个规则结果传入下一个规则结果,它是前后有依赖的。

而无依赖的是独立的,代码更容易实现扩展性、精确性和复杂逻辑,且就算变化也是局部变化。

层结构更适合"条件无依赖、逐步缩小范围“的场景(比如先过滤系统类型,再过滤内存,最后过滤硬盘,每个条件不依赖前一个的具体结果)。

而你的场景中,qemu 层的判断逻辑(“满足版本后输出什么”)完全依赖前一层的架构结果,用层结构会导致:

  • 同一层(qemu 层)需要嵌入"架构 arm"“架构 x86"的分支判断,违背"层是通用过滤"的设计初衷;
  • 新增架构(比如 risc-v)时,需要修改所有后续层的逻辑,扩展性极差。

核心总结

  • 树是前后依赖的;
  • 层是前后不依赖的,每一层是通用的;
  • 规则引擎的设计,天生就是为了规则流,前后就是有依赖的;
  • 所以写规则配置的时候,就是树的方式,很难用层的方式;
  • 层因为其通用,很可能有较大的复杂性,且还需要扩展性,一般适合用代码实现;
  • 但是因为其通用和局部性,修改难度低,用代码反而比用规则引擎简单。

一切都是为了 kiss。

小结

  • 决策流程这个场景,适合树而不是层;
  • 树是前后依赖的,层是前后不依赖的、每一层是通用的;
  • 规则引擎天生就是规则流,前后有依赖,所以写规则配置就是树的方式;
  • 无依赖的过滤适合写代码,决策流程适合规则引擎;
  • 一切都是为了 kiss。