26oo 第一单元总结

74066201_安妮 2026-04-01 23:54:26

2026面向对象第一单元总结

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

我对自己的程序进行了度量分析,包括每个类的属性个数、方法个数、每个方法的大致规模(代码行数)、控制分支数目(圈复杂度),以及类的总代码规模。

第三次作业主要类的度量数据(大致统计):

Node.java:属性约6个(type, value, left, right, third, fourth),方法较多(构造器 + getter/setter),总代码规模中等。方法大多简单,控制分支少。
Polynomial.java:属性包括terms映射、isExponential等,方法有fromNode、add、subtract、multiply、deriveX、deriveY等。数学运算方法规模较大,控制分支较多(尤其是处理指数和多项式)。
ExpressionExpander.java:这是核心类,方法数量最多(expand、derive、各种expandXXX、simplify等),总代码规模最大。许多方法有if/switch分支,圈复杂度较高。
Derivative.java:专注导数计算,方法较少,规模适中。
Main.java:入口类,方法不多,主要负责读取输入和调用扩展。
Lexer.java / Parser.java:解析器,方法以token处理为主,分支较多但逻辑清晰。
ExpressionPrinter.java:负责输出格式,方法专注打印不同节点。

结构:

hw2

img

hw3

img

类图:

img

comparison:

img

经典OO度量分析:

类的内聚整体较好,大部分类职责单一(例如Polynomial只管数学运算,ExpressionExpander负责表达式展开和化简)。耦合方面,ExpressionExpander与Node、Polynomial、Main等有较多依赖,但通过静态方法和明确接口,耦合控制在合理范围内。没有过度依赖某个类。
类设计考虑解释:

Node 是最基础的AST节点,设计成树结构,方便递归处理表达式。
Polynomial 专门处理多项式运算和高精度计算,让数学逻辑与表达式树分离。
ExpressionExpander 是大脑,负责展开、化简和导数,是整个程序最复杂的部分,我把它设计成静态方法为主,便于调用。
Derivative 和 GradientHandler 单独抽出来处理导数相关功能,避免ExpressionExpander过于庞大。
Lexer/Parser 负责输入解析,保持独立。

优点:结构清晰,分层明显(解析 → 展开 → 输出),容易理解每个部分做什么。
缺点:ExpressionExpander方法较多,有些分支逻辑复杂,未来如果功能增加可能需要进一步拆分。

二、架构设计体验

三次作业的迭代过程:

第一次作业:比较简单,没有自定义函数,项目结构也很简单。只有基本表达式处理。因为国际学校注册问题,我没有及时加入班级,没能完成第一次作业。
第二次作业:增加了自定义函数,打印逻辑也变了。我新建了 ExpressionExpander 类来处理表达式展开和新的打印规则,还新建了打印相关的类来专门管输出格式。这次作业让项目结构开始清晰起来。
第三次作业:需要处理导数,并且要按正确顺序打印。我新增了 Derivative 类专门负责导数的数学计算。后来因为要支持x和y两个变量,我又加了 GradientHandler 类来处理梯度相关部分。同时打印逻辑继续完善。

public class GradientHandler {
    public static Node computeGrad(Node expr) {
        Node expanded = ExpressionExpander.expand(expr);
        Node dx = ExpressionExpander.derivative(expanded, "x");
        Node dy = ExpressionExpander.derivative(expanded, "y");
        Node sum = new Node("+", dx, dy);
        return ExpressionExpander.simplify(sum);
    }
}

通过三次作业,我的架构逐步成型:从简单的主类 + 解析器,逐步拆分成 Node(数据) + Polynomial(数学) + ExpressionExpander(核心逻辑) + 专用处理类(Derivative、GradientHandler) 的结构。
重构体验:我做过几次重构。早期很多逻辑挤在一个类里,导致调试困难。后来把功能分开到不同类,代码变得更容易维护。重构后方法数量分布更均匀,单个方法复杂度有所降低。
新迭代情景的可扩展性:假如未来要支持更多运算(如三角函数、积分),我的设计比较容易扩展。只要在ExpressionExpander中新增对应处理方法,在Polynomial中扩展运算支持,其他类基本不用大改。Node树结构也很灵活,能容纳新节点类型。

三、程序中的Bug分析

我的Bug主要特点:

大部分Bug是格式和打印问题,比如括号缺失、相同项没有合并、输出顺序不对。一旦数学逻辑正确了,这些格式Bug就成了主要问题。

出现Bug的方法 vs 没出现Bug的方法:

有Bug的方法通常代码行数较多、控制分支(if-else、switch)多,圈复杂度高。没Bug的方法大多短小、职责单一,分支少。

如何避免:

如果我把方法保持独立、逻辑清晰,就不容易出Bug。早期我把太多逻辑塞进一个方法,导致调试花了很多时间。把方法拆小、保持独立,能大大减少后期调试。
反思:我的Bug很多是Java和OO基础不熟练造成的。后面通过反复重构,我能更快发现和避免类似问题。更好的设计(高内聚、低耦合)确实能减少Bug。
(由于我没参与互测,没能发现别人程序的Bug,这里就不详细写了。)

测试策略:

我主要用自己构造的测试用例,覆盖基本表达式、自定义函数、导数、梯度等。没有太多结合别人代码结构来设计用例,主要是根据自己的类设计来覆盖关键路径。

四、代码优化分析

我做了什么优化
我把很多逻辑从一个大类里拆分到小类里(比如把导数逻辑单独放进Derivative类)。保持方法独立、逻辑清晰。这样调试时更容易定位问题。
优化效果
优化后,代码的简洁性和正确性都提高了。数学逻辑正确后,格式问题也更容易解决。虽然花了很多时间,但最终正确性和整洁度都有明显提升。

五、大模型(AI)使用情况

三次作业AI使用率:

hw2hw3
正确性60%40%
性能优化70%35%

其他使用场景:

我用AI辅助理解作业要求、修复CheckStyle错误、调试Bug(包括自己的Bug)、翻译内容。也用AI帮我检查一些明显错误。

AI效果评价:

AI在找明显Bug和快速修复小问题时很有帮助,能节省时间。但当逻辑复杂时,AI经常给出错误建议,甚至破坏已经正确的代码。有时它会“修复”不存在的问题,反而浪费时间。总体来说,AI是辅助工具,过度依赖会适得其反。少用AI时,我自己实现的效率反而更高。

互测观察:

我没发现互测房间里同学大量使用AI生成代码的情况,所以这里不做具体评论。

六、心得体会

通过这个单元,我学到了很多东西。一开始我花了很多时间才理解作业要求(语言障碍也让我比较吃力)。第一次实现特别难,很多地方看不懂。
现在我明显进步了:更会重构代码,也学会了通过抽象来优化程序。把大逻辑拆成小模块,让代码更容易维护和扩展。虽然过程辛苦,但收获很大。

七、未来方向与课程建议

我觉得第一单元的课程可以改进的地方是:有些测试用例只显示通过/失败,不给出具体的输入输出或正确结果。这让我调试时很迷茫,不知道自己的输出哪里错了。如果能偶尔看到正确输出,或者有更多提示,会帮助我们更快找到问题,更好地学习。

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

302

社区成员

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

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