面向对象第一单元作业总结(作业集 1–3)
一、前言
本阶段的三次作业构成了课程第一单元的完整训练闭环,其核心目标在于引导学生在真实编码场景中建立面向对象的设计思维,并通过迭代演化的方式体会软件系统在需求变化下的演化规律。三次作业围绕“表达式求导”这一主线展开,从最初的一元多项式逐步扩展至支持嵌套、递归与多因子混合的复杂表达式系统。
在题量方面,三次作业均为单题形式,表面上任务规模有限,但对设计质量的要求却逐次提高。第一次作业侧重于基本语法与字符串处理能力;第二次作业引入了三角函数与多因子组合,复杂度显著提升;第三次作业则要求学生构建完整的表达式模型,并基于递归结构完成求导运算。整体难度曲线陡峭,尤其在第三次作业中,抽象能力不足的学生往往难以在短时间内完成稳定实现。
从教学视角来看,这一阶段的作业不仅是编程训练,更是一次关于“如何从过程式思维转向对象式思维”的认知重构。对我而言,这三次作业既是一次技术挑战,也是一次自我检视与工程素养的初步形成过程。
二、设计与分析
2.1 分析方法说明
在本次总结中,我主要采用以下方式进行设计分析:
使用 SourceMonitor 对代码规模、方法复杂度及结构分布进行量化分析;
借助 PowerDesigner / IDEA UML 生成类图,观察系统结构演化;
结合运行日志与调试过程,评估设计决策的合理性与代价。
需要特别说明的是,本文严格遵循作业要求,不粘贴任何源码,所有分析均基于结构、数据与行为展开。
2.2 第一次作业设计分析
第一次作业的目标是实现一元多项式的求导功能。输入为一行格式规范的多项式字符串,输出为其对应的导数表达式。
在初始设计阶段,我采用了较为直接的实现方式:将整个表达式拆解为若干单项式,并使用 HashMap<Integer, BigInteger>存储每一项的系数与指数。解析过程依赖正则表达式完成,求导逻辑则直接依据数学公式实现。
类结构设计较为简单,主要包括:
Main:程序入口;
Polynomial:封装多项式及其基本操作;
Term:表示单项式的数据结构。
此处插入类图截图
SourceMonitor 的分析结果显示,本次作业的整体复杂度较低,方法规模普遍偏小,最大圈复杂度仅为 4。这种结构简单直观,适合需求单一的场景,但也暴露出明显的局限性:一旦引入新的因子类型,原有结构将面临较大规模的重构压力。
从设计角度看,这次作业更像是一个“面向过程的 Java 程序”,而非真正意义上的面向对象设计。它帮助我完成了从“能写出正确程序”到“开始思考结构合理性”的初步过渡。
2.3 第二次作业设计分析
第二次作业在第一次的基础上增加了三角函数因子,并要求支持幂函数与三角函数的混合运算。这一变化直接打破了原有的单一映射结构。
为应对新需求,我对设计进行了扩展:引入复合键 TermKey,同时维护 x、sin(x)与 cos(x)的指数信息;使用自定义对象替代单一整数键;并在合并项的过程中加入三角恒等式化简逻辑。
新增类包括:
TermKey:复合键类;
TrigFunc:三角函数抽象;
Simplifier:化简模块。
此处插入类图截图
SourceMonitor 数据显示,第二次作业的总代码量接近翻倍,方法复杂度显著上升,最大圈复杂度达到 8。这表明系统内部逻辑已经开始变得复杂,单一类的职责过重的问题逐渐显现。
在实践中,我发现化简逻辑与核心结构之间的耦合度过高,导致部分方法难以维护。尽管程序最终通过了绝大多数测试点,但从工程角度看,这种设计在长期演化中并不理想。
这次作业让我第一次意识到:功能的增加往往意味着设计责任的重新分配,如果不能及时调整结构,系统将迅速走向臃肿与脆弱。
2.4 第三次作业设计分析
第三次作业是本单元中变化幅度最大的一次,要求支持表达式嵌套、括号递归以及多层求导。面对这种高度动态的结构,之前基于“项—系数—指数”的思路已不再适用。
在这一阶段,我尝试构建一个更具通用性的表达式模型:
定义抽象类 Expr,统一表达所有表达式元素;
派生类包括 Constant、Power、Sin、Cos、Add、Mul;
使用表达式树表示输入结构;
各类自行实现 derivative()方法,通过递归完成整体求导。
此处插入类图截图
SourceMonitor 的分析结果表明,第三次作业在规模与复杂度上均达到新高:总代码量超过 900 行,方法总数超过 30 个,最大圈复杂度达到 11。这一数据反映出系统在表达能力增强的同时,其内部结构也变得更加复杂。
从设计效果来看,这种基于抽象与多态的结构在面对需求变化时表现出更强的适应性。例如,新增一种因子类型只需扩展一个新类,而无需修改已有逻辑。然而,这也带来了新的挑战:如何在保证结构清晰的前提下控制类数量与方法复杂度,仍是我尚未完全解决的问题。
总体而言,第三次作业是一次对面向对象思想的集中检验,也是我第一次在实际项目中体验到“设计决定上限”的含义。
三、踩坑心得
3.1 字符串解析中的边界问题
在第二次作业中,我曾使用较为简化的正则表达式进行字符串拆分。在常规测试下表现良好,但在某些包含连续符号或特殊空格组合的输入中,解析结果出现异常。该问题直到强测阶段才被暴露,导致部分测试点失分。
这一经历让我深刻认识到:字符串解析不是次要环节,而是系统稳定性的第一道防线。任何对输入的过度假设,都会在未来某个时刻付出代价。
3.2 化简逻辑的过度设计
第三次作业中,我花费大量精力实现多种三角恒等式自动化简策略。初衷是提升输出质量,但实际效果却适得其反:化简逻辑不仅未能显著提高得分,反而引入了多个边界错误,最终导致整体稳定性下降。
对比数据显示,在不开启复杂化简的情况下,程序通过率更高。这说明在工程实践中,正确性永远优于优化,尤其是在需求尚未完全稳定的阶段。
3.3 测试能力的明显短板
回顾整个阶段,大多数错误并非源于逻辑不可行,而是测试覆盖不足。尤其是在表达式嵌套场景下,手工构造测试用例的能力明显不足,缺乏对极端输入与边界条件的系统性思考。这一短板直接影响了最终成绩,也暴露出我在工程素养方面的薄弱环节。
四、改进建议
4.1 架构层面的改进
在未来的设计与实现中,应从一开始就明确各层的职责边界:
使用工厂模式统一对象创建过程;
将化简逻辑从核心结构中剥离,采用策略模式进行管理;
控制单类的职责范围,避免出现“上帝类”。
4.2 测试层面的改进
测试不应被视为编码结束后的附属工作,而应贯穿整个开发过程:
建立系统化的测试用例库;
使用脚本语言编写自动化对拍工具;
针对每次需求变更,补充对应的回归测试。
4.3 工程习惯的改进
在代码层面,应更加注重可读性与可维护性:
为每个类和方法编写清晰的文档注释;
严格控制单个方法的规模与复杂度;
在设计阶段预留扩展空间,而非临时修补。
五、总结
通过本阶段三次作业的训练,我在多个层面获得了实质性提升。首先,我对面向对象的基本思想有了更为具体的理解,不再将其视为抽象概念,而是能够在设计中加以运用。其次,我初步建立起工程化思维,开始关注结构、扩展性与长期维护成本,而不仅仅是短期功能实现。最后,我也更加清楚地认识到自身在测试能力与系统设计经验方面的不足。
在后续学习中,我计划从以下几个方面继续努力:
系统学习常用设计模式,并尝试在实际项目中加以应用;
提升自动化测试能力,形成稳定的工程质量保障体系;
在编码之外,更多地进行设计层面的思考与复盘。
从课程角度来看,这一阶段的作业安排具有明确的教学意图与良好的训练效果。建议在后续教学中,适当增加设计案例的讲解比重,帮助学生更快建立正确的设计直觉。同时,若能引入代码评审或互评环节,也将有助于学生从他人作品中学习优秀实践。
总体而言,这三次作业不仅是一次技术训练,更是一次认知升级。通过对问题的反复拆解、设计与重构,我更加深刻地理解了“软件设计是一门平衡的艺术”。这种理解,将在未来的学习与工程实践中持续发挥作用。
浙公网安备 33010602011771号