月度归档: 2026 年 2 月

关于我在2026年重构一个15年前的项目的事儿(一)

起源

我一直在维护几个旧站点。其中一个是我和几个在我小学、初中时候认识的网友一起开办的宝可梦主题的论坛。

它从架设起来开始就一直没怎么升级过,所以从我接手托管开始到现在,它一直是 Discuz! 6.1F 这个很早的版本。上次手动升级它的架构还是让它支持 php 5.7(是的它之前是为php4设计的,后来php5.2是它最后一个兼容的版本,但是它有一个 break 的 bug),那会儿做了不少兼容的事情,也熬了不少夜。

但有一说一,它本身还算比较坚固,因为当初的几个网友里面有一位年少有为,曾经在 FreeDiscuz! 这个项目组里面贡献代码。虽然后来因为大人的原因 Discuz! 恢复开源,加上各种原因没有继续,但是在6.x这个ajax 刚刚兴起的时代时候的 Discuz!6 还是非常好用的。

但它面对现在互联网上几亿亿倍的随机流量以及99%+的机器分布,还是力不从心了。

一切的起因是有一天晚上我发现机器的 php-fpm 一直在跑满,仔细一看发现这个项目被机器人自动发现了一个高流量下的bug: Discuz! 6.1F 有一个通过 url 中的 sid={A-Za-z,6} 参数作为临时 session 的设计,是在兼容早期客户端读写 Cookies 失败时候依旧能保留登录态的设计,所以它独立在用户登录态以外且直写 MySQL 。在大量用户反复短期登录/退登的时候,它很快就会把 dz_session 这张表写满,然后 php-fpm 就会雪崩。

恰逢我刚换新的部门,加上家里事情很多,只能临时关掉了。

关于LLM和编码

都在说 2025 年是 AI 元年,但实际上 2025 年下半年成熟的 cursor、claude code 才基本让简单编码这件事情变得普惠化。LLM AI Coding(我也不太喜欢 Vibe Coding 这个词)本质上通过 LLM 推理代替了一定的技术设计过程,让用户可以用自然语言生成机器指令并能在一定闭环情景下完成这些指令。从 LLM 本身的特性来看,其实很多人做的事情本身就是在重复其他人做过的事情,所以模型才会基于推理给出要做的事情的正确路径,其实这还正好符合重构的场景。

我也买了 cursor、claude code,无论是工作还是在休息时间,都在大量使用。在论坛崩掉前两周,我还在讨论这个问题:

有没有人尝试过用AI重写那些十几年、几十年前的稳定版工具?
我来举个例子,比如 Discuz!6.x。 ​​​

因为我发现,现在基于 LLM + AI编码工具的 showcase 基本都是对于新产品的高效生产,但很少有人讨论 LLM 如何遵循旧系统逻辑,把历史产品使用新的技术栈重构。于是,那就试试吧。

第一次尝试

我选择了 claude code + GLM-4.7,成本够低,token window够大。

一切的起点很简单,一段看起来很华丽的话,加上原站点的文件+表。

你现在是一个重构项目的指挥官。为了保持当前会话尽可能长的上下文,你需要自己规划启动其他的 claude code实例来完成你拆解的任务,并且尽可能将子实例需要的上下文传递清楚。

任务整体详情:
在D:\Dev\poketb.com下有一个我的历史项目,它的目录下的几个sql文件分别是它用到的数据库(完整dump)和表结构。
已知核心项目是bbs目录(Discuz 6.1F),因为它实在太老了,所以我需要**完整**将它的所有功能使用新的技术栈重构。
首现,在d:\dev下面新建一个全新的任务空间(不要用上次用的poketb-bbs-refactor,那个是单个claude实例创建的,上下文超了之后有很多错误的地方),所有的改动都在新的任务空间目录下创建。
首先需要理解项目,可以结合web搜索理解 Discuz 6 的系统设计,并且规划与上下文系统的关系,举个例子,Ucenter在这个站点的情况下只有一个bbs应用,就是不需要的设计。
然后,进行技术选型。在之前的单进程模式里面规划了 typescript + next.js 14 + mariadb 的技术栈,在这个大主题下评估每个历史模块(比如我现在能想到的,可见即所得编辑器)的技术选型和开发方案。
这些方案需要落在doc下面。
然后,另外的要求是需要尽可能保持现在论坛的前端样式、交互不变,但需要更新为现代样式系统,另外需要规划包含尽可能完善的移动版的页面。移动、PC版模板系统需要分开。
然后,主指挥官需要先通过项目理解尽可能清晰、细化的理解原系统的系统模块设计(最好能细化到模块粒度),并在重构的过程中模块 by 模块的确认每个核心功能逻辑完成迁移。
如果有一些模块的初始化数据在数据库中,但数据dump太大的话,尝试在上下文中使用简单的mysql实例来导入并进行数据获取。
指挥官需要尽可能保持自己的的会话的长时间。如果确实超过了上下文,需要设计上下文保存、恢复机制并尽可能尝试自我恢复。

在开始之前如果有需要我确认的信息,问我,不要自己决定。

读过上面这段文字的就会意识到,这不是第一版。原因很简单,如果你不告诉 claude code 应该用 sub agent 去工作的话,它会把理解项目、写规划、写新项目全都放在一个单进程里,这显然会超过 context window,甚至还会 oom 。

另一个我发现的问题是,无论是 claude code 还是 cowork 还是 cursor ,它们对 windows 开发环境的实施实在是太差了—— claude code 给自己单独装了个 MingGW ,cursor 每次尝试跑指令都会先生成 wsl 跑错了再回来 powershell ——不过还好它还能跑个三天,做出来一个“我已经觉得实现了80%!”的“新重构论坛”。

当然没跑起来啦,今晚因为它自己把 Token 限额跑超了,第一次实验就以失败告终了。

说回这个第二次的起点 prompt ,起了subagent+skills也是一样的问题,claude 自己压缩上下文窗口后会丢掉信息,导致中间重写的宠物系统完全是自己想象的;对于旧项目的探查也非常不仔细,只看了几个 api php 文件就开始写。

当然,最后导致它走不下去的原因,其实还是它被我本机的环境误导,并在今晚把 token 限量跑完了。

原因也很简单,我这个系统也是我用了很多年的一个旧系统,虽然一路升级到 Win11 也在不停换平台,但是很多系统设置还是十年前的。比如我的 3306 端口其实是我的 RDP 端口,然后 claude code 写完设计尝试连 mysql 写表,结果怎么都连不上,甚至还把我的 mysql 卸载重装了还是装不上,于是就设计了一个 dev 模式用 sqlite ,线上用 mariadb 的模式。

结果,它就在同步两边表结构的时候,进入了死循环,把自己跑挂了。

所以其实直接给到复杂指令(探查+设计+实施)对于现在的 LLM AI Tools 还是太难了,还是需要其他的设计。