OO第一单元作业总结

喜你入骨 提交于 2020-03-19 13:24:41
第一单元小结
  1. 基于度量分析自己的程序结构(工具:DesigniteJava、MetricsReloader)

    总的分析:unit1的作业的代码的质量不是很高,主要有以下几点原因:

    1. 类与类之间耦合程度过高,可扩展性差
    2. 部分类内部实现过于复杂,不利于调试和维护
    3. 没有使用对象构造中的工厂模式进行因子、项等的创建
    4. 部分类内部方法的实现不够聚合,会与其他类的一些方法有较大联系

    圈复杂度:和类内部实现的复杂度相关,循环条件判断等复杂的逻辑组合相关

    类之间的依赖关系

    UML图如下:

    分析:在这次的设计过程中,类的划分上是存在一定的问题的,例如对于不同因子的求导的过程,求导应该交给对应的类自己去完成,在内部实现求导功能,返回一个统一的类型,而不是交由外部进行判断然后求出求出对应的结果,因此应当在之后的设计中尽可能降低类与类之间的耦合程度,增加类内部的聚合度,从而实现功能的专一性(职责明确),DIT为1。

    优点:使用到了类的继承的设计结构,抽象方法的复写

    缺点:方法的功能上不是很专一,方法与方法之间的耦合度比较高,有些方法的实现过于复杂,不便于调试和维护

    Metrics分析:

    分析:在这一单元的构造中,部分的代码架构不是很好,不太容易维护,其中最主要的原因是大量的使用到了if-else的逻辑判断的语句,同时存在者多层的嵌套结构,导致代码的可维护性和可扩展性大大降低;

    解决的办法:通过将方法内部结构进行拆分,对功能复杂的函数,进行拆解,有多个函数共同实行,尽可能地简化实现的逻辑结构。

  2. 分析自己程序中的bug:(在三次实验的过程出现的唯一一次bug是最后一次无脑将x**2直接替换成x*x,导致输出结果出现WF,结果强测炸了四个点,还被刀了两刀,需要引以为戒;同时介绍一些我在程序调试的时候出现的bug,供大家参考)

    1. homework3:cos(x**2)中的x**2不能化简得时候,直接将其替换成x*x,cos(x*x)是不合法的,x*x不是一个因子,不能直接出现在cos()中,价格括号将其转化成表达式因子,但这样的话,实际上是负优化,结果的长度反而会变长,故建议去掉。

    2. homework3:(由于我的表达式的解析思路是将整个表达式先根据+-号分割成多个项,然后再根据*号将拆分成不同的因子,通过对项中的每个因子求导,最后实现对整个项的求导)由于第三次作业中可以有表达式因子,所以这些嵌套的因子会造成再用+-号解析时出现错误;

      解决方法:先对表达式中的()中的表达式因子替换成一个特殊符号,以此来消除()中加减号的影响

    3. homework3:有关表达式格式的判断(是否WF),开始的思路是用一个大的正则表达式进行整体的判断,但是这种想法有个问题,实际的表达式事可以出现多层不断的嵌套(递归的形式),所以想要实现一次性的判断格式是比较困难的

      解决办法:再递归求导的时候,在每一层的时候就判断表达式的格式,如果WF直接结束程序,每一层的表达式用正则进行判断

    4. homework3:嵌套因子的求导,解决办法:递归求导,遇到包含表达式因子时,将表达式因子传递下去,递归,直到表达式中不含有()这类的表达式因子,然后返回即可

    5. 深拷贝和浅拷贝:需要时刻注意!!!,通过上网查阅相关的资料可得:对于函数中返回的对象而言,实际上并不是向我们想的那样返回的是一个对象的全部信息的拷贝,实际上返回的是对象引用(即引用地址的拷贝),因此会造成对象的共享,但当我们需要的是一个全部对象的拷贝时,就会产生bug;

      解决办法:实现cloneable的接口,实现clone方法;(注意:对于对象,clone方法实现的是对对象全部信息的拷贝,但是对于像Arraylist这样的列表来说,clone实际上还是列表中每个对象的引用地址,所以需要一个一个clone)

    6. 剩下的就是一些小的bug:比如第三次作业中有关括号、空格的问题等等

    小结:总的来说bug出现的位置,同时使逻辑结构较为复杂的地方,例如条件分支的嵌套、循环的嵌套、对类处理比较集中的地方,由于大部分的代码都是完成基本的功能,对于真正设计处理逻辑的核心代码使少部分的,因此bug往往会出现再核心代码的地方,处理逻辑较为复杂,总体上bug的出现使符合二八定律的
  3. 发现别人bug所采取的策略

    1. 首先是通过搭建的测试机进行大范围的评测,这一部分的样例格式上是没有问题的,检查的主要是整个程序的主要功能实现是否存在问题。
    2. 这对边界的测试点,用自己的构造的样例进行评测(例如+0*x*+0等)
    3. 性能测试点:在第三次作业中由于使用的是递归求导,所以会存在tle的情况,因此我们可以构造一些多层嵌套的样例,eg:((((((((((((x))))))))))))、sin((x+cos((x+sin((x+cos((x+sin((x+cos((x*x))))))))))))等等
    4. 格式测试点:x**2替换成x*x这种的求导格式上的错误(/(ㄒoㄒ)/~~一定要注意!!!)
    5. 针对代码的设计结构进行设计相关的样例:主要是根据正则表达式构造一些边界测试点进行测试
  4. 应用对象创建模式来重构:

    1. 总结前三次作业的总的构造方法

      创建表达式、项和因子三个数据存储数据的类,同时因子会包含三角函数、常数、幂函数、表达式因子四种子类;在抽象主类因子中会定义一些公共的抽象的方法,如求导、乘积等等,用到了类之间的继承;

    2. 整体思路

      • 先将表达式解析成为多个项Arraylist
      • 将每个项解析成为多个因子的组合
      • 求导:对每个表达式的求导转化为对每个项的求导,对每个项的求导转化为对每个之中的因子的求导,最后讲求到结果合并即可;对于嵌套因子的问题也可以这样,先对外部函数求导,在对内部的因子或者表达式的因子的求导,重复上述操作即可(递归求导)。
    3. 针对对象创建模式的一些改进思路

      • 可以使用工厂方法模式对产品的构造进行归一化处理,对这一题来说,可以将我们读入的表达式交给我们的总的工厂,然后总的工厂下面有项的工厂,项的工厂下面有因子的工厂,工厂之间是存在一定的关系的,最后返回产品的时候可以返回,项的Arraylist,然后每个项中包含因子的Arraylist,这样的话可以实现归一化的处理,同时返回的结构也比较的清晰便于处理。
  5. 对比和心得体会

    对比:通过对象创建模式的一些设计的技巧,可以较大程度上提高我们的可维护性和拓展性,在我们需要增加,反三角函数等其他的因子类型,我们只需要修改工厂可生产的产品种类即可,对于其他的业务逻辑的代码不需要做较大的改动;优化代码结构,使代码结构更加清晰。

    心得和体会:

    1. 在码代码之前要考虑清楚整个架构的设计,靠椅考虑一些向后兼容的问题,例如使用工厂模式等一些较为优化的设计结构、统一接口和继承等
    2. 调试的时候着重考虑逻辑结构复杂的地方,保证整体的业务逻辑没有问题
    3. 在做迭代开发的时候,需要注意迭代后的要求和之前的区别,对于化简和处理逻辑都需要重新思考,不然会造成像x**2被随意的替换成x*x造成格式上的错误,清除前后要求的区别对于迭代开发才能尽可能的在原来的基础上进行改进,减少重构 的可能
    4. 在这一次的作业逐渐接触到在面向对象的一些技巧和方法,开始体会到面向对象编程的一些优势,整体来说设计的优化会极大的减轻代码的编程工作,希望在接下的作业中能够考虑到代码的可维护性和拓展性,优化自己的设计。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!