oo第一次总结

第一次作业

初次接触java编程,对于面向对象的理解非常浅薄,几乎是强行将整个程序拆分成不同的类,分为小括号内信息的单项式类,单个花括号内信息的多项式类,以及所有多项式组成的类,每个类得到一个符合标准的字符串输入,进行解析,创建下一级对象,进而完成对整个输入的解析。看似对不同的内容进行了封装,实则还是线性的单向的调用。属于“伪装”的比较好的c代码。

MainClass的主要作用是提供整个程序的入口,创建一个全部多项式的对象,调用他的方法开始计算,控制部分的输入格式。之所以这么做,是由于一直难以确定各个类的实际作用,无法很好的规划某个类到底应该做些什么,因此无法确定主函数应该交给哪个类负责,并且由于没有将正则匹配验证输入合法性的方法与整个计算过程分离,导致包含多个多项式的类如果包含主函数,则会显得繁杂不堪。

Bug分析

本次作业中,在互测阶段被发现了一个错误,原因在于对于指数前出现正号的情况没有考虑完全。笔者与周三上午发现并修正了该Bug,但修改后没有再次完成提交,实在是追悔莫及。

在测试的过程中没有发现对方的任何错误。采取的策略是依照bug树逐条检查,并用python生成大规模数据进行压力测试。

类图:

度量分析:

第二次作业

第二次作业中由于采用了傻瓜式的调度策略,因此在设计运行方法时并未遇到大量障碍。电梯类与楼层类主要负责发出请求,即创建请求对象,并加入请求队列。电梯类还有额外有一个模拟移动的方法。本次作业的主要难点在于如何清除通知请求时,有两种可行的思路,一种是记录下每个按钮按下的状态,分别置于楼层类与电梯类中,取出每个请求后在执行前进行验证;另一种是执行完一个请求后,在请求队列中搜索所有的同质请求并从队列中删除。在本次作业中采用了后者,但是前者可以明显降低时间复杂度,并且更好的归纳电梯类与楼层类。这个程序的圈复杂度主要来源是main函数,同样是没有抽出正则匹配的方法,因此显得较为繁杂。

Bug分析

本次作业中,在互测阶段被报出一个超过100条指令并未执行前100条的错误。其原因在于对于助教以及指导书中100条边界条件理解错误。我的处理方法为超过100条后提示错误并终止程序运行,并不执行前100条指令。可以看出对于指导书的反复阅读和打磨也是非常必要的。

类图

度量分析

第三次作业

第三次作业中主要的改动在于新的控制器类继承了原来的控制器,并重载了scheduler方法用于满足捎带请求的处理逻辑。在实现中,对于主请求和捎带请求的调度方法有两种设计思路,一是取出一个请求作为主请求,立刻在请求队列中寻找符合条件并离出发楼层最近的捎带请求,若捎带请求目的地在主请求目的地之前,立刻执行该捎带请求并维护主请求,否则执行主请求,并将该原捎带请求升级为主请求;二是取出一个指令后,取出所有符合要求的捎带请求,放入一个全新的队列,优先执行捎带队列中的请求,同时维护主请求,再次寻找捎带请求,维护捎带队列,直到捎带队列为空。在本次实现中,采用了第二种方法。显然,第二种方法的复杂度远高于第一种方法,主要问题在于维护捎带队列的难度非常大,要保证按照距出发楼层距离最近的顺序进行排序,并且同楼层执行多条指令时还需要考虑输入顺序,以及与主请求间的输入顺序。导致请求队列中反复遍历该数组,并且scheduler中的控制方法非常繁杂,捎带请求要不断地与主请求进行多级比对,获得正确的输出顺序,代码长度接近150行,已经重回了面向过程的编程。而第一种方法,省去了大量的维护捎带队列的时间,并且在构造该队列时已经保证按输入顺序排序,也不必过分考虑输出顺序与输入顺序的关系,因此远远优于第二种方法。

本次作业中,圈复杂度的主要贡献者是检索捎带请求的函数,由于涉及上的错误,导致处理流程非常漫长,对外部参数有非常高的依赖性,一共需要5个参数才能开始检测,每次检测要遍历数组。判断是否为捎带请求的方法更为致命,共计6个参数,封装性被完全破坏掉了并且,依然沿用了return true这种典型的c代码风格。

Bug分析

这次设计失误导致我自身debug的过程非常漫长,周一到周二大约花费了20个小时来处理各种逻辑错误,比如优先执行主请求时没有考虑同时执行多个捎带请求的情况等等,每一次比对都要耗费大量的时间,由于从逻辑上静查代码已经不太可能,主要的debug手段是依靠脚本生成的大量数据覆盖所有的可能性。

在互测中双方均未发现bug。

类图

度量分析

心得和体会

三次作业之后,痛定思痛,最大的收获是不要急于编码,“谋定位后动”真的是非常重要。在相对比较复杂的第二次和第三次作业之中,均在开始动手实现代码后,发现了更为高效的设计思路,都可以减少实现难度以及debug的难度。这一点在第三次作业中尤为突出,为了梳理逻辑我几乎在每一行代码后面都加入了注释,说明这一行代码的目的,即便如此,重复的变量调用以及判断使得更改代码非常复杂,可能在解决某个错误时又反复触发另一个错误,导致debug的时间非常漫长。

第二点是,提高类的价值,也就是对类进行更好的抽象,其实也可以归类到第一条之中,但是有些许不同。这种设计不再是针对方法上的设计,而是在实现的过程中,每个方法的位置的问题。比如监测输入合法性的方法,与主函数;调度器的方法与控制电梯移动的方法。究竟每个类到底应该做些什么,究竟可不可以依赖自身的数据或者少量的外部数据就能完成工作。若是依赖太多的外部数据就导致这个类更加类似于一个函数,一个数据结构,而不是真正意义上的类,整体的代码风格更偏向C语言。

总结

作为一个java小白,从零开始的java编程之路还是十分惊险刺激的,时间紧迫是每次java作业共有的属性。周一不熬夜,周二就得通宵,没有充足的时间就没有健壮的代码。短短三周,只能说初识了java的面目,后面还有万水千山等待我去发掘与探索,希望能与各位同学一道,共攀此峰。

posted @ 2018-04-03 23:59  t68i663  阅读(129)  评论(0编辑  收藏  举报