面向对象第四单元学习体会与总结

1、第四单元作业架构总结

2、四个单元架构设计与OO方法理解的改进

3、四个单元测试理解与实践的改进

4、课程收获总结

5、对课程的建议


 1、第四单元作业架构总结

  第四单元的两次作业,从目标上总结,都是对给出信息进行分类整理,再对各个信息内部进行特定要求的查询。只要明确了各个指令的意义,便能知道怎样存储较为方便,并顺利的写出指令。

  具体到实现中,具体要解决的问题有两点。

  通过上级元素名索引其内部信息

   基本所有指令都是对一个模型容器内部的信息进行询问,而所有信息都是逐个没有稳定顺序的输入,于是我在第一次作业中将所有官方接口中有的UmlElement全都对应了自己建立的新类,并在输入的同时将其全部放入相应的HashMap中。

    private HashMap<String, MyUmlAssociation> associationMap = new HashMap<>();
    private HashMap<String, MyUmlAssociationEnd> associationEndMap =
            new HashMap<>();
    private HashMap<String, MyUmlAttribute> attributeMap = new HashMap<>();
    private HashMap<String, MyUmlGeneralize> generalizeMap = new HashMap<>();
    private HashMap<String, MyUmlInterfaceRealize> interRealizeMap =
            new HashMap<>();
    private HashMap<String, MyUmlOperation> operationMap = new HashMap<>();
    private HashMap<String, MyUmlParameter> parameterMap = new HashMap<>();

    private HashMap<String, MyUmlInterface> interfaceMap;
    private HashMap<String, MyUmlClass> classMap;
    private HashMap<String, String> findClass;
    private HashSet<String> dupClass;    

  之后在遍历一遍下级元素,在上级元素中设置HashMap,HashSet,ArrayList等容器将下级元素加入。比如遍历Attribute的Map,将其加入MyUmlClass中设置好的容器中。

  这里出现的findClass和dupClass是用来实现按名查找的。在存入MyUmlClass元素时,都遍历一遍已存入的MyUmlClass检查重名情况,将检测出的重名类名加入dupClass中。

  第二次作业中,发现并没有必要每个新的UmlElement元素都去建类。原因为:一部分UmlElement是查询时完全用不到的;另外一些元素可以在其上级元素的Map等容器中用基本类型进行表达,比如UmlLifeline,直接在UmlInteraction中用HashMap<String, Interger>去表示即可。

  这其实是符合Java本身自然方式的存储方法了。一个类的属性,方法等,自然是包含在这个类里的。通过这样的存储方式,第一次作业的指令的实现便十分简洁,具体也不再赘述。

  一点点算法实现

  第一次作业都是简单的将信息取出来,做个判断,或者数个数,问题就基本上解决了。

  第二次作业有两个规范性检查是有一些难度的判断:判断循环继承与多重继承,其余均与第一次类似。

  运气比较好,我的第二次作业第一次内容的部分是直接从第一次作业转移过来的,并且第一次已经在类和接口中设置了便于做查询的容器。

public class MyInterClass extends MyUmlElement {
    ......
    private ArrayList<MyUmlInterface> linkInterfaces;
    
    ......
    public ArrayList<MyUmlInterface> getLinkInterfaces() {
        return linkInterfaces;
    }
}

public class MyUmlClass extends MyInterClass {
    ......
}

