OO_UNIT4_SUMMARY
经过一个学期的学习,OO课程终于落下帷幕。本次博客会首先对第四单元作业的架构进行分析,再对OO课程进行总体回顾,最后是个人的建议与体会。
一、第四单元三次作业架构设计
1、第一次作业
第一次作业是对类图的解析,与之前的几次作业都不太相同的是:本单元的几次作业的代码构建都有较强的层次性,无论是类图、顺序图还是状态图都比较强调各种元素之间的联系。对于类图来说,除了给定的MyUmlInteraction类,我还新设立了MyUmlClass、MyUmlInterface、MyUmlOperation、MyUmlAttribute和MyUmlParameter类。由于对JSON文件是单条指令单条指令的读取,如果对一些内部元素提前处理可能会找不到上层元素从而报NullPointException的异常,所以可以分层读取,也可以全部读取结束后再对诸如UmlClass和UmlOperation的元素联系起来。具体的类图如下所示:
下面以MyUmlClass为例做简要介绍,首先个人的MyUmlClass类中的属性如下图所示:
private UmlClass umlClass; private String parentId; //父类ID private boolean isRepetition = false; //是否有名字重复的 private HashSet<MyUmlInterface> implementNum = new HashSet<>(); //实现的接口 //关联 private int associatedNum = 0; //关联数目 private HashSet<UmlClass> associatedClass = new HashSet<>(); //关联的类 //属性 private HashMap<String, MyUmlAttribute> nameAttribute = new HashMap<>(); private HashSet<MyUmlAttribute> idAttribute = new HashSet<>(); //不违背信息隐藏原则 private List<AttributeClassInformation> list = new ArrayList<>(); //方法 private HashMap<OperationQueryType, HashSet<MyUmlOperation>> operations = new HashMap<>(); private HashMap<String, HashMap<Visibility, Integer>> nameOperation = new HashMap<>();
属性中包含自身的UmlClass,判断是否重复的布尔值,实现的所有接口,关联的数目以及关联的类,类中含有的属性以及方法等,在MyUmlClass的属性中可以看到很多都是在MyUmlInteraction中对某些关于类的信息查询的返回值,这样在查询时可以直接调用相关方法。需要注意的是在很多查询方法时需要使用递归,比如查找属性是否重复时需要将父类的所有属性也要考虑进去,但是应该通过ID而不是Name来找父类,否则因为姓名重复而导致错误。同时在查找所有实现的接口时,需要对访问过的接口进行标记,否则可能会超时。
2、第二次作业
第二次作业在第一次作业的基础上增加了状态图和顺序图的查询,总体来说没有很大的差异,我将类图、状态图和顺序图分成了不同的类,每个类的属性如下所示:
public class MyUmlInteraction private HashMap<String, MyUmlClass> nameClass = new HashMap<>(); private HashMap<String, MyUmlClass> idClass = new HashMap<>(); private HashMap<String, MyUmlInterface> idInterface = new HashMap<>(); private HashMap<String, MyUmlOperation> operation = new HashMap<>(); private HashMap<String, UmlElement> idElement; private HashSet<String> repetitionClass = new HashSet<>(); //重复的类的name private HashSet<String> nameClasses = new HashSet<>(); public class MyUmlCollaborationInteraction private HashMap<String, MyInteraction> idAndMyInteraction = new HashMap<>(); private HashMap<String, String> nameId = new HashMap<>(); private HashSet<String> repetitionInteraction = new HashSet<>(); //存储重复的interaction的name private HashMap<String, UmlElement> idAndElements; public class MyUmlStateChartInteraction private HashMap<String, UmlElement> idElements; private HashMap<String, MyStateMachine> idMyStateMachine = new HashMap<>(); private HashMap<String, MyStateMachine> nameMyStateMachine = new HashMap<>(); private HashMap<String, MyRegion> regions = new HashMap<>(); private HashMap<String, UmlTransition> transitions = new HashMap<>(); private HashSet<String> repetitionStateMachine = new HashSet<>();
可以看到每个类只存储自己直系的下一层,这样职能层层分派可以防止在一个类中处理过多信息,类图展示如下:
3、第三次作业
第三次作业是对自己的类图、状态图以及顺序图做一定的检查,是对第二次作业完全的增量开发。
二、四个单元中架构设计及OO方法理解的演进
第一单元中我还是较为依赖面向过程的思维方式,第一次和第二次还算比较顺利,第三次作业较为复杂,处理起来也较为繁琐,由于没有将表达式、项、因子等分开处理,导致一个类中处理了过多信息,非常冗杂,对于一些细节也很难把握,对面向对象的设计思想理解得也不是很到位。但是总的来说包括对正则表达式以及封装、继承、多态等运用都有了较大的收获。
第二单元主要是多线程编程。首先需要理解的重点是生产者消费者模式,该模式除了在本单元的电梯设计上在其他很多方面运用也较为广泛,当然在本单元的学习中也了解了一些诸如单例模式、工厂模式等模式化编程思想。其次线程交互也很重要,在并发编程中如果对线程交互处理不当很容易产生死锁或者一些玄学Bug, 所以线程之间要职责明确,事先固定好分工。
第三单元主要是关于JML设计。虽然规格化设计看似是对大家编写代码的便利,但实际上它只是作为一种正确性保证,在实际编写过程中还是要运用一定的数据结构知识。同时关于JML的一系列自动化验证工具在使用时也是非常不方便的,对于例如openjml等工具的使用体验非常不友好,但是总的来说对契约化设计还是有了一定的了解。
第四单元主要是关于UML设计,我将几乎每个元素组件都单独构建成一个类,类与类之间根据上下层进行联系。本单元对迭代化设计思想体现得也较为明显,后两次作业都是对第一次作业的增量开发,对代码的扩展可能也是四个单元中体现得最为明显的。
三、四个单元中测试理解与实践的演进
第一单元测试自己主要是采用肉眼检查加手动构建测试样例的方法进行测试,但是实践证明手动构建测试样例不仅费时间费精力,根本不可能覆盖到所有情况,一些小错误也很难被测试出来。
因此在第二单元我根据测试样例的格式进行了自动测试数据的生成,再将程序生成结结果与他人结果进行比对。相对于第一单元的测试的确更加高效和简便,但是测试程序的正确性在测试中就显得较为重要,同时一些出现概率较小的bug也很难测试出来,所以只能多测试并且尽可能完善测试数据的生成程序,让测试数据覆盖尽可能多的情况。
第三单元又引进了JUnit单元测试,之前的测试都是黑箱测试,而这种白箱测试可以实现一边写程序一边测试的增量开发或者在写程序之前就将所有的单元测试写好,这样可以保证自己每个模块想要实现的功能都是正确的,提高了程序的可靠性。但是题意还是应该理解完全。所以本单元采用白箱与黑箱测试相结合的方法可以让程序测试得更加全面。
第四单元由于时间等问题我主要是在StarUML中手动生成一些极端样例然后导出mdj文件后根据实例方法导出数据。
四、课程收获及线上学习体会
本学期的OO课程虽然都是通过线上学习的方式进行的,可以说是有利有弊吧。理论课虽然是通过腾讯课堂录播的形式开展的,但是整体效果我认为线下上课可能相差无几,而且课上也增加了讨论题的环节(虽然大部分时候都是几位相同的同学与老师起舞弄清影,或者老师强硬点名回答问题)和课下问卷,所以对大家的督促作用也起到了较好的效果,录播视频也可以反复观看,不懂的地方可以一直温习。实验课我个人认为与在校没有什么区别,在校应该也是用自己的电脑。个人认为差别比较大的可能是研讨课,大家分享的几乎都是关于作业的一些架构设计与测试等等,之前说过的会请到一些企业实际操作的分享由于疫情原因搁置了会有些遗憾。但是总体来说,线上体验还是不错的,老师助教们准备得都很充分,几乎没有失误出现。
就课程收获而言,对于JAVA面向对象的思想有了一定的了解和运用经验,对于程序评判的标准也不应该只是正确性,而是应该有清晰的架构,良好的可扩展性,高内聚低耦合。同时对于测试程序也有了一定的经验,定位和修复错误的能力也有了一定的提升。一些同学课上分享的编程经验或者架构设计对自己也有很大的帮助。
五、改进建议
如果要提对于课程的具体建议的话,我认为首先关于JML单元的自动化测试工具比如openjml等方面内容可以舍弃,因为对代码检测没有实质性作用,对于一些小程序还能勉强应付,对于复杂程序会出现很多奇怪的错误,而且真的很花费时间。其次我希望实验课的结果可以及时反馈,就是参考答案可以及时给出,大家还可以在一起进行探讨,否则实验课的训练效果可能会大打折扣。最后是研讨课可以提前出一些题目让大家在一起讨论,过于开放的主题有的同学们之前都不是很熟悉,课上短时间内也不可能马上消化,所以很容易出现大家不是很积极发言的情况,提前给出主题让大家有时间准备可以让研讨课的事件利用得更充分些。
总之OO课程算是圆满结束了,很感谢老师和助教的辛勤付出,也祝愿北航的OO课程能够越来越好!