面向对象程序设计第一单元博客

左茂成-24371203 2026-04-01 22:36:40

面向对象程序设计第一单元博客


一、基于度量的程序结构分析

最终提交版本共 21 个 .java 文件,分布在 4 个包中:expr(AST 节点层)、parser(解析层)、evaluate(求值层)和默认包(入口)。以下数据为 MetricsReloaded 工具的实际度量结果。

evaluate 包

类名属性数方法数WMCOCavgOCmax
ExprValue125833.1912
TermKey49131.443
EvalVisitor314231.644
FunctionTable(本体)2671.171
FunctionTable.FuncDef(内部类)2331.001
FunctionTable.RecursiveFuncDef(内部类)3441.001

parser 包

类名属性数方法数WMCOCavgOCmax
Parser223542.3511
Input0273.504
Preprocessor0122.002

expr 包(AST 节点,各类结构类似)

类/接口属性数方法数WMCOCavgOCmax
Expr(接口)01
ExprVisitor<T>(接口)011
NumExpr / VarExpr / NegExpr1331.001
AddExpr / SubExpr / MulExpr / DerivExpr / PowExpr / ExpExpr2441.001
ChoiceExpr4661.001
FuncCallExpr3+2常量661.001

默认包

类名属性数方法数WMCOCavgOCmax
MainClass0111.001

各包圈复杂度汇总

v(G) 平均v(G) 总计
evaluate2.30140
expr1.0045
parser2.9276
全项目1.97262

总体来看,通过合理的包划分和职责分离,各类内聚程度良好。expr 包中所有类的 OCavg 均为 1.00,是全项目内聚性最好的包。


二、架构设计体验

2.1 三次作业的迭代架构演进

HW1:单遍解析 + 直接求值

Input ──► Preprocessor ──► ExtendedParser ──► ExprValue ──► 输出
                                 ↑
                              (解析与求值混合在一个类中)

初始架构完全没有 AST 中间层,ExtendedParser 在解析字符的同时直接构建多项式表示 ExprValue,函数体以字符串形式存储,调用时重新解析。

  • 缺点:基本上什么缺点都有了哈哈。解析和求值高度耦合,无法对表达式结构做任何变换(求导等);TermKey 只有 xexp 一个字段,无法支持多变量,难扩展

HW2:重构,引入AST + Visitor

Input ──► Preprocessor ──► Parser ──► AST(Expr) ──► EvalVisitor ──► ExprValue ──► 输出
                             纯语法解析      ↑              求值访问者
                                          Visitor接口
                                      (未来可扩展为 DiffVisitorPrintVisitor 等)

核心变化:

  • 引入 AST 中间层Parser 不做任何计算
  • 引入 Visitor 模式EvalVisitor 遍历 AST 产生ExprValue,两者解耦

HW3:扩展双变量 + 求导 + 递推函数

得益于第二次作业的重构,HW3 在 HW2 架构基础上直接进行增量开发

2.2 重构体验

HW2 的这次重构几乎是完全重写,问题太多,不如重新设计来得清晰。

重构最大的收益是 HW3 扩展时的开销极低:新增双变量只改了 TermKey 和 ExprValue 中的几个方法;新增求导只加了一个 AST 节点和一个求值方法;新增递推函数只扩展了 FunctionTable 和 EvalVisitor。

三、程序 Bug 分析

Bug :ChoiceExpr 中死分支的忽略

EvalVisitor.visitChoice 通过 a.subtract(b).isZero() 判断两个 ExprValue 是否相等。其中的死分支不应当进行提前解析,否则会造成超时等性能问题。


四、互测 Bug 发现策略

在互测阶段,主要采用边界值 + 针对性构造的组合策略:

边界值测试

包括但不限于

  • 指数 0 和最大值 8:x^0(应输出1)、exp((x))^0(应输出1)
  • 递推函数最大索引 5:f{5}(x) 需要展开 4 次递推
  • 0^0=1 的语义:x^0*y^0 应输出 1
  • 空表达式/单项:1, -x

根据代码针对性构造用例

阅读被测程序代码,针对性设计用例


五、优化分析

基本没有优化,主要想保证代码功能的正确性。


六、大模型使用情况

6.1 三次作业中的 AI 使用率

作业代码 AI 占比说明
HW1~30%自己设计核心逻辑和框架,AI 辅助
HW2~40%AI 参与了 Visitor 模式的骨架搭建
HW3~10%AI 参与了求导规则实现和递推展开逻辑的整理

6.2 代码之外的 AI 使用

  1. 架构设计规划:在每次迭代前,使用 AI 进行架构方案讨论。AI 能快速给出 Visitor 模式、AST 层的设计建议,质量较高,但对功能的一些复杂的特定约束不了解,需要自己核对指导书。

  2. 博客撰写:AI 参与了本篇博客第一部分的数据分析和格式整理,以及部分内容草稿的编写。AI 生成的内容结构合理,但是具体内容必须亲自核实和修改。

  3. 互测 bug 寻找:向 AI 描述被测程序的代码结构,请 AI 推测可能的 bug 类型,无法精确定位所有 bug,主要依赖自己针对性的构造数据。

6.3 互测房间 AI 使用分析

观察互测房间中部分同学的代码风格,很多同学使用ai进行了适当的优化


七、心得体会

第一单元的三次作业围绕"表达式处理"这一主题逐步深入,让我对面向对象设计的核心思想有了切身体会。

最深的感受是"架构非常重要"。HW1时图省事写了一个巨大的重量级的解析器,到 HW2想扩展功能时发现根本无从下手,不得不进行一次几乎完全推倒的重构。这次重构花费了大量时间,但换来的是 HW3 扩展很舒服

另外,每次添加新功能前先写测试用例,能在开发过程中立刻发现逻辑错误,而不是等到提交后从通过率来反推问题。


八、未来方向

对于第一单元课程的改进建议:

希望第二次作业能够平衡一下开发难度,有实验课类似的形式提供一点具体思路。

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

302

社区成员

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

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