一个人 + AI,完成了4万行代码的重构。但这之后,我面临了一个新的挑战:如何让这套系统真正具备“被AI长期维护”的能力?
当我打开 ControlPropertyEditor.cpp 这个文件时,我找到了答案。它有三千多行,业务逻辑、UI创建、数据绑定、API调用全都搅在一起。这对AI来说,是一个无法吞咽的“巨兽” 。任何一个小的修改,都可能因为上下文的长距离依赖而产生意想不到的“幻觉”。
于是,过去几天,我做了两件事:
- 把“巨兽”拆成“军团” :对超过2000行的核心文件进行手术刀式的拆分,让AI能精准理解每一块“领地”的职责。
- 让分页表格“活”起来:为
PaginatedTableWidget实现了完整的事件绑定链路,包括双击弹窗、编辑回填等复杂交互。
这就是我这几天的全部工作。现在,我想聊聊这个过程,以及它如何让我的“一人+AI”模式再次进化。
一、 拆分“巨兽”:给AI一份清晰的地图
我最早重构时,虽然明确了分层,但ControlPropertyEditor这种“上帝类”的存在,依然是AI协同的最大障碍。AI在处理它时,往往因为看不到全貌而做出错误判断。
我采取的拆分策略是“按职责分包”:
我不再让一个文件处理所有事情,而是将 ControlPropertyEditor 这个“司令部”拆分成了若干个“独立团”,每个团只负责一项专项任务。
src/widgets/ControlPropertyEditor/
├── ControlPropertyEditor_ApiCall # 负责API调用配置的独立模块
├── ControlPropertyEditor_ComboBox # 专门处理下拉框数据源配置
├── ControlPropertyEditor_DataBinding # 负责复杂的数据绑定逻辑
├── ControlPropertyEditor_LeftForm # 处理主从复合控件的左侧表单
├── ControlPropertyEditor_TabEvents # 管理多页容器的切换事件
└── ControlPropertyEditor_Helpers # 存放共享的工具函数
这次拆分带来的几个关键改变:
- AI的“工作记忆”更集中了:以前,让AI修改一个API调用配置的逻辑,它需要读取整个3000行文件,这会导致注意力分散,经常误改旁边的ComboBox配置。现在,我把
apiCallConfig相关逻辑单独喂给AI,它在一个上下文清晰的200行文件内工作,修改精准度大幅提升,再也无须担心“改A崩B” 。 - 代码审查从“大海捞针”变为“定点检查” :我自己review代码时,也能快速定位到具体模块。逻辑内聚性变强,边界清晰,一眼就能看出问题。
- 为未来的“热插拔”打下基础:当每个配置模块都像这样独立时,未来如果我想让某个配置项支持插件化加载,也已经铺平了道路。
这验证了我的一个核心观点:代码规范,首先是让AI读得懂;而模块化,是让AI读得准。
二、 分页表格的“成人礼”:完整的事件绑定链路
如果说拆分模块是“苦功”,那么让分页表格支持完整的事件绑定,就是这周最“硬核”的攻关。PaginatedTableWidget 一直是系统的核心控件,但它之前更像一个“展示器”,而缺少完整的交互闭环。我需要让它能够响应双击、弹窗、数据回填。
这个功能的技术难点在哪?
对于一个配置驱动的系统来说,难点不在于写代码,而在于如何优雅地把“交互逻辑”抽象成“配置数据” 。
- 问题:用户在表格上双击一个单元格,系统怎么知道该弹哪个窗口?窗口的数据从哪里来?用户修改后,如何精确地回填到原表格?
- 解法:我将整个流程全部“配置化”。为此,我创建了一个新的独立模块
CellDoubleClickConfig来统一管理。
-
双击行为的配置化:表格不再关心双击了要干嘛,它只会根据当前点击的列,去查找
CellDoubleClickManager中的配置。这个配置定义了:- 模式:是弹出一个简单的编辑框(
Edit),还是弹出一个数据选择器(Picker)。 - 数据来源:如果是
Picker,那么调用哪个API (pickerApiCode),数据路径是什么。 - 回填规则:选择的数据应该映射到当前行的哪些字段 (
targetFieldMapping)。
- 模式:是弹出一个简单的编辑框(
-
交互的清晰解耦:
- 表格:只负责发出“我被双击了”的信号,并携带行列信息和当前行的原始数据。
- 处理器 (
CellDoubleClickHandler) :作为一个“事件路由器”,根据配置,判断是启动“编辑对话框”还是“选择器对话框”。 - 对话框:独立执行,专注完成它的编辑或选择任务,通过信号将结果传回给处理器。
- 回填:处理器收到对话框的结果后,调用表格的方法,完成数据更新。
-
UI与逻辑的彻底分离:这个功能的UI配置入口,我放在了
ControlPropertyEditor_CellDoubleClick这个拆分出来的独立模块中。服务商在配置时,完全不需要理解背后的C++逻辑,只需要在可视化界面上选择列、选择API、填好映射关系,整个流程就配通了。
这就是配置驱动的真正威力: 我们不是在写一个固定的交互程序,而是在创建一个描述“交互剧本”的语法。任何能读懂这个语法的人(或AI),都能编排出一套复杂的业务交互流程。
三、 写在最后:AI与代码结构的关系
经过这几天的密集拆解和功能开发,我越来越确信,AI时代的代码组织,应该以“上下文”为中心进行优化。一个2000行的文件,在非AI时代,虽然不优雅,但开发者凭借记忆和经验,勉强可以驾驭。但在AI时代,它就是AI幻觉的温床。
当我把 CellDoubleClickConfig 这种复杂逻辑拆解为清晰的多个小模块时,我实际上是在做一件事:
我在为AI铺路。
我不需要记住每一个API调用的细节,也不需要记住UI布局的层级关系。AI会替我记住。我只需要确保,当AI需要找到“双击回填”的逻辑时,它能精准地定位到 CellDoubleClickHandler 这个文件,而不是在三千行代码里大海捞针。
这篇文章的标题是“从巨兽到军团”。把系统比作一支军队,我现在做的,就是让这支军队的建制清晰起来。每个模块就是一个连队,它有自己的旗帜、自己的职责、自己的战场。而我的角色,也从那个事事亲力亲为的“班长”,变成了运筹帷幄的“指挥官”。
后续方向:
- 继续将超过1000行的高内聚核心类进行职责拆分。
- 完善
CellDoubleClickConfig的配置向导,让服务商能更简单地编排复杂的交互流程。