zoukankan      html  css  js  c++  java
  • OO第一单元总结

    OO第一单元总结

    一、本人程序分析

    对于我的程序,我采用了UML图和DesigniteJava软件进行分析。

    homework1

    第一次作业整体比较简单,我用Term类来储存项,用Poly类来储存多项式,用Read类来进行读取。第一次作业整体结构也比较简单,

     这次作业中我的printTerm方法的圈复杂度太大了。这个方法主要是用来输出项。之所以这个方法复杂度比较高,是因为控制流设置得有些复杂了。因为希望减小输出长度得到更高的性能分,所以我在系数为+-1和指数为1的时候设置了特殊判断。

     

     这张图展示了所有方法的行数、圈复杂度和传入参数/总得来说,我这次的方法写的长度基本都控制在了30行以内,是比较好的地方。而圈复杂度只有Term.printTerm圈复杂度较高,是这次做的不好的地方,上面已经有了分析。

     

     homework2

    作业2我在结构上基本沿袭了第一次作业。这次作业我比较满意的是化简的算法。我使用了DFS的方法,并且对是否考虑贪心的思路进行了分析。不足之处在于,由于这次优先实现了功能,在添加化简的方法显得有些脱离于整体框架。

     这次的问题是都出现了“未使用的抽象”的问题。

     方法上出现了幻数和条件、语句过长的情况。幻数的出现主要是为了确当不同的化简情况。未来将用枚举变量来规避。语句过长和逻辑条件过于复杂需要在后续的设计中规避。

     

     这次的高内聚低耦合原则贯彻的不是特别好,Poly类和Read类都出现了LCOM大于0的情况。CC过大出现在了getlenth和printTerm两个方法中,这个原因与作业一出现的问题相同,都是为了更好的性能导致方法的逻辑有些复杂。

    homework3

    这次作业我重构了整个代码,用一个Parser类来处理输入,AddFac类用于管理表达式,MultFac用于管理项。

     这次出现了循环相关模块的问题。Cos与Sin本身在求导时就相互依存。后来考虑这一部分应该像作业二一样用一个统一的类来管理,再维护一个布尔变量进行区分,这样也不会导致后期修改时经常考虑到了sin而忽视cos的问题。还出现了缺失层次的问题。此外还出现了未开发封装的问题。固然,处理输出项和表达式时颇有共通之处,但后续也确实应当试图把共同的处理封装起来。

    出现幻数是为了处理WF,长表达式主要是因为使用了IDEA自动生成的equals方法, 同时也出现了圈复杂度过大的方法。tostring方法圈复杂度过大的原因与前两次作业相同。而parseExp和parseItem的圈复杂度过大,是因为要根据不同的输入来决定下一个项/因子是什么。或许可以采取更好的方案解决。

     


    这是我第一次使用专门的分析软件分析代码,感觉以后应该每次写完作业以后都进行分析,来看看能否在一些项目上有所改进。

    二、程序中出现的bug

    第一次作业中强测与互测均没有出现bug。

    第二次作业中互测出现的bug是判断WF时,我原本使用的方法是判断指数数字连续出现的次数,如果超过5位,则必定是WF,如果不是,再判断与10000比较大小。但这种分析方法忽略了前导0存在的情况。改正的方法是读出指数转化为BigInterge后再进行判断。得到的经验是处理需求时最好处理需求的本质,如果考虑需求的其他特征,就可能会出现问题。换言之,从形式逻辑的角度分析,不妨把每一个需求看作定义,那么分析需求本质的方法是得到准确外延的方法,可以将需求框定死,就不容易出错。而从其特征出发,则不一定能找到其准确的外延,如果外延过大,则会处理到不应该处理的部分,如果外延过小,则无法满足所有需求。

    第三次作业中出现的bug较多,但总结下来,问题无非是读入与输出的错误。读入方面,对指导书的分析不甚全面,因此忽略了空字符出现的情况。而后续没有发现这种错误,也是由于测试集并没有覆盖到空白字符的情况。输出方面,主要是忽略了在处理嵌套函数时,即使表达式因子中只有一个项,也应当加括号。最后也是因为试图探究化简的方法,反而忽视了正确性。最后bug一大堆,化简了两次也没写出比较好的化简方法sigh。

    总结两次作业中出现的bug,我认为主要是这几方面做的不够好:

    1.分析需求不到位:对题目中的要求,特别是格式的要求理解不到位。

    2.结构不够清晰,层次感不好。第三次作业中出现的bug都不是功能性错误,而是输出/输入错误,并集中于输出部分。输出部分在化简时我的层次和结构做的很差,这是出现bug的主要原因。

    3.自己构造的测试用例不够全面。

    三、互测采用的策略

    互测中我采用的策略是人工阅读代码+自动生成样例对拍。依靠这种方式,三次作业中我都找到了互测屋内其他同学的bug。在阅读他人代码的过程中,也学习到了一些更好的处理思路。有趣的地方在于,我自动生成的样例可以测出别人的bug,却在测试自己的程序时难以发现自己的问题。我想这主要是因为,自己写代码时考虑的需求,可能会体现在构造样例上。如果说前两次的作业使用python中的regex包就可以生成比较好的测试样例,第三次作业则需要自己想出一套构造测试数据的方法,而在构造时我图方便,也并没有把所有情况覆盖全,这也导致了后面自己的程序也没有能够覆盖所有可能的情况。

    因此可以说,在设计程序/分析需求时就考虑如何测试,或者在设计测试程序时,主要面向所有的需求,而不去考虑自己程序的具体实现,可能更容易构造出覆盖全面的测试集。从某种意义上讲,测试与设计也是相辅相成的,根据测试中产生的问题不断改进,未尝不是一种可取的设计思路。

    四、对创建模式以及重构的思考

    尽管第二次实验也考察了工厂模式的实现,分享课上也有同学分享过类似的设计模式,但我对于这种创建模式还是不太能得心应手地应用。或者说,在这几次作业中,我还不太能感受到创建型模式的优越性。如果后续有机会可以阅读到利用这一方法实现的同学的代码,可能我的理解会更加深入。

    但在重构方面,做第三次作业时我发现前两次作业的架构并没有很好的扩展性,于是第三次作业我重新设计了架构,采用Factor和AddPowerable两个接口来归一化各种因子和项的设计。这种层次化的设计让我在实现求导功能和相对性能不太好的输出时感到得心应手,十分清晰。这次重构前我对于整个架构提前做了设计,写起来就比较舒服,颇有一种顺滑感,但是后期写到读入的部分,由于之前的设计每台考虑过这里,就有些阻塞,写出来的代码也相当难看,确实是未来应当改正的地方。

    五、心得与体会

    1.抽象是面向对象的关键。越写到后面越发现,初期设计时,如果抽象做的好,那么后面就可以用一个方法实现相同的功能,而不至于写了几处相同的地方而不自知。

    2.架构对coding至关重要。前两次作业的架构比较简单,大概看完指导书,脑子里就能有大概的思路了,但是第三次作业需要设计好大概的架构才会有下手的勇气。而且良好的架构在后续的开发中也能更好地满足迭代的要求。

    3.一个方法不要承担太多功能。缺乏架构时,往往想到哪写到哪,让一个方法承担了“不能承受的生命之重”事实上应该考虑一个方法只实现比较简单的功能,复杂的功能由多个方法组合实现。不可能一个方法既能求导又能化简,既能输出又能化简。带着一个方法实现太多功能的思想编程,必然会越写越难受。代码风格检查对方法长度有限制不是没有理由的。

    4.认真分析需求。

    5.在测试中改进程序。

    4、5在上面已经有提到过,在此不再赘述。


    最后,感觉自己好像已经触及到了面向对象的大门,看到了里面的世界,但自己尚未称得上入门。希望下个单元自己可以学到更多东西。

  • 相关阅读:
    opacity兼容性以及存在问题处理
    删除节点方法要注意的区别
    java基础-常见面试题(一)
    第04次作业-树
    第03次作业-栈和队列
    第02次作业-线性表
    Data_Structure-绪论作业
    C语言第二次实验报告
    C语言第一实验报告
    mysql 查询优化
  • 原文地址:https://www.cnblogs.com/duaawyk/p/12516976.html
Copyright © 2011-2022 走看看