zoukankan      html  css  js  c++  java
  • 面向对象第一单元总结与心得体会

    大体思路:

    第一单元的三次作业要求都是给定一个表达式,求导函数。从过程上分析,需要以下这些步骤:

    ·将读入的内容解析成多个对象,并为这些对象寻找一个合适的容器去储存。

    ·求导,产生对象,同样需要容器储存

    ·输出结果

    顺着这个思路,我开始了三次作业

    第一次作业

    作业初步分析

    以下为第一次作业的UML图

     可以看到,第一次作业中我的封装意识并不强,将原本应该在定义的项类内部完成的工作交给了主类完成,这一点破坏了封装性。而且类内部本身方法众多,且无法区分哪些方法只是为了避免单个方法过大而分离出的方法,总体上,程序的结构混乱,完全不利于后续的修改和拓展

     以上为Metrics Analyse的结果,ev高意味着非结构化程度高,难以维护和模块化。

    BUG分析和DEBUG策略

    我所采用的BUG分析和DEBUG策略是分块+静态分析辅以特殊情况的构造。首先,程序执行分为开头说的三步,那么就一步步分析。第一步,因为我是使用正则表达式解析字符串的,而且没有Wrong Fromat的情况,那么只要我保证正则表达式正确,就能逐项解析出各个项,再利用后续的提取程序获得项这个类的对象,装入容器即可。因此我需要检查的是正则表达式是否正确,以及解析程序是否正确。因为第一次作业中项的形式不多变,因此我采用穷举法来找错误;第二步,针对求导,只有一些特殊情况需要重点考虑,这些情况也能够穷举;第三步,输出,也能穷举。

    总体而言,第一次作业很简单,因此可以依靠穷举完成所有debug的工作。当然了,这必须建立在对程序相当熟悉的基础上。我使用这种方法,对于自己的程序很有效,但是对于别人的就不一定了。我自己强测和互测被发现的bug数为0,但发现的bug数同样为0.

    对比的心得和体会

    因为第一周用静态分析的方法全力找别人的bug,所以我吸取了别人的程序中非常好的方面,并在下一次的作业中应用了这些。

    封装性的强化:在构造方法中解析。我看到了一种处理程序的方法,建立了项类,并在其构造方法中解析输入的字符串。这就把生成对象的具体过程封装在对象的构造方法中,提升了封装性。

    第二次作业

    作业初步分析

     可以看到,这次的作业相比于第一次复杂了不少,但是仔细看,主类只有底下的一点,我把大部分的工作交给了其他的类。我的策略是,把输入的字符串交给多项式类,再通过项类、因子类将字符串逐级解析下放,并通过简单工厂模式产生因子对象,再通过boolean类型的isWrongFormat将是否存在不合法格式逐级上报,同时在构造的时候就在各个层级上将能合并的都合并了。我将所有的类都设为不可变类,这就意味着,所有的类的成员变量只能通过构造方法设定。我认为求导是这些类的行为,因此就把求导设置成了这些类可以被访问的方法。最后,通过逐级上传的方式,我利用toString输出结果。

    在这次作业中,封装得到了大的提升。但是依然应该看到,还是有不少问题的。例如在下图中,这些方法都过于复杂,而且有些方法实现了不止一种功能,例如toString方法,我在其中还加入了简化,这显然不符合解耦的原则,而且由于时间原因,Simplifier类没有很好地设计,导致ev、iv和v数值不同程度的高(实际上,我程序中的bug全部出现在这些地方)

    BUG分析和DEBUG策略

    在bug分析和debug策略上我依然采用的是模块分析+静态分析辅以构造测试的方法。而且步骤基本大同小异。唯一不同的一点在于优化,在原先优化的基础上我又增加了一个专门的二次优化用的类,但是后续没有时间严格静态分析debug,只做了一些简单的测试,导致强测直接50分。

    在互测中我没有仔细去看其他人的程序,因为我发现随便写一个包括三角的测试都能hack,也就是说互测屋里都是和我一样优化失败的。

    心得体会

    相比于上次一的程序,这一次的程序中多了一些私有的方法。这些方法有的在类中承载了一定的功能,但只供类内部的方法使用,有的只是单纯为了降低方法的复杂度而分离出的子方法。通过private关键,程序的封装性提升了。

    在这一次作业中,我进行了重构,设置了三级类,它们之间存在着明显的上下级关系,但是这种关系并不是继承上的,而是实现上的。这种模式使得这些对象使用起来并不是很方便,但是层次性明显,避免结构的混乱,后续也不用修改这种架构。

    本次作业其实存在致命缺陷,这种缺陷将使得后续的维护和扩展极为困难,那就是多项式中项的组织方式,以及项中因子的组织方式。有的时候我想要规范化(即保留0次幂和系数1),有的时候又删去,这种混乱的组织方式会导致后续的灾难,即使我再心细也有出错的可能。

    第三次作业

    作业初步分析

    本次作业加入了嵌套表达式,这使得难度进一步提升。但是,有之前的3级架构的存在,这种我们只需要在这个三级架构之上加一个关系就可以了,即因子->表达式,这就组成了这次作业最核心的架构。以下为此次作业的UML图:

     可以看到关系相比于第二次作业并没有复杂多少,这同时也证明了第二次作业中的三级架构非常具有扩展性。其实原因也很简单:这种结构抓住了多项式的本质。

    在本次的作业中,我依然是采取了三步法完成程序,只是在各个阶段采取的上下策略不同。在构建表达式的时候,我采取的是由外而内的构建方式,在多项式阶段将括号中的信息储存(当然括号如果不匹配直接WF)并替换特殊符号,在解析到因子阶段的时候再依情况释放并选择是否加工(因为三角本身自带括号),进入下一层的表达式。这样采用递归的方式,表达式就构建起来了。当然,为防止潜在的爆栈可能,我将简化深入到了构建表达式的过程中。在项构建阶段(即在接受字符串的构造方法)的末尾,我加入了简化的方法,对每一项都使用transfer方法,将所有的”假形式“(即指数为0,三角括号中为0或x的表达式,表达式因子本身只含有一个因子,可释放)全部转化为对应的真形式,并进行简单的同类项合并,同时返回的形式是我们常用的形式(不含1系数,常数项为0则整项只含有这个0)。递归的化简伴随着构造,这种情况虽然不利于解耦,但是可以有效避免爆栈或者tle,因为等到表达式完全构造完成再做简单的化简,就需要遍历整个表达式(实际上是依附于三级结构的树状结构),这又是一笔开销,如果在构建阶段就完成简单的化简,则后续求导遍历的表达式深度也会减少。

    在求导和输出方面,依然沿袭了上一次的方式,求导的过程伴随着简化,也采取了逐级上传的模式。

    化简体现在了两个方面:因子的“释放”和因子间的合并、项之间的合并。因子释放的问题很好解决,在接口中定义transfer并实现就行了,但是项和因子的合并却并不好解决,因为要判断项是否可合并,就要看项中的因子,要判断因子是否可合并,就要看因子包含的表达式是不是一样,这就回来了。我采取的策略是,从最里层开始写相同和可合并两个判断用的方法,再逐级转向外层,也就是说,这种写法要思考因子项两次。

    以下为此次作业的度量:

     可以看到几乎所有的都是ev的值过大,也就是说这些方法的安排并不妥当,难以结构化和模块化。这属于方法本身的问题,要优化风格,就要适当拆分这些方法。但是有一些可以有更好的方式解决。之后再说。

    BUG分析和DEBUG策略

    本次的bug分析和debug依旧沿袭了之前的策略。事实证明这种方法对于心思缜密的人来说非常有效,但是并不适合一次找多人的bug,时间明显不够。

    心得体会

    第三次作业结构化和封装性都非常好,此外由于在多个类中都会用到正则表达式,而个各类单独建立又过于麻烦,于是我单独建立了一个正则库,所有的正则表达式都从这里取,而且要修改也非常方便。

    但是,这里面依然有可以改进的地方:

    ·优化、求导可以单独建库,并通过类似于工厂模式的方法实现。优化和求导的确是三级结构的行为,但是把这些方法可以像正则表达式一样抽取出来,建立一个行为库,同时考虑到不同的类的行为不同,可以采取类似于工厂模式的方法实现。虽然化简过程最好贯穿构建和求导的过程,但这并不意味着不能建立一个库存放这些行为。这样,单独的类就不会过于臃肿。

    ·因子类可以进一步细化。在本次作业中我将因子还是分为了四类,但是在除常数类之外的因子中都存放了有无表达式作为底和底的信息。这三类因子可以弄一个抽象类,再在每个抽象类下完成有表达式和无表达式的行为,这也就是之前分析度量的时候说的更好的解决方法。

    ·打包。我们可以看出,这些类中有些具有共同的特点,比如因子,具有很强的相似性。那么我们就可以通过打包的方式,将这些类以及接口放在一个包内,这样,我们管理类就更有序、更有层次了。

    BUG分析和DEBUG总结

    可以看到模块分析+静态分析辅以构造测试动态追踪是一种非常强大的方法。这种方法的强大性在于,从源头上、一步一步地排除掉所有可能出现的bug,使得程序事实上无懈可击。这也是唯一一种能做到完全debug的方法,大批量、自动化测试只能顾及到大部分情况,边界情况和特殊情况命中的概率极小,且测试的时间开销有可能巨大。这种方法通过模块化的静态分析发现问题,再确定是否需要辅以动态追踪来具体定位,保证从开始到结束每一个过程都正确,那么程序整体就没问题。

    但是,这种测试方法的缺点也是非常明显的。第一,测试的质量完全取决于程序员和程序员对代码流程的理解。通俗来讲,就是因人而异,碰上思维缜密的,那就没问题,但是碰上马虎大意的,就有可能导致程序严重出错。也就是说,这种方式只适合哪些思维缜密的人。第二,这种测试方法费程序员。直接后果就是,这种测试方法不适合大规模工程,除非有和工程结构配套的程序员去模块化测试。

    心得体会总结

    第一单元作业由于我提前对于工厂模式有所了解,加上上学期有一些java的基础,我对于一些java的机制在上学期不明白的豁然开朗,对于面向对象的思想也有了一定深度的理解。也正是由于这种理解,我很轻松就掌握了简单工厂模式和工厂方法模式的应用。也有了将正则提取成库的程序和将表达式的行为建库的总结想法。总体而言,我觉得我这个单元的内容掌握的不错,课程也还算简单。

  • 相关阅读:
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    实验二 K-近邻算法及应用
    实验一 感知器及其应用
    实验三
    实验二 结构化分析与设计
    实验一 Visio的使用
    ATM管理系统
    流程图与活动图的区别与联系
    四则运算
  • 原文地址:https://www.cnblogs.com/zzy122530/p/12542273.html
Copyright © 2011-2022 走看看