面向对象程序设计第一单元总结
面向对象程序设计第一单元总结
一、历次作业架构分析
1. 第一次作业
第一次作业由于不需要格式检查,我直接对输入的字符串进行处理:将表达式分成用+-号相连接的项,并进一步提取项的因子。我选择用Item类来表示项这个对象,由于每个项都可以简化成axb的形式,于是Item只需要存储参数a、b,并实现相应的求导和toString方法。表达式类用继承ArrayList的Poly表示,其中装入所有的Item。
类图如下:

度量分析:第一次作业代码架构较为散乱,分割处理字符串、生成Poly、求导等方法的调用都杂糅在了main方法中,有待改进

优化情况:
1. 首先进行了合并同类项,将x的幂次相同的项合并,具体通过重写Poly中的add方法
2. 其次对求完导的Poly进行排序,将正系数放在前面,即-a+b优化为b-a
2. 第二次作业
第二次作业在第一次的基础上加入了sin,cos以及表达式因子。由于加入嵌套后,对字符串的解析更加复杂,第二次作业我选择使用递归下降的方法(Factory类)来处理字符串并返回一个表达式类Poly,Poly中已经将字符串解析完毕。本次作业的项可以简写为 axbsin(x)ccos(x)d,于是可将Item扩充为[a,b,c,d]四元组,通过分析四元组来进行求导和输出。
类图如下:

度量分析:第二次作业将杂乱的处理方法归整好放入Factory以递归下降的形式使用,使得main方法更为简洁美观。美中不足的是Item的求导我采用分析四元组的方式来处理不同类型的结果,较为复杂,差点超过60行。

优化情况:
1. 同第一次作业,生成Poly时进行了合并同类项
2. 对最终toString方法做了一定的化简
3. 第三次作业
第三次作业加入了格式检查,并要求实现sin与cos函数的嵌套因子。在第二次作业的基础上,扩充了递归下降解析器(Factory类)的功能。重点重构在于Item类的结构以及其求导和toString方法。由于Item中可能存在多种不同的sin、cos函数,于是如下图所示的架构:
延续前次作业的Poly以ArrayList形式存储每个项Item;Item私有变量分别是常数项constant、幂函数幂次power、sin因子sinFactor和cos因子cosFactor;其中,sinFactor以HashMap的形式组织其内部的因子或表达式(key=Poly,value=该sin函数的幂次)。
在求导直接输出时,我通过Poly.diff()循环拼接其中Item.diff(),并完善项和因子的toString方法,最后整理输出

度量分析:第三次作业由于sinFactor与cosFactor更加复杂,在采用如上很奇怪的存储方式后,难以获取求完导后的Poly结构,于是求导方法我直接进行了字符串输出,较为繁琐。

优化分析:
1. 本次作业由于项求导较复杂,没有进一步进行优化,只延续了前几次作业生成Poly时的基础化简和拆分括号;但就强测性能分情况来看效果还不算差。
二、Bug分析
前两次作业强测互测均未出现bug;第三次作业在强测格式检查时出现了一个bug,原因是我在递归下降过程中缺少了一个格式检查的判断条件,导致(x这类格式没有判错,修改bug后较为完善。
互测时,主要以较容易出问题的边界数据(常数求导,0系数,0指数,0表达式因子等)测试,并借助室友写的评测机进行功能测试。
测试时发现较多同学容易在最终优化上出bug,例如删去0项、删去系数1等操作,利用replace时无法考虑到所有可能的情况就贸然替换。对于本单元作业的性能,我认为最主要还是看架构的好坏,优化的过程应该是细化分布在Parser、Store、Derive、Output各个部分的,而不是最终强行替换而来。
三、收获与感悟
本单元作业使我对java的编写能力和debug能力都有了较大的提升,具体如下:
1. 递归下降和语法树
前两次作业并没有加入格式检查,可以对输入的字符串暴力拆分,但第二次作业前我决定更改split大法,通过学习递归下降的原理和表达式树的生成方法,实现了一个Factory,接受输入字符串并按照我的数据架构返回好Poly类;
2. 面向对象的类分析
三次作业中对于不同类的需求不断增加,从Poly、Item、Factor,甚至sin与cos的嵌套,此时更需要良好的宏观布局,通过Java的继承、接口特性来组织。对此我有一些遗憾,第三次作业的架构并没有令我满意,Poly(List)--->Item--->Factor(Map)--->poly1的复杂嵌套并不美观也难以进一步优化。通过老师的讲述和同学的交流,进一步加深了对架构的理解。但是不同架构有着不同的优化难度,我们也难以评判其标准,毕竟最终要输出成字符串,不是吗?
3. 重构经历
第一次到第二次作业的过渡,难度提升并不算大,我选择将解析字符串的方法进行重构,以递归下降的角度剖析,再完善其他方法即可;
第二次到第三次由于增加了嵌套难度,我原本的架构无法存储,不得不进行重构。延续了第二次的解析器后,重写了Item的私有变量,加入了sin和cos因子,之前的求导方法也全部推倒,直接以字符串进行输出。
两次重构分别是解析和求导两个模块,虽然都适应题目要求作出改进,但自我感觉仍然没有做到满意,如果更深刻的思考架构,可能会组织出更好的代码。
4. 第一单元的作业有许多内容让我受益匪浅,但我认为在某些地方可能并没有深刻体现出面向对象的地方:
前两次作业表达式结构较简单,许多同学的精力都放在了处理字符串(split、正则表达式等操作)上,对于整个单元的全局思想不够(例如我,抱着侥幸心里认为没有格式检查和更难的嵌套),接着第三次作业突然出现的格式检查,才将递归下降的思路展现出来,但一周内让同学们清晰认识还是有一定的困难。精力又从本应该花时间的架构上转换到处理字符串,导致最终收获可能还没有pre2,pre3深刻。
5. 期待后续单元的作业,希望面向对象这门课能够让大家学习到高于码代码本身的一些珍贵的能力和思想。

浙公网安备 33010602011771号