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

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. 验证结果

执行命令:

bash 复制代码
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 访问者化重构。
相关推荐
凡人叶枫7 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
noipp7 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
学逆向的7 小时前
C++纯虚函数
开发语言·c++·网络安全
凡人叶枫8 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
坚果派·白晓明10 小时前
【鸿蒙PC】SDL3 移植:AtomCode Skills 4 步速通多媒体库适配
c++·华为·ai编程·harmonyos·atomcode·c/c++三方库
赴生-10 小时前
C++进阶 C++11(下)
开发语言·c++
有点。10 小时前
C++(贪心算法一)
c++·贪心算法
WBluuue11 小时前
数据结构与算法:有序表(二):跳表
数据结构·c++·算法·skiplist
赴生-11 小时前
C++进阶 异常
开发语言·c++
凡人叶枫12 小时前
Effective C++ 条款28:避免使用 handles 指向对象内部
linux·服务器·开发语言·c++·嵌入式开发