第一单元作业总结
本单元主要解决的是对表达式的求导问题,三次作业在难度上由小到大,在设计上由简到杂,层层深入。下面分别对三次作业的代码结构、出现的bug、以及互测手段进行分析。
第一次作业
代码结构
第一次作业涉及的表达式只包含幂函数,问题较为简单,且刚开始接触面向对象编程,对对象的结构和层次化设计不是很熟悉,导致第一次作业主要沿用了面向过程的思想,代码UML图如下:
由于采用了面向过程的思想,导致在表达式解析时采用的代码过于臃肿,使Main函数长度超过合理的60行长度,复杂度较高。第一次作业的类只设置了Term类,用于储存每一项的系数和指数,我想这也是唯一能和面向对象扯上关系的结构了。代码的复杂度如下:
bug分析
第一次作业没有出现bug,可能是我在程序设计结构上取了巧的缘故。但总体代码的可扩展性很低,这也是我第一次作业明显的弊端,为后面的作业设计留下了隐患。
互测手段
进入互测阶段的玩家大多在主要功能上 都不会出现差错,可能出现bug的地方主要是便捷条件以及特殊判断的地方。在作业一的互测中,我发现很多同学在连续两个符号的地方容易处理错误,因此在hack时主要涉及了空格和连续两个符号的复杂搭配。可能时我所处的房间正确率较高,最后只hack成功了一人。
第二次作业
代码结构
在第二次作业中我吸取了第一次作业的教训,在程序设计上努力使用了面向对象的思想,针对幂函数、常数、三角函数分别建立了类,并将这些类继承于同一个接口factor。在主类中设计了ExceptionCheck方法用于判断格式的正确性。在这次作业中我充分体会到了面向对象设计的结构的严密性和功能的强大性,运用面向对象避免我们的代码出现臃肿现象,增强代码的可读性和可维护性。代码UML图如下:
本次代码的明显缺陷是类方法的冗余,许多定义的get或set方法其实在程序中并没有使用。另外在格式的判断上,没有考虑代码的延展性,对于空格错误没有考虑处理,导致在第三次作业时话费了较长时间。这次代码的复杂度较第一次有了改善,代码复杂度如下:
bug分析
本次作业出现了一个bug,就是在幂函数指数的判断时,以为不超过10000等价于整数不能超过5位,忽略了整数前导零的情况,导致在格式判断上出错。这反映出了我在写完作业自测时测试覆盖性存在问题,考虑情况不周。
互测手段
本次作业的互测有些捉襟见肘,没有检测到同房间的一个bug,却被其他同学针对bug分析中的bug hack了14次。总结原因是在互测时数据点的设计上不具有针对性,而这也从侧面反映了我在自测时覆盖性不够的问题。
第三次作业
代码结构
第三次作业的功能比较复杂,增加了表达式的多级嵌套以及格式错误的判断。针对多级嵌套以及表达式的特点,我才用了树型结构来完成对表达式的存储和求导工作。在表达式的解析上,我回忆到了上学期所学数据结构课上用栈对中缀表达式的解析,将其修改后完成了对本次作业复杂表达式的解析。代码UML图如下:
本次代码结构上的主要缺陷是将大量工作放在了树类中完成,造成了类的长度有些冗余。在功能实现上,树形结构对于表达式的化简显现出了明显的短板,由于表达式加减乘除运算的先后顺序问题,对每个表达式的处理后都要加上括号,最后导致了一些不必要的括号出现,虽然在正确性上得到了保证,但性能上不如人意。代码的复杂度如下:
bug分析
本次作业主要出现了3个bug,第一个是在类如cos(- 1)的结构上错把-1当做了常数,而忽略了中间的空白符使它成为了表达式的情况。第二个是在格式错误的判断上,在匹配指数超过50的正则表达式上,我采用了类似\\d{3}的形式,并采用了只检测第一个不符合就退出的逻辑结构,这导致当出现x**050*x**1233的情况时判断出错。第三个bug是异常的抛出,在表达式解析时,我才用的策略是构造表达式树存在异常即输出WF,这导致有些格式错误只在求导时出现而没有被检测出。
纵观这三个bug,均是在一些细节上出现错误,这也警醒了我在以后的作业中,写完后要充分地自测后再提交。
互测手段
在本次互测中我才用了python程序随机生成表达式和手动构造表达式相结合的方法,取得了明显的成效,成功hack了10次,而自己被hack0次。
对比和心得
第一单元的作业结束了,回顾这三次作业,在互测时我看到了许多大佬成熟的面向对象程序设计体系,以及良好的代码风格,相对比我在面向对象的设计上存在许多的不足。主要有以下三点:
1、工厂模式的使用不够熟练。
2、程序高内聚低耦合的设计不够突出,存在大量方法存在于一个类中的情况。
3、逻辑严密性不够。
针对以上三点不足,我会抓住本周的空闲时间认真反思和阅读有关资料,争取在以后的作业中提升自己的程序设计水平。