# cilly-vm-cpp 重构复盘(第 1 阶段:SRP)

8 阅读2分钟

1. 目标与范围

这次重构只做一件事:围绕 SRP(单一职责原则),把 VM 里的“执行职责”和“统计职责”拆开。
重构范围如下:

  1. 栈组件从“带统计”改为“纯数据结构”。
  2. VM 通过观察者发布事件,不再内置统计接口。
  3. 同步修复测试与构建系统(Bazel 目标、依赖、测试名)。

2. 改造前的问题

改造前,VMStackStats 的职责边界不清晰:

  1. StackStats 同时负责 栈存储统计计数
  2. VM 对外暴露了 PushCount/PopCount/Depth/MaxDepth 等统计接口。
  3. 统计逻辑和执行逻辑耦合,改一处会牵动核心路径。

问题本质是:功能可用,但长期维护和扩展成本会持续升高。


3. 本次改动清单

3.1 栈组件更名与瘦身

  1. 文件重命名:
    • src/stack_stats.h -> src/vm_stack.h
    • src/stack_stats.cc -> src/vm_stack.cc
    • tests/stack_stats_test.cc -> tests/vm_stack_test.cc
  2. 类型更名:
    • StackStats -> VmStack
  3. 功能调整:
    • 删除统计职责,仅保留 Push/Pop/Top/At/Clear/Empty 等栈行为。
    • 保留 values() 只读接口供 GC root 扫描使用。

3.2 观察者机制落地(栈统计)

新增 IVmObserver / VmStackObserver

  1. IVmObserver 提供:
    • OnStackPush()
    • OnStackPop()
    • OnTestEmit(const Value&)
  2. VmStackObserver 专门负责统计:
    • push_count_
    • pop_count_
    • max_depth_

3.3 test hook 迁移到观察者

  1. VM 增加并打通测试事件路径:
    • TestEmit(const Value&)
    • NotifyTestEmit(const Value&)
  2. __test_emit(x) builtin 仍保持脚本语义不变,但内部统一走 VM 事件广播。
  3. 新增 VmHookObserver(基于 OnTestEmit),用于测试侧采集 emit 值。
  4. 测试代码从旧接口迁移为 observer 方式:
    • 旧:vm.SetTestEmitSink(...)
    • 新:VmHookObserver hook; vm.AddObserver(&hook);

3.4 VM 迁移

  1. VM 内部栈类型切换为 VmStack
  2. VM 增加 AddObserver(IVmObserver*)
  3. VM::Push/Pop 中增加事件通知:
    • Push 后广播 OnStackPush
    • Pop 后广播 OnStackPop

3.5 Bazel 构建修复

本次重构中,构建系统发生了两类问题并已修复:

  1. 测试目标名未同步
    • stack_stats_test 已改为 vm_stack_test 并更新到 test_suite(all)
  2. frontend 子包依赖冲突
    • 移除 //src/frontend:frontend 残留依赖。
    • //src:cilly_core 统一收口源码。
    • 修复 src/BUILD.bazeltests/BUILD.bazel 的依赖关系。

4. 验证结果

执行命令:

bazelisk test //tests:"all" --test_output=errors

结果:38/38 测试全部通过
说明这次 SRP 重构没有破坏现有行为。


5. 改造收益

  1. 职责更清晰
    VmStack 只管数据,统计逻辑归 VmStackObserver,VM 只负责执行与事件广播。

  2. 扩展更简单
    后续加 profiler/debugger,只需新增 observer,不必反复改 VM 核心执行路径。

  3. 构建更稳定
    Bazel 依赖图更干净,减少跨包引用造成的隐式构建错误。


6. 阶段结论

第 1 阶段(SRP)目标达成:
“将统计职责从核心执行路径剥离”已经完成,且测试全绿。
下一阶段可以按计划推进:

  1. DIP:GC 接口抽象化。
  2. OCP:Generator/AST 访问者化重构。