三次迭代踩坑实录:表达式解析从0到完整实现

秦康-24371236 2026-04-01 21:39:44

三次迭代踩坑实录:表达式解析从0到完整实现

一、写在前面:这三周我到底做了个啥

这三周的面向对象作业,我一步步把一个只能算加减乘幂的简单表达式解析器,迭代成了能支持x/y双变量、指数函数、自定义函数、递推函数、求导/梯度的完整表达式引擎。

从最开始只会拆括号,到最后能处理 dx、dy、grad、f{n-1}(x) 这种复杂语法,整个过程一边踩坑一边重构,也算真正体会到了面向对象迭代开发的感觉。

二、三次迭代:需求一点点堆上来,我也一点点往上补

第一次作业:最基础的表达式展开

第一次要求很单纯:输入带+、-、*、^、小括号的单变量表达式,把所有括号展开、合并同类项,输出最简形式。

当时我主要做了这几件事:

  • 搭了最基础的递归下降 Parser,能把字符串拆成语法树
  • 写了 Expr 表达式类和 Monomial 单项式类,用来存项、做运算
  • 实现括号展开、幂运算、同类项合并
  • 第一次真正理解:表达式要先解析,再运算,最后输出

难度不算大,但第一次写递归下降,还是卡了挺久。

第二次作业:加了指数、选择因子、自定义函数

第二次在第一次的基础上突然加了不少东西:

  • exp() 指数函数
  • 三目选择式因子 [(a==b)?x:y]
  • 自定义普通函数调用 f(x)

我当时的做法是:

  • 给 Node 接口加了 ExpNode、SelectionNode、FunctionCallNode 这些新节点
  • 扩展 Expr,让它能识别和存储指数项
  • 加了 FunctionRegistry 来存函数定义
  • 尽量不推翻第一次的结构,在原有框架上扩展

这次最大的感受:第一次的架构好不好,直接决定第二次改起来痛不痛苦

第三次作业:双变量 + 求导 + 递推函数,直接拉满难度

第三次是最终版,也是最难的一次:

  • 新增变量 y,变成双变量表达式
  • 支持 dx( )、dy( ) 求导、grad( ) 梯度
  • 支持递推函数 f{0}, f{1}, f{n-1}, f{n-2}

我主要做了这些调整:

  • 重构 Monomial,同时存 x 次数、y 次数、指数参数
  • 写 DerivativeNode 处理求导语法,在 Monomial 里实现求导逻辑
  • 加 EvalContext 上下文,用来传函数、变量、递推下标
  • 给递推函数加缓存,避免重复计算爆炸

这次重构最多,但也最有成就感——整个结构终于稳定下来了。

三、我的代码结构:高内聚、低耦合,我是这么理解的

我这套代码整体分成三层:Parser 解析层、Node 语法树层、Expr 表达式运算层

内聚性:每个类只干一件事

  • Monomial:只管单项式本身——存 x、y、指数项,做乘法、求导、格式化,不掺和解析和整体运算,非常专一。
  • Expr:只管表达式整体运算——加减乘幂、合并同类项、求导、输出,不关心字符串怎么解析。
  • Parser:只管把字符串变成语法树,完全不参与计算。
  • 各种 Node:比如求导节点、指数节点、函数调用节点,每种只处理一种语法,职责很清晰。

简单说:一个类只负责一块功能,不会乱七八糟堆代码

耦合度:依赖关系很干净,不乱串

  • 整体是单向依赖:Parser → Node → Expr → Monomial,没有循环依赖。
  • 都面向接口编程,Node 只暴露 expand 一个方法,互相之间不直接调用细节。
  • 用 EvalContext 把运行时信息包起来,函数、表达式、上下文之间不硬耦合。

所以后面迭代加功能时,基本不用大改老代码,加新类、新节点就行,扩展性还不错。

四、Codex 帮我干活:真实体验比传统 AI 好用太多

这次作业我大概有 20% 左右的代码是用 Codex 生成的,剩下都是自己写逻辑、调结构,但 Codex 全程都在帮我提速。

它主要帮我干了这些事:

  • 快速生成重复代码:比如各种 Node 的模板、getter、构造方法
  • Debug 神器:报一个错,把代码贴过去,它能直接指出空指针、边界条件错在哪
  • 帮我造 hack 数据点、测试用例,覆盖各种边界情况
  • CheckStyle 一键修正:格式不对直接帮我改好,省了大量时间

真实感受:Codex 这种代码智能体,比豆包这种好用多了,它能跟着你一起写、一起调、一起测。
同样的工作量,以前要写半天,现在有它辅助快很多,尤其是机械性工作直接解放双手。

五、对这门课第一单元的一点小建议

从一个初体验复杂项目构建的学生的角度,我对我们的课程有两个小建议:

  1. 第一次作业最好给一个参考代码框架
    第一次接触递归下降、表达式结构,很多人完全不知道从哪下手。如果能给一个基础的类结构、Parser 骨架、Expr 的核心方法,大家能少走非常多弯路,也能更早进入正确的面向对象设计思路。

  2. 提前说清楚三次迭代的兼容方向
    三次需求是一步步加的,如果第一次就能大概知道后面要加变量、求导、递推,我们在设计架构时会更有远见,少一些后期推翻重构的痛苦。

六、做完这三次作业,我真正学到了什么

  • 终于搞懂递归下降解析器到底怎么写,不再害怕表达式解析。
  • 深刻理解什么叫高内聚、低耦合,不是背概念,是真的在代码里用到。
  • 学会用面向对象的思路做迭代开发,而不是一把梭写完。
  • 体验了 AI 辅助开发的完整流程:生成→Debug→测试→规范,效率提升非常明显。

这三周虽然经常debug到深夜,但确实是我收获最大、成长最扎实的一次作业。从一个只会写简单逻辑的人,到能独立完成一整个解析引擎,进步肉眼可见

...全文
34 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

302

社区成员

发帖
与我相关
我的任务
社区描述
2026年北航面向对象设计与构造
java 高校
社区管理员
  • 孙琦航
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