一、第四单元作业总结
1、第一次作业
第一次作业针对UML类图的相关内容,要求实现类信息查询、继承与实现关系分析等操作。由于之前从未真正接触UML类图(IDEA自动生成UML类图除外),对一些相关知识还比较陌生,所以本次作业让我耗费了大量时间去做一些前期的准备工作,比如查找UML类图的相关资料、认真研究课上的PPT、亲自动手画类图等等。这些前期工作决定了对UML类图的掌握程度,也决定了架构以及代码实现的质量。
我的第一次作业架构主要分为三部分:顶层的是与外部库(封装好的jar包)交互模块,实现UmlInteraction接口,内含查询类的个数、查询顶层父类等方法。中层是对从外部库接收的UML信息进行处理,记录所有类的所有相关信息以及所有关联的信息等等。底层是具体的元素类,包含Class类、Operation类、AssocationEnd类等等,真正有用的所有信息都存放在这些类之中。
在UML语言中,我认为各个元素的id十分关键,它是UML元素的唯一标识,与各个UML元素一一对应。将这一特点运用在架构当中,就是用Hashmap存放<id,element>键值关系,从而可以通过id找到对应的UML元素。而为了能够通过name找到对应的元素信息,迎合外部接口的需要,需要另外建立Hashmap来存放<name,id>键值关系。此外Hashmap还参与构造UMLClass、UMLInterface元素的继承与实现关系网络,通过递归查询类的顶层父类以及所有实现的接口。可以说,Hashmap的使用是本次作业设计的关键。
本次作业比较难实现的部分,个人认为是查找类实现的所有接口,主要部分为递归遍历接口的所有祖先接口。递归部分代码如下:
1 public void searchFathers(String interfaceid) { 2 if (!interfaceidmap.containsKey(interfaceid)) { //该接口是否已访问过 3 interfaceidmap.put(interfaceid, 0); //存放访问过的接口id 4 interfacenamelist.add(getInterfacemap().get(interfaceid).getName()); 5 Classnode centerinterface = getInterfacemap().get(interfaceid); 6 ArrayList<String> interfacefathers = 7 centerinterface.getinterfacefather(); 8 int length = interfacefathers.size(); 9 for (int i = 0; i <= length - 1; i++) { 10 searchFathers(interfacefathers.get(i)); //递归访问接口的所有父接口 11 } 12 } 13 }
本次作业的UML类图如下:
2、第二次作业
第二次作业同往常一样,是在第一次作业的基础之上进行增量设计,只不过此次作业的迭代设计更加典型——整个第一次作业可以直接应用于第二次作业的UML类图分析部分。也就是说,可以通过继承来扩充功能类,添加关于UML顺序图与状态图的分析部分。第二次作业新增的顺序图与状态图部分知识量也不小,同样需要在设计架构与代码实现之前做好准备工作。
第二次作业架构与第一次架构思路差别不大,主要是增量设计:在功能类中增加对顺序图和状态图的分析,增加State类、Interaction类等等。第二次作业所用到的算法在第一次作业中都有所涉及,比如递归查询父类等。第二次作业新鲜之处在于状态图的构建,自己要通过一定的数据结构还原UML状态图。其实这部分内容在第三单元早就有所涉及,也就是图的构建与相关操作。在本次作业中,我依然采用邻接表的方法建立状态图模型,使用dfs算法进行后续状态的查找。具体的递归实现与第一次作业大同小异。
本次作业的UML类图如下:
二、各单元架构设计与OO方法理解演进
1、第一单元
第一单元的主题是以长表达式(字符串)为基础,进行单元拆解。第一单元的作业设计,就是对字符串的拆分与计算的过程,其中拆分为主,计算为辅。第一单元的架构模式在第三次作业中得到了十分明显的体现:加多项式由乘多项式组成,乘多项式由加多项式组成,各种具体的函数式(幂函数式、三角函数式)可化归为乘多项式。需要对加多项式和乘多项式分别建模,对应的每个类中既存储构成多项式的数据,又自带求导方法。
在第一单元中,我从对java语法一知半解到比较熟练地运用,思维从面向过程逐步过渡到初步的面向对象。第一次作业中,我总共就设计了三个类,一个类进行字符串的拆分,一个类存储所有拆分过的子表达式,另一个类进行计算。结果每个类都十分冗长难看,每个方法都十分复杂,十分面向过程,难以理解与维护。第三次作业,我对每种多项式都设计了对应的类,并单独设计字符串拆分与匹配的功能类,架构上有所进步。
2、第二单元
第二单元的主题是基于多线程的电梯调度设计。在本单元中我第一次接触到多线程编程,学习了不少java多线程的知识。第二单元的架构主要是对电梯线程与乘客线程分别建模,将调度器与电梯、乘客分离,可以对调度器单开一个线程。第二单元的需求情景类似于生产者与消费者模型,调度器接收并处理来自于乘客(生产者)的请求,电梯(消费者)主动地从调度器中接取请求。
在本单元中,我对线程安全的理解逐渐深刻,对面向对象设计架构的理解也逐渐加深。在代码实践过程中,能够更加轻松地对需求情景中的对象进行抽象,更加熟练地对对象之间的联系进行分析与建模。
3、第三单元
第三单元的主题是JML规格化设计,其实可以说是图论相关算法单元。在本单元中我第一次接触到JML语言与规格化设计方法,并在第一次作业中得到实践应用。第一次作业比较简单,看规格写代码,再加以适当的优化,没什么好说的。第二、三次作业的主题是基于图的算法应用,包括最短路径算法、bfs与dfs等遍历算法等等。
要运用图论的算法,首先要正确、高效地建立图模型。我在两次作业中都采用了邻接表方式建模,用Hashmap进行节点的邻接关系映射。第二次作业中,我将不同路径id相同的点视作一个点进行建模;而在第三次作业中,我对所有的点都分开建模。增量设计使得我采用继承的方式,保留关于图的计算类(内含最短路径算法与dfs遍历算法)以及节点类(存储id以及pathid还有邻接节点的相关信息)。
第三单元训练了我的建模能力,强化了我对图论算法的熟练使用。并且对java各种容器类的使用也更加熟练,能够利用各种容器类快速地组织起来适合于相应算法的数据结构。
4、第四单元
第四单元的主题是UML模型的分析。知识量大,代码任务也很重。在本单元中UML的各种元素都要在架构中有所体现,具体形式是对应为一个个具体的类,存储UML元素的信息与相关操作。对UML模型的理解十分关键,理解的透彻,写起代码来就轻松自如。具体的架构与设计在之前已经进行说明,不再赘述。
通过对UML的学习与理解,我对面向对象的理解也更加透彻。类的内部元素、类与类之间的关系,从UML图上,映射到了我们的代码之中。
三、各单元测试理解与实践演进
1、第一单元
初步接触java语言与面向对象编程,我对测试的理解还停留在大一的c语言面向过程阶段,缺乏调试大量工程代码的经验。关于测试样例的构造不太全面与充分,测试的方法还停留在面向过程测试阶段,缺乏模块化测试思想。第一单元的测试比较盲目,就是自己构造一些不同类别的多项式,进行测试。测试样例不多,质量也欠佳。通过测试找bug更多的是依靠运气,缺乏理性分析。
2、第二单元
在第二单元中,我的测试能力有所进步。在实践上我开始进行模块化测试,将测试分成几部分进行:对于线程安全的测试,对于电梯内部行为的测试……并且对于多线程的测试经验从无到有,也自己总结了一些多线程测试的小技巧:打印语句判断轮询、在线程等待与唤醒处设置标志……不过对于测试样例的构造还尚未做到全面与充分。
3、第三单元
在第三单元中我开始尝试编写测试程序,对类内部的数据进行合法性判断,确定对于数据的处理是正确的、各个类得到的信息是正确的。这使得我的测试效率大大提高,不用完整地跑一组测试样例,就可以找到一些关于数据处理的bug。此外,我关于测试样例的构造也在不断地进步,能够理性地分析每个测试样例的侧重点,更加全面地构造测试样例。
4、第四单元
第四单元的测试要结合UML图,不过本质上并没有变化。在这一单元中我的每个测试样例的侧重点更加突出,测试目的更加明确。并且我继续保持着编写测试程序的习惯,写完代码,先写测试程序,先保证每个类得到的数据是正确的。对于功能类,即对数据的分析处理,我进行模块化的测试,对于类的计数、类的可见性查询、类的顶级父类查询等各种操作分别进行充分的测试。
四、课程收获总结
经过一个学期的面向对象编程训练,写了11次复杂的代码作业与4次总结性的博客作业,我的面向对象设计与构造能力得到了很大的提升。从一开始的盲目、混乱的架构以及可维护性极差的代码实现,到后来的理性的、面向对象式的架构以及较高质量的代码实现,我的设计架构能力与代码实现能力有了不小的进步;从一开始的随缘测试、大海捞针找bug,到后来的科学构造测试样例、编写测试程序以及模块化测试,我的测试水平得到了提升。
除了能力上的提升,知识上的收获也十分丰硕:第一单元让我熟练掌握字符串相关操作,学习了不少正则表达式相关知识;第二单元让我了解了java多线程的许多知识,对锁、wait、notify、jion等知识与概念有了比较深刻的理解;第三单元让我复习了大一下学期的算法与数据结构,对图论的相关知识有了更深的理解,同时也学到了很多JML的相关知识;第四单元让我学到了很多UML的知识,并能够熟练地通过画UML图来表述自己的架构。
五、对课程的改进建议
1、官方的对指导书的扩张解释或类推解释、重测等重大消息,除了在讨论区开贴说明之外,最好能够以更加有效的方式及时地通知到大家(比如在通知群里通知大家等)。
2、最好能在课程中心建立相关课程栏目,方便及时地给大家发放PPT等课程资料(就像计组、OS、马原等课程一样)。
3、部分作业好像不太符合单元主题(对,就是第三(JML(图论))单元,大家在第三单元里都忙着学习和选择相关算法,缺乏对JML的学习和规格化设计)。