public class MyUmlInterface extends MyInterClass {
    ......
}

  这样的设计使得我在处理这两个规范时很有大一下数据结构作业的感觉。

  循环继承:在类中发生只可能是一个环,用简单的循环判断。接口是重头戏,对每个接口广度遍历,遍历过的接口不再加入遍历队列,出现和当前接口相同的即发生循环继承。

  多重继承:在每个MyInterClass中进行深度遍历。得到可重复的相连接口的List。再判断List中是否有重复元素即可。对于类再把父类也考虑进去。

    public ArrayList<String> getAllDupInterfaces() {
        if (allDupInterfaces.isEmpty()) {
            for (int i = 0; i < linkInterfaces.size(); i++) {
                allDupInterfaces.add(linkInterfaces.get(i).getId());
                allDupInterfaces.
                        addAll(linkInterfaces.get(i).getAllDupInterfaces());
            }
        }
        return allDupInterfaces;
    }
  private boolean isDupList(ArrayList<String> tmp) {
  HashSet<String> a = new HashSet<>();
  a.addAll(tmp);
  return a.size() < tmp.size();
  }  

 2、四个单元架构设计与OO方法理解的演进

  第一单元,初涉OO,在第一次作业交了一个Java文件至今记忆犹新~。通过第一个单元,我理解到一个拥有独立功能和相关数据的模块便将其封装为类,类的内部不应该嵌套过多冗杂的功能。这些在第一单元中的“求导法则类型”,“基本表达式”类型都有所体现。

  第二单元,学习了OO的一个重要机制:多线程。有了第一单元的基础,在第二单元中将各个模型建立的过程比较顺利。电梯系统的各个部分:任务输入,任务分配,电梯接受任务,任务执行都可以进行明确的解耦与封装。此外,共享资源的增加也让我对多线程的安全性有了更加深刻的理解。从一开始的一个任务缓冲区,到输入与调度器,调度器之间,调度器与电梯都设有共享资源,若没能关注到所有地方的可能出现的问题,程序甚至会在自己完全意识不到的情况下废掉。

  第三单元的架构并没有给我很深的印象。一是作业要求就已经非常明确的指出了我们需要怎样的对象去储存怎样的信息;二是在后期要求增多时,我也没有像同组的一些大佬一样将任务抽象为很多层,而是在一两层左右就将问题进行统一的解决。这个单元我理解最深刻的是规格的作用。明确每个方法,每个类的规格,一是便于对模块自身进行单元测试;二是能够使各个模块的整合结果的准确性更高。我意识到自己时常的凭感觉“大写特写”的方式是有问题的,严密的规划是工程的基础。

  最后一个单元,是对OO的一个重要的工具——UML图的理解。就作业本身来说,重点偏向了OO最基本的东西:类的设计以及信息的读写。当然信息的量是比较大的。将这些大量的信息分批整合,给出读取方法,个人认为在OO方法上是偏倒退的一个挑战,但实际完成下来,我对编码过程中的严谨性更加的注重了。

 3、四个单元测试理解与实践的演进

  四个单元的测试方法,正如他们的设计一样,是有不小的差异的。

  第一单元,对测试还比较抗拒,正巧这个单元中测的测试难度都不小,也比较全面,没能被坑到。而我做的测试,也仅仅是对指导书上的一条条要求自己想合适的样例进行测试。这时我对测试的态度其实是可有可无的,但是之后出现问题后,态度便发生了变化。

  第二单元第二次作业,过中测后没能进入互测。debug后发现就是一个平常的随机数据将我的程序给炸了。很显然,中测已经不再是我的保护伞了。在第三次作业中我使用python的subprocess模块进行了批量的随机数据测试,并自己写了一个简单的测试逻辑对结果进行检查。很幸运,找到了一个多线程相关的bug。最终的强测也没有再出现别的bug。没有了中测的保护后我意识到程序仅仅过了中测是远远不够的,数据的类型有无数种,谁能保证就没有一组能使自己的程序bug呢?

  第三单元,我首次尝试了单元测试junit,这是供程序编写人员使用的白盒测试方法。老实说,最后也不算很会用,操作过程对于我来说有点烦人。但这不能否认单元测试的重要性,我相信如果是在大型工程中而不是课程作业中时,确保每个模块正确的重要性是毋庸置疑的。正如搭积木一般,一块未稳便可能轰然倒塌。

  第四单元,对于我来说,测试数据随机生成是做不到的了。但这次我使用了“单元测试”的方式(未使用Junit)。我针对每个指令都画出可能出现bug的UML图,将其作为数据进行测试。事实证明测试是真真真的很重要!!!我在最后一次作业中找到了bug——循环继承的检测中进了死循环。。。

  对于一个写好的程序,一些随机数据的功能测试说服力是不够的。我认为较为完备的测试需要大量的随机性够强的随机数据,辅以各个接口模块的手编数据,这样才能验证一个程序的基本功能的正确性。

 4、课程收获与总结

  说到这里,老实说2,3点似乎已经包括了很多这里的内容。。。我大概的再总结一下吧。

  第一,学了一点儿Java语言(手动滑稽),Java语言真的是一个很严谨,也比较强大的语言,它许多容器的设计原理,如HashMap真的非常有参考与学习价值。

  然后,面向对象,说道理Java就是来干面向对象的活儿的。这个学期这么多次作业,每一次都能总结为多个对象互相协作来解决相应的问题。这些对象的抽象,模块化,规格化,这门课让我印象较深的一点。

  最后,测试,实话说大学以来这算是我在测试上花的力气最大的一门课了。我的认真的测试是从第二单元开始的,编写数据生成逻辑和结果检测逻辑都是很费劲的活儿,但能看到强测最终没出bug我也没啥遗憾了。而且,在测试时我也逐步加入了面向对象的思维。数据生成与投入之间的接口,结果输出与正确性分析之间的接口,我在某一次作业后发现这些东西认真构思后是可以在不同类型的作业测试中通用的,怎么说呢,这可能也算是一种学以致用吧(笑哭)

5、课程建议

  提高对架构的重视程度。我的架构,其实没有哪次是特别令自己满意的,不少对象的设计还是带有面向过程的思维。但是,怎么说呢,面向过程写得快啊!在时间不是很够,也基本能做对的话,我是不会去深究架构的。我也确实是很想学一些大佬还有助教给的标程的,但是一写起来,发现并不用那么多代码也能把强测过了,,就真的直接摸了。。。

  进一步鼓励互测。我的互测积极性一直都不是很高,只要能把自己的程序测准了,就真的不想花时间去测别人的程序了。

  指导书,各个要求,希望不要那么模棱两可了。当然这学期大多数指导书是优秀的。但是某一些(尤指第四单元),真的是边猜谜边写,真的很难受。

  

猜你喜欢

转载自www.cnblogs.com/Leopordcfbuaa/p/11072888.html