309
社区成员
发帖
与我相关
我的任务
分享

从类的基础构成来看,我的程序可分为三类核心层级:抽象定义层(Factor, Expression, Term)、业务实现层(各类因子、项、表达式类)、工具支撑层(Polynomial, ExprParser, TermData)。抽象层作为程序的核心规范,只定义求值与求导的统一行为接口。实现层是抽象接口的具体落地,按类型拆分为各类因子、项与表达式,每个类只负责单一元素的处理,属性简洁、逻辑专一。支撑层承载程序最核心的复杂逻辑,负责表达式解析、多项式运算、递归函数处理等关键工作,是整个程序的运行基础,属性与逻辑都更为集中。
整体方法和代码规模分布不均,简单功能类代码精简、逻辑直白,核心支撑类代码量更大、内部逻辑更复杂,方法的控制分支与循环也更多,这也是程序整体复杂度的主要来源。

从OO度量结果来看,程序整体复杂度处于中等水平,与多项式解析、函数展开这类业务的特性相匹配。复杂度最高的三个类ExprParser, Polynomial和FuncFactor都承担了过于繁重的任务。
内聚性上,我的设计呈现明显分化。简单功能类的内聚性表现优秀,职责单一且逻辑独立,每个类只专注完成一件事。而核心工具类(ExprParser, Polynomial)的内聚性则偏弱,单个类承担了多项职责,既需要处理核心运算,还要兼顾字符串格式化、缓存管理、子表达式解析等工作,职责边界不够清晰。FuncFactor类从最初只负责自定义函数的功能经历迭代后加入了递归解析功能,复杂度瞬间上升。
耦合性方面,程序以规范的继承耦合为主,各功能因子类合理继承了抽象类的功能,各司其职,扩展新组件时不会破坏原有结构。而核心类的耦合度偏高,Polynomial多项式类作为计算基础被全程序依赖,ExprParser解析类虽然采用了递归下降逐步解析,但设计上直接关联所有实现类,新增表达式元素需要修改解析逻辑,耦合过于紧密,直接影响了程序的扩展灵活性。
我在设计时的核心思路,是用抽象接口统一行为,再按元素类型做细粒度拆分实现。抽象类Expression,Term, Factor定义了统一的行为接口,确保所有业务类都能以一致的方式完成求值和求导,这一设计提供了新计算功能较为良好的扩展性。
各功能因子类继承了上述抽象类,让每个类只处理一种元素逻辑,降低了每个类的复杂度,调试时能快速定位问题,也符合单一职责的设计原则。Polynomial多项式类作为核心数据结构,用内部类管理单项式结构,迭代后加入缓存机制减少重复计算,将所有多项式运算封装在类内部,对外只提供标准调用接口。ExprParser解析类我采用了集中式设计,把词法分析、语法解析、函数定义读取等逻辑整合在一起。最初的设计是ParseExpression -> ParseTerm -> ParseFactor的递归下降解析,但是后续功能的加入逐渐导致类的体量过大、逻辑过于集中,现在反思应该剥离各功能模块解析,独立处理。
反思本单元程序的设计,有一些不错的方面。基于抽象的层次设计让程序结构清晰,扩展新的表达式元素成本很低。按元素类型拆分实现类,让每个组件职责明确,代码可读性与可维护性更好。缓存机制的加入,有效优化了重复解析与递归计算的性能。
但设计中的问题也十分明显。两个核心类的复杂度失控,方法分支过多,长期维护与修改容易引入错误。核心类与其他组件的耦合过紧,扩展时经常需要修改原有代码。部分类的职责划分不够清晰,承担了过多功能,进一步拉高了类的复杂度,也让后续优化变得更困难。
整体而言,我的程序在结构分层与职责拆分上做到了基础规范,但在复杂度控制与耦合优化上还有明显欠缺,后续可以通过拆分核心类、优化接口设计等方式,让整体架构更简洁、更易维护。
第一次作业:完成了最基础的多项式表达式解析与计算,搭建了Expression -> Term -> Factor三层核心结构,通过HashMap综合多项式,实现了常量、变量、加减乘和幂运算的基础功能。
第二次作业:新增了指数函数,选择因子和抽象函数的支持,直接基于已有的因子抽象层扩展了对应的实现类,同时调整了解析器适配新的语法规则。整个过程没有进行大规模重构,依托初次作业的分层结构顺利完成了功能扩展。
第三次作业:实现表达式求导与递推函数功能,重构了顶层抽象接口,为所有组件统一添加了求导方法derive。重构了多项式类的内部数据结构,新增了递归函数专用的缓存与展开逻辑,拆分了原本集中在解析器中的复杂处理逻辑,还专门设计了递归函数因子类,将递归展开、参数替换、缓存管理的逻辑完全封装在独立类中。
第三次作业的重构显著让我感受到了上文提到的耦合程度带来的问题,简单的因子扩展较为简单,但是在输入解析和多项式计算两个地方还是产生了大量的改动,修改非常复杂与不便。之后的架构设计要更加注意功能的分离解耦,方便拓展。
根据往届作业,设想支持三角函数的解析与计算处理。
类实现仍然不难,需要新建正弦、余弦因子类,分别实现求值和求导方法。词法解析和计算依然是难点,解析方面ExpParser要支持 's','c' 等的读取判定,括号处理可以复用exp处理的逻辑,计算方面需要修改Polynomial的处理,包括三角函数合并化简等内容,有一定复杂性和处理难度。
bug修复阶段我一共被查出了4个bug。第二次作业被查出了多正负号的解析问题,和一次exp指数函数计算问题;第三次作业被查出了函数嵌套TLE问题和嵌套函数中选择式的解析问题。
综合分析来看,问题主要都集中在复杂度最高的ExprParser和Polynomial类,也就是输入解析和计算功能,以及迭代后承担更多任务更为复杂的FuncFactor类(即复杂度最高的三类)。我认为出现这些问题的原因就是在于这些耦合度过高的类在扩展时每次都要专门为了新的功能重新设计方案,与之前已经实现的功能交叉在一起,就会出现意想不到的bug。因此最好的解决方案就是在之后的作业中注意分离功能,降低复杂性和耦合度。
我在hack的过程中采用了两种方式,一种是根据易错点自行设计样例,一种是分析特定代码针对性地生成对抗样例。前者就是比较传统的方式,构造一些关于符号、括号、计算、复合、嵌套等方面的易错点,尤其是从我自己出bug的问题中汲取经验,设计一些针对性样例,也可以和其他同学交流获取一些构造方向上的思路;不过显而易见这种方法命中率和效率奇低,而且我构造的样例并没有特别测试极限,看到别人hack我的样例后我确实觉得大受启发。第二种方法就是用AI分析其他同学的代码来找出可能的问题点,不过这种方法对于同样是AI生成的代码分析效果就不太理想了。
最初我的代码只进行了正项提前优化,没有太多精力进行更复杂的优化,后两次作业的性能分确实也一般。
第三次作业TLE后,我对整个程序的输出和计算过程进行了一些优化,主要包括给递归函数展开、指数内表达式、函数实例等加入缓存来避免同一表达式被反复展开与解析,通过前缀积和后缀积的方式优化乘积求导。优化后确实有效降低了程序运行时间,能够应对多层嵌套函数。
最后,研讨课上学习到了同学的更多优化方式,提公因式和动态dp,震撼之余也学到了优化的新思路。
在一周时间有限的情况下,使用AI辅助基本上是不可避免的。有别于上个学期OOpre的循序渐进,这个学期这个单元的OO每次作业都是不小的挑战。总体上,三层递归下降架构是我基于练习自行设计的,具体的实现细节以及后面越来越多的功能添加都是AI辅助我完成的,尤其是功能过多导致耦合性强后,为了防止修改出现问题,后面的修改都有AI的帮助。debug自不必说,如此复杂的系统AI来找出问题确实大大提高了效率。
当然AI的使用也不是完美的,我在使用中也积累了很多经验。AI自行发现bug的能力还是不太令人满意,效果最好的方式还是要提供错误样例,才能较好地解决问题,不过这就反过来需要我自己有bug分析发现能力。在模型的选取上,前期我主要用deepseek进行工作,在经过多次反馈后还能有不错的结果;第三次作业改用Copilot的GPT-Codex后debug效率有显著提升,差距确实存在。
我总结下来互测房使用AI最大的特征可能是AI针对性错误样例分析不出来,以及大段注释。单纯从代码风来看,由于IDEA或者VScode的自动补全功能,以及Checkstyle规定的代码风格要求,实际上就看不太出来是否人工操作的了。所以反过来互测房成功率最高的方法成了人工构想的样例(可以是AI生成,但方向是自己想的或者交流的,比如第三次作业中的多层嵌套TLE样例)。
通过本单元的 OO 实践,我感受到了类的设计架构是保障程序结构清晰、功能可扩展的关键,合理的分层与抽象能让新增功能的实现更简洁高效。经过迭代与bug后我也认识到,核心模块耦合过高、类的职责边界模糊,会直接导致程序维护困难,出现问题,大幅降低迭代与扩展的效率。往后的单元练习中我会更注重类的单一职责落实与模块解耦,让架构在保持清晰分层的基础上,拥有更稳定、更灵活的扩展能力。
另外本次作业也有力地锻炼提升了我的AI编程水平,包括提示词,debug,样例测试等;在提升了效率的同时我也在思考,如何学会与AI工具共同完成任务,是现在必须要思考的问题。
首先想说的是研讨课,的的确确学到了其他大佬的思路构想,像是同学们分享的优秀架构(第一次研讨课讨论exp直接把e作为底数存储),优化方法(第二次研讨课讨论第三次作业分享的dp和提公因式)等等,都让我在自己的程序之外开拓了更多想法。
然后说说作业设计,我个人感觉一周之内完成一次完成的迭代设计,现在的难度和工作量实在是有点吃力,前几届纯手搓代码的工作就更难以想象了,希望课程组再评估一下难度递进的程度,让课程学习更有效,不成为每周特别大的负担。
互测部分确实拓展了思路,也让我更多反思了自己的架构程序,这点上我觉得非常认可。不过现在互测的流程实在有点麻烦,需要一两天里不停地想起来又该提交互测了,带来的精神压力有点大。