经历 看似很 痛苦的三周,求导作业终于完成啦!
三周作业难度逐渐递进,每周重构一次,自然很是快乐。下面分析分析这三周的得与失。(请自行忽略背景)
一、作业分析
1、homework1
第一次作业很简单,求简单幂函数的导数。我就全程面向过程,从开始的读取表达式,然后正则表达式进行分割得到每一个项,然后进行直接进行求导,求导之后存入item类的容器中。得到求导之后的各个项之后进行合并同类项,输出。
整个过程思路很清晰,实现起来也很简单。
下面是代码的复杂度和UML分析:
-
类的UML分析
-
复杂度分析
2、homework2
第二次作业增加了对sin(x)与cos(x)的求导,以及乘积的求导,由于第一次并没有考虑以后的可扩展性,把项单单纯纯的认为是幂函数,所以在第二次作业中重构了因子类,新增加sin,cos与power三个类,并均实现Function接口,便于生成item对象。
在第二次作业中,每一个项都是由若干个因子乘积得到,可以对每一项进行合并得到每一项都有由系数,幂函数,三角函数乘积组成。这样就可以使用固定的求导公式进行求导。具体的解析步骤和方法是很第一次完全一样的,只是增加了几个正则表达式。
下面是UML分析和复杂度分析:
-
复杂度分析
3、homework3
第三次作业新增加了嵌套因子,显然又需要重构代码结构。前两次作业由于没有嵌套不需要考虑sin与cos里面的函数,而第三次的嵌套导致sin与cos里面的函数要是一个属于顶层的一个类的对象,那就需要使用接口来实现这个顶层类。
我设计了顶层Function接口,认为每一个正确的字符串都可以被认作为一个函数。多项式是多个函数相加,是一个函数,项是多个函数的乘积,也是一个函数,每一个因子也是一个函数。每一个函数都实现了Funtion的toString方法与求导方法。
在结构设计好了之后,我开始进行处理输入字符串。在同学启发下,我选择了递归分析做法来识别出非法字符串。通过对读入表达式进行一层一层的控制,一层一层的判断,来完全控制整个字符串的格式。
下面是UML与复杂度分析:
-
UML分析
第二UML省略了两个方法类。
二、BUG分析
2.1 自己程序的BUG
由于第一次作业比较简单,写出来的程序基本没有bug。第二次作业的bug,由于在课下没有认真进行测试,导致在强测出现了一个基础性bug,也是自己写代码时没有注意的一个小小bug:一个符号替换漏写了一个符号。bug的出现与程序整体结构关系很大,作为一个在求导过程中默认的基本限制,这个bug出现之后,在很多符号问题上出现了错误。
2.2 互测时发现别人的bug
我在第一次,第二次进入互测,每次都会看别人的代码,然后根据调试情况找到可能出现bug的地方,然后针对进行构造测试点。
三、应用对象创建模式
第一次,第二次作业的对象其实都不是很复杂,函数形式都很简单,并不是很需要使用对象创建模式。
在第三次作业中,我采用Generate的类,也就是工厂模式中的Factory,专一用来创建对象,不过我并没有对其进行分离来创建,是在一个类中使用方法来创建。如果要采用,只需把第三次作业的各种创建从Generate类中分离出即可。
四、心得体会
4.1 代码架构很重要
我在第三次作业开始之时,刚刚开始思考的不是如何进行求导,如何建立对象,而是如何对字符串进行解析,如何判断非法字符串,如何得到每一个项。在思考无果之后,我果断选择先将每一个函数的类完成,构造每一个函数类对应的数据并实现每一个类的求导。在实现之后,发现如果不考虑非法字符串,把未知当已知,可以进而完成Generate类。在生成每一个项对应的对象之后,我再去思考非法字符时,会很轻松。
4.2 心态很重要
首先说明一下,我第三次作业没有进入互测。。。
在第三次作业发布之后,我苦于不会建立表达式树,不会递归解析字符串,困顿了两天,无从下手。在第三天也就是周五的时候下定决心开始写架构,倒着写代码,最后实在无奈之下,采用DS里面的栈方法进行递归建立对象。说实话手法极其粗糙很暴力也很原始,实现起来也很麻烦,很绕,但是我还是坚持着一点点的写完,一点点的实现功能,在后来写完测试时,也能够基本实现需求。
在结束求导与建立对象之后,我把重点放到了判断非法字符串上。由于不是很理解表达式树的思想,我便采用递归分析的方法来判断。尽管不是很理解其真正的内涵,不过还是硬着头皮上了。在真正开始写时,我发现我陷入了一个巨大的泥潭:需要很多很多的判断(也就是if)。
当时写到心态爆炸,每次字符串的标识增加的时候,我都需要考虑是否越界,每次因子检查完毕之后,都要核实字符串标识的位置,每一次函数返回的位置都需要认真考虑返回什么,如何返回等等诸如此类问题让我头疼爆炸,写了很久很久。由于时间很紧迫,也没有多少时间足够犹豫,我就不得不摆好心态,一点点一点点的写,不慌不急,写到距离提交还有3个小时才通过基本的数据点sin(x) 、cos(x)这种简单的样例。我便直接提交中测,发现全是bug,RE WA等等各种情况,无奈之下一步步的递归一步步的调试,深层次递归一次看不懂,看两次,看三次。最后在第十次提交,距离中测截止时间18分钟时通过中测。
这样加急的作业,最后质量不怎么样也是很正常的,强测以很低的分飘过。在bug修复阶段时,修复了三个bug,其实也都是可以在实现时规避的,可惜当时心态着实不好。
回顾第三次作业的一周很艰难,最后两天基本一直写代码,写不动了睡觉,醒来继续写。最后通过时既有遗憾也有兴奋。
最后希望自己之后的作业没得bug,一遍AC