2026 OO_Unit1 总结

肖鹏-24231219 2026-03-27 20:30:52

OO-Unit1-Summary

目录

基于度量分析程序结构

类图

img

├── Factor (接口,用于解析后建立AST)
│ ├── DeriveFactor
│ ├── ExpFactor
│ ├── FuncFactor
│ ├── NumFactor
│ ├── RecFuncFactor
│ ├── SelFactor
│ ├── Expr
│ ├── Term
│ └── VarFactor
以上均是各类因子的实现类,其中funcfactor特殊,对于自定义函数和递推函数,处理的方法在functionexpander工具类中
├── Mono
├── Poly
建立AST后,对每个因子都要转为poly类型,用于后续的计算,mono则是poly的基本组成单位,三次作业之后mono的标准格式为:num*x^index1*y^index2*exp(expr)
├── FunctionExpander
用于展开自定义函数和递推函数,将递推函数转换为普通函数
├── Lexer
├── Parser
├── MainClass

ClassOCavgOCMax(类的最大响应集)WMC(类的加权方法数)
DeriveFacto1.0012
ExpFactor1.5036
Expr1.25310
FuncFactor1.0013
FunctionExp3.251352
Lexer1.7537
MainClass4.0044
Mono2.411241
NumFactor1.0013
Parser4.271247
Poly4.831458
RecFuncFac1.0014
SelFactor1.0015
Term1.3338
VarFactor1.5036
Total256
Average2.565.0017.07
MethodCogC(认知复杂度)ev(G)(本质复杂度)iv(G)(设计复杂度)v(G)(圈复杂度)
DeriveFactor.DeriveFactor(Expr, char)0111
DeriveFactor.toPoly()0111
ExpFactor.ExpFactor(Factor, BigInteger)0111
ExpFactor.getExp()0111
ExpFactor.getIndex()0111
ExpFactor.toPoly()3244
Expr.Expr()0111
Expr.SetIndex(BigInteger)0111
Expr.addSign(String)0111
Expr.addTerm(Term)0111
Expr.getIndex()0111
Expr.getSigns()0111
Expr.getTerms()0111
Expr.toPoly()4133
FuncFactor.FuncFactor(Factor)0111
FuncFactor.getPara()0111
FuncFactor.toPoly()0111
FunctionExpander.copyPoly(Poly)0111
FunctionExpander.ensureRecursiveReady()2214
FunctionExpander.evalExprWithArg(Expr, Poly, Integer, Map<String, Poly>)4133
FunctionExpander.evalFactorWithArg(Factor, Poly, Integer, Map<String, Poly>)24111314
FunctionExpander.evalTermWithArg(Term, Poly, Integer, Map<String, Poly>)2133
FunctionExpander.expandRecursiveByOrder(int, Poly, Map<String, Poly>)5345
FunctionExpander.expandRecursiveWithArgument(String, Factor)0111
FunctionExpander.expandWithArgPoly(Poly)0111
FunctionExpander.expandWithArgument(Factor)1212
FunctionExpander.extractFunctionBody(String)1212
FunctionExpander.initFunction(String)1212
FunctionExpander.initRecursiveFunction(String[])128411
FunctionExpander.normalizeExpression(String)0111
FunctionExpander.parseExprFromString(String)0111
FunctionExpander.reset()0111
FunctionExpander.resolveOrder(String, Integer)7547
Lexer.Lexer(String)0111
Lexer.getNumber()2133
Lexer.next()3223
Lexer.peek()0111
MainClass.main(String[])4144
Mono.Mono(BigInteger, BigInteger, BigInteger, Poly)0111
Mono.add(Mono)0111
Mono.copyPoly(Poly)0111
Mono.derivative(char)10258
Mono.derive(char)1222
Mono.etoString()5333
Mono.getCoefficient()0111
Mono.getStr()0111
Mono.getXIndex()0111
Mono.getYIndex()0111
Mono.isSimilar(Mono)1133
Mono.mul(Mono)0111
Mono.setNegative()0111
Mono.sub(Mono)0111
Mono.toString()2141618
Mono.xtoString()3323
Mono.ytoString()3323
NumFactor.NumFactor(BigInteger)0111
NumFactor.getNum()0111
NumFactor.toPoly()0111
Parser.Parser(Lexer)0111
Parser.expectToken(String)1222
Parser.parseDeriveFactor()4334
Parser.parseExponent(Lexer)3133
Parser.parseExpr()1811213
Parser.parseFactor()2391415
Parser.parseRecFuncFactor()1122
Parser.parseSelFactor()2122
Parser.parseTerm()1122
Parser.skipToTopLevelColon()8546
Parser.skipToTopLevelRightBracket()5145
Poly.Poly()0111
Poly.add(Poly)1122
Poly.addFreshMono(Mono)0111
Poly.addMono(Mono, Boolean)13477
Poly.derive(char)4233
Poly.isEqual(Poly)2081015
Poly.isExpr()1261117
Poly.isZero()4424
Poly.mul(Poly)3133
Poly.pow(BigInteger)4133
Poly.sub(Poly)1122
Poly.toString()2261216
RecFuncFactor.RecFuncFactor(String, Factor)0111
RecFuncFactor.getOrderExpr()0111
RecFuncFactor.getPara()0111
RecFuncFactor.toPoly()0111
SelFactor.SelFactor(Factor, Factor, Factor)0111
SelFactor.getFactor1()0111
SelFactor.getFactor2()0111
SelFactor.getResultFactor()0111
SelFactor.toPoly()0111
Term.Term()0111
Term.addFactor(Factor)0111
Term.changeIsPositive()0111
Term.getFactors()0111
Term.isPositive()0111
Term.toPoly()2133
VarFactor.VarFactor(BigInteger, char)0111
VarFactor.getIndex()0111
VarFactor.getValue()0111
VarFactor.toPoly()2113
  • 分析问题:
    • 高复杂度类集中在核心流程:FunctionExpander、Parser、Poly、Mono 的 WMC/OCMax 明显高于均值,说明这些类承担过多职责,后续维护和扩展风险大
    • 解析与展开逻辑耦合偏重:FunctionExpander OCMax=13、WMC=52,且多个方法高认知复杂度,意味着函数解析/展开链路过长、分支过多,易引入边界错误
    • 语法解析路径复杂:Parser 的 parseExpr()/parseFactor() 复杂度显著,说明语法规则分支堆叠,缺少清晰分层或子解析器拆分
    • 表达式/多项式输出逻辑膨胀:Poly.toString() 和 Mono.toString() 复杂度突出,说明字符串拼装逻辑过于集中,潜在格式规则过多/分支过深

