2026 OO U1 博客

吉俊西-24373190 2026-03-31 17:16:53

U1博客

程序结构

规模量化

总规模

文件类总行数属性数方法数
MainClasssrc/MainClass.java7201
Parsersrc/Parser.java364317
Lexersrc/Lexer.java5035
Fxsrc/Fx.java1412
Fnxsrc/Fnx.java5882
Polynomialsrc/expr/Polynomial.java418117
Keysrc/expr/Key.java5236

Polynomial类

方法规模(行)控制分支数备注
Polynomial()20构造
Polynomial(Polynomial)80构造
equals182
hashCode30
add(Key,BigInteger)91
add(Polynomial)61for×1
multi252for×2
div82if×1,for×1
power162if×1,for×1
subst392for×2
negate61for×1
derive403for×1,if/else if×2
isExprFactor301if/else×1
toString336if×2,for×2,loop内 if×2
toString_subF579
toString_subF_opt1476
toString_subF_opt2373

Parser类

方法规模(行)控制分支数备注
Parser(Lexer)30构造
Parser(Lexer,Fx)40构造
Parser(Lexer,Fnx)40构造
Parser(Lexer,Fx,Fnx)50构造
parseFnx425for×2,while×1,if×2
parseExpr275if/else if×3,if×1,do-while×1
parseTerm111while×1
parseFactorWithSign122if×2
parseFactor256if/else if 链×6
parseExprFactor223if×3
parseVarFactor243if×2 + if/else×1
parseExpFactor212if×2
parseCondFactor261if/else×1
skipCondBranch186while×1 + if/else if 结构×5
parseFuncFactor282if/else if×2
parseDeriveFactor302if/else if×2
parseNumFactor182if×2

综上来看,由于所有的数据都在Polynomial类中存储,所以Polynomial类中的方法不可避免地很多。

一些优化函数的圈复杂度也不低。

OO度量

img


可以观察到,ParserPolynomial类的RFCWMC都很高,他们在这个题目里担任的职责较为单一,还是可以接受的。

类图

img

可以看到,虽然Parser是递归下降的写法,但是对应的ExprTermFactor都统一为Polynomial类了。

这样做:

  • 优点是不用烦恼类型转化了,所有的功能全都从单项式通项的角度出发,代码量也许更少;
  • 缺点是可扩展性极差,只针对了作业,并不体现层次化。

架构设计体验

  • 第一次作业根据递归下降设计了Expr,Term,Factor类,第二次作业统一成了Polynomial类,之后写得还算顺风顺水)毕竟情景比较简单,直接无脑处理了
  • 假设要加一个三角函数因子,或者是对数函数,或者是增加自变量种类等等,我都必须重写我的Polynomial类,而且效果很差)可以看出这种架构没有可扩展性而言。

分析自己程序的bug

第二次作业

  • 选择式的分支跳过出错,问题出在Parser类的ParseCondFactor方法。出现这样的问题是因为没有充分测试。
  • toString方法的优化出错。出现这样的问题是优化写的控制语句比较复杂,而且没有经过充分测试。

    第三次作业

  • 递推函数的解析出错,问题出在Parser类的ParseFnx方法。出现这样的问题是因为没有经过充分测试。
  • 核心类Polynomial初始化时创建了不必要的对象,导致强测TLE。出现这样的问题是因为知识不充分,不了解创建对象的开销。没有设计压力测试。

对于优化出错,对应代码的圈复杂度高,测试需要覆盖所有的情况,而且要在必要的时候引入子方法来减少方法的复杂度。

我在这两次作业犯了很多未充分测试的低级错误,以后要在易错的地方多搓数据点。

所谓测试能力和代码能力是息息相关的,测试应该被重视。

分析发现别人程序bug所采用的策略

测试策略包括构造指导书提及的边界情况,例如exp(0)x指数超过int64的情况。还有在规定cost范围内构造的嵌套样例。

第二次作业有exp双层括号exp嵌套的问题,成功hack。

没有注意分析别人程序的架构。下次注意。

分析自己做的优化

做的优化有:

  • 正数项提前
  • exp内若是常数因子*幂函数因子常数因子*指数函数因子的形式,提出常数因子,去掉内层括号
  • exp提取公因式

我的优化思路是在对应的位置替换为一个子函数,这样保证了我可以选择是否优化,我认为还挺简洁的。不过这样写的子函数更像是一个补丁。。。没有涉及代码复用。

大模型相关使用

  • 第一次作业的框架是AI生成的;第二次作业手写重构了AI的框架;第三次作业是手写的。用了copilot的代码补全,对于重复性的工作和代码纠错很有帮助。性能优化是手写的。
  • 部分debug,博客作业中的量化架构部分用了AI
  • 大模型对于简单的、已经固定的任务完成得很好。用cursorclaude code等上下文很长的ai,写出来的代码自己没有把握。。。我还是oop小白,更倾向于提问获得思路,然后手动实现。
  • 第一次作业,下面的例子在Expr类中用了index成员变量保存幂函数的指数。个人认为这个index框架是AI写的。因为变量名和这个注释。
    // 第一次作业 开阳星
    // Expr类
    // ...
    if (this.index >= 2) {
        Poly forIndex = result.clonePoly();
        // ! index<=8, we needn't fastPower for now.
        for (int i = 1; i < this.index; i++) {
            result = result.mul(forIndex);
        }
    }
    // ...
    
    有些同学有AI补全的痕迹,但是没看出来大量生成代码。架构方面没有细看,以后互测还是要趁这个机会多多学习。

心得体会

按照助教给的思路,写下博客之后,发现我在以下几点做得非常不足:

  • 在设计阶段自行构造数据
  • 在互测阶段阅读借鉴他人架构,并构造数据攻击他人架构
  • OOP的设计模式的应用

虽然U1的题目内容并不复杂,但是设计的时候应该尽量体现OOP的设计思想,而不是写出能跑的代码就可以了)开闭原则,注入依赖,层次化设计等需要多磨练。另外构造数据测试的时候该构造也得构造,该学习别人架构的时候也得学习,不能摆烂。

未来方向

建议让表达式的单项式变得更复杂,逼迫同学们放弃设计一个类就一劳永逸的想法。。。

思考题

如何检查输入是否如何要求

在递归下降的结构里,严格按照写出的文法进行判断,{}中的内容用while循环,[]用if等等。如果不符合预期就抛出异常。

如何精确计算一个合法输入的cost

在递归下降的结构里一层一层回传cost,或者在递归下降的过程中建立语法树,遍历一遍

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

302

社区成员

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

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