架构设计体验

hw1

  • 设计了基于接口的因子体系,方便后续扩展不同类型的因子
  • 对于varfactor,预留了value以便引入新变量
  • 设计了poly类,统一表达式的计算和化简,简化了后续的计算逻辑,mono基本单位格式为:num*x^index
  • poly类统一后输出,对poly和mono的tostring重写

hw2

  • 对于自定义函数,一开始直接在预处理时展开;对于选择式因子,最初更是将可能的两个结果因子均进行了解析。两者导致了互测的tle问题。重构后,建立了函数因子类和函数处理工具类,在建立ast过程中处理函数,不进行简单的字符串替换,而是将函数表达式的AST中的x部分替换为实参再转换为poly化简;选择表达式则在解析过程中判断结果,直接得到需要解析的结果因子部分
  • 引入expfactor,并更新mono为:num*x^index^exp(expr)
  • 修改mono和poly的计算方法

hw3

  • 新变量,对应修改计算方法
  • 求导因子,这里的实现由于架构的不同,没能够仿照上机练习例子的实现(对因子添加求导方法),而是在poly类、mono类中添加求导方法,将待求导的表达式转为poly再求导,返回一个poly对象,正符合了我的设计目标需要的返回对象
  • 递推函数,类似自定义函数,一个recfuncfactor作为AST树的节点,同时在函数处理工具类中添加递推函数的处理方法,具体得到递推函数的表达式,之后即可复用自定义函数的处理方法

新迭代

如果增添多个函数:由于函数因子中预留下函数名,并在函数处理工具类有函数名与函数体的键值对容器,这样只需要添加一个根据函数名获取函数体的方法即可得到单个函数的函数体,从而复用已有的处理路径

分析自己bug & 发现他人bug的策略

自己遇到的bug

  • 结果为0时输出空串:由于mono的tostring方法对于0返回空串,poly拼接时就可能得到空串输出,进行特判解决
  • 自定义函数和选择表达式处理方式不合理导致tle:重构了两者的处理方法
  • 对于选择表达式因子,跳过错误结果因子时,由于可能嵌套选择表达式因子,所以不能够用单一的字符':' '?'等来判断是否跳过,要对括号深度进行计数
  • 边循环边修改容器因子

发现他人bug的策略

  • 尝试自己和同学出现过的bug
  • 评测机压测
  • 让ai检查代码

优化

关于性能分的优化:

  • 在转为poly类时就同时在进行运算上的化简,合并同类项等
  • 输出时,mono类特殊处理了一些情况,如系数为正负一等
  • 输出时,在poly中将正项提到首项
    对于第二点,由于增添了很多不同分支的处理,导致方法的复杂度增加,不够简洁

大模型使用

  • 三次作业使用:
    • hw1: 无,仅参考了公众号和练习的架构
    • hw2: 写的过程中查询了ai如何正则表达式替换f(x);在bug修复时重构代码,增添了函数处理工具类,可能由于一开始架构的设计问题,导致了tle问题始终优化不了,所以将这个类重新全权交给ai,ai设计了一遍就通过了(。一个类使用了ai,大概10%
    • hw3: 由于hw2中函数处理工具类交给了ai, 所以hw3的递推函数处理,用到的工具类的方法也由ai设计了。依旧是在这个工具类中使用了ai。
  • 评测机搭建使用过ai。
  • 评测机效果一般,问题在于数据生成随机,不容易进行边界测试,这一部分可以靠人工提供边界条件让其设计
  • 代码生成效果非常好,因为我采用的是idea集成的,它可以阅读理解整个项目的架构,交互时我先是给出了详细的输入输出要求和题目内容便于他理解整个项目,然后是我的需求(简要来说是对函数体解析建立ast,将实参替换ast中x后化简;具体给出了这个工具类的属性,它的静态方法在其他类中的调用等等),生成之后要求进行一定的测试。agent生成的代码几乎都没有问题,出现一次bug是由于我的提示词不够清晰导致。缺点在于生成的代码有一定的黑盒性质,需要自己又去阅读理解

心得体会

Unit1的作业让我更加熟悉了递归下降的方法,如何将一个复杂的、嵌套的语法分解为各个部分,大大简化了解析。然后是统一成poly进行计算的方式也很巧妙,我一开始设计架构时在如何计算化简考虑了很久,参考了公众号才采用了这种统一计算的方式。

未来方向

我认为未来可以加上一些对于性能优化的提示,然后对于博客需要的度量值也可以提供一下可采用的工具

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

302

社区成员

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

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