面向对象设计与构造课程作业_第四单元总结_北京航空航天大学计算机学院 2019春季

面向对象设计与构造课程作业

第四单元总结

北京航空航天大学计算机学院 2019春季

17373468 赵子敬

 

单元主题: UML 模型的理解

第一次作业:实现一个 UML 类图解析器,可以通过输入各种指令来进行类图有关信息的查询。

第二次作业:扩展类图解析器,使得可以支持对 UML 状态图和顺序图的解析,并可以通过输入相应的指令来进行相关查询。在所解析的 UML 模型基础上,按照规定的规则检查模型中是否存在违背规则的情况,并输出相应信息。

 

一、总结本单元两次作业的架构设计

这两次作业都是解析UML文件,实现一些检查和查询,在此过程中加深我们对UML模型的理解。

第一次作业只解析UML类图,类图从文件中类的层次梳理代码的数据管理和交互方式,已经解析出的类图文件将所有类图中的元素打散,将信息归纳在元素内部,抛弃了元素间直接的关联和包含关系,而我们在解析过程中需要实现的就是恢复元素之间的关联和包含关系。类图中的层次关系包括:Class和Interface下直接管理Attribute和Operation,Operation下直接管理Parameter;Class和Interface之间存在Generalization、InterfaceRealization以及Association的联系,其中Association存在特殊的AssociationEnd结构。在第一次作业中我的主要设计思想为,为需要管理下级结构的元素进行单独封装,有层次地管理各个元素的存储位置以方便查询。类图如下:

第二次作业新增了两大方面的功能,一是对类图元素间关系三个方面的检查,二是新增了状态图和顺序图的解析和查询。在理解UML以及第一次作业经验的基础上,第二方面的新增功能反而并不困难,仍然采用了第一次作业的思想,对于需要管理下级元素的元素进行封装,而第一方面功能则需要对第一次作业进行动作不小的拓展。

对于状态图,StateMachine下直接管理Region,Region下直接管理了各个State和Transition,而这次作业经过化简后保证只有一层Region,这使得StateMachine和Region处于一一对应的情况。对于顺序图,Interaction下管理了Lifeline和Message。从结构的复杂程度和需求的复杂程度而言,状态图和顺序图都不如第一次作业的类图复杂,而本次新增的对类图的检查功能使得扩展类图的需求更复杂。首先检查一个Class中Attribute和所对应的AssociationEnd是否同名,这个检查在我看来没有任何实际意义,徒增了我封装的Class类中需要储存的信息量,需要将本不需要存储的AssociationEnd也存在它关联对端的Class中;其次是检查循环继承,第三是检查重复继承,这两项检查都是图结构中的操作,我再第一次作业中使用了深搜实现了对Class和Interface的父类或父接口的查询,而这次为了应对更复杂的图结构,我单独开发了Graph类来管理拥有图结构的元素关系,包括为Class、Interface和State建立图结构,将对父元素的查询功能封装在图中实现,一来降低耦合度,二来封装后可以通过更快的静态数组来加速图计算。

此外,本次作业由于封装的类众多,我才用了package来管理各个类,不至于在开发的时候显得混乱。作业package结构和类图如下:

 

在两次作业中我也总结了UML结构间的层次关系如下:

UML 类图、顺序图和状态图元素层次关系

 

UML 类图( MODEL_SUBSET


所包含元素:(引用自官方包源码)

        this.add(ElementType.UML_CLASS);
       this.add(ElementType.UML_ASSOCIATION);
       this.add(ElementType.UML_ASSOCIATION_END);
       this.add(ElementType.UML_ATTRIBUTE);
       this.add(ElementType.UML_OPERATION);
       this.add(ElementType.UML_PARAMETER);
       this.add(ElementType.UML_GENERALIZATION);
       this.add(ElementType.UML_INTERFACE_REALIZATION);
       this.add(ElementType.UML_INTERFACE);
UmlClass (LEVEL_1)

· _id 对应的是类的 id

· _type 对应的是该标签的类型,在这里对应的是类 UML_CLASS

· _parent 对应的是父类的id,如果是顶层父类,对应的是 UmlModel 的 id

· name 对应的是类的名字

· visibility 对应的是类的可见性

UmlAssociation (LEVEL_2)

· _id 对应的是关联的 id

· _type 对应的是该标签的类型,在这里对应的是关联 UML_ASSOCIATION

· _parent 对应的是相互关联的两个类中的其中一个的 id

· name 对应的是关联名称

· end1 对应的是其中一个 UmlAssociationEnd 的 id

· end2 对应的是另一个 UMLAssociationEnd 的 id

UmlAssociationEnd (LEVEL_3)

· _id 对应的是关联端的 id

· _type 对应的是该标签的类型,在这里对应的是关联端 UML_ASSOCIATION_END

· _parent 对应的是所在的关联的 id

· name 是该关联端的名称

· reference 对应的是该 UmlAssociationEnd 所对应的类的 id

· multiplicity 对应的是该关联端对应的个数(Unused)

· visibility 对应的是该关联端的可见性(Unused)

· aggregation 由于本次作业没用到,单纯根据英文的话是聚合(Unused)

UmlAttribute (LEVEL_2)

· _id 对应的是属性的 id

· _type 对应的是该标签的类型,在这里对应的是属性 UML_ATTRIBUTE

· _parent 对应的是所在类的 id

· name 是该属性的名称

· visibility 对应的是该属性的可见性

· type 是该属性的变量类型(比如 int double )(Unused)

UmlOperation (LEVEL_2)

· _id 对应的是该操作的 id

· _type 对应的是该标签的类型,在这里对应的是操作 UML_OPERATION

· _parent 对应的是所在类的 id

· name 是该操作的名称

· visibility 对应的是该操作的可见性

UmlParameter (LEVEL_3)

· _id 对应的是参量的 id

· _type 对应的是该标签的类型,在这里对应的是参量 UML_PARAMETER

· _parent 对应的是所在操作的 id

· name 是该参量的名称

· type 对应的是该参量的变量类型(比如 int double

· direction 对应的是该参量的传递方向,指的是传入参数或返回值

UmlGeneralization (LEVEL_2)

· _id 对应的是继承关系的 id

· _type 对应的是该标签的类型,在这里对应的是继承关系 UML_GENERALIZATION

· _parent 对应的是继承关系中子类的 id

· name 是该继承关系的名称

· source 对应的是该继承关系所对应子类的 id

· target 对应的是该继承关系所对应父类的 id

UmlInterface (LEVEL_1)

· _id 对应的是接口的 id

· _type 对应的是该标签的类型,在这里对应的是接口 UML_INTERFACE

· _parent 对应的是父接口的id,如果是顶层父接口,对应的是 UmlModel 的 id

· name 对应的是接口的名字

· visibility 对应的是接口的可见性

UmlInterfaceRealization (LEVEL_2)

· _id 对应的是接口实现关系的 id

· _type 对应的是该标签的类型,在这里对应的是接口实现关系 UML_INTERFACE_REALIZATION

· _parent 对应的是接口实现关系中实现接口的类的 id

· name 是该接口实现关系的名称

· source 对应的是该接口实现关系所对应实现接口的类的 id

· target 对应的是该接口实现关系所对应接口的 id

 

UML 状态图( STATE_MACHINE_SUBSET


所包含元素:(引用自官方包源码)

        this.add(ElementType.UML_STATE_MACHINE);
       this.add(ElementType.UML_REGION);
       this.add(ElementType.UML_STATE);
       this.add(ElementType.UML_PSEUDOSTATE);
       this.add(ElementType.UML_FINAL_STATE);
       this.add(ElementType.UML_TRANSITION);
       this.add(ElementType.UML_EVENT);
       this.add(ElementType.UML_OPAQUE_BEHAVIOR);
UmlStateMachine (LEVEL_1)

· _id 对应的是状态图的 id

· _type 对应的是该标签的类型,在这里对应的是状态图 UML_STATE_MACHINE

· _parent 对应的是其上级组织的 id

· name 对应的是状态图的名字

UmlRegion (LEVEL_1)

· _id 对应的是区域的 id

· _type 对应的是该标签的类型,在这里对应的是区域 UML_REGION

· _parent 对应的是所属状态图的 id

· name 对应的是区域的名字

· visibility 对应的是区域的可见性(Unused)

UmlStateUmlPseudoStateUmlFinalState (LEVEL_2)

· _id 对应的是状态的 id

· _type 对应的是该标签的类型,在这里对应的是状态 UmlStateUmlPseudoStateUmlFinalState

· _parent 对应的是所属区域的 id

· name 对应的是状态的名字

· visibility 对应的是状态的可见性(Unused)

UmlTransition (LEVEL_3)

· _id 对应的是状态转移的 id

· _type 对应的是该标签的类型,在这里对应的是状态转移 UML_TRANSITION

· _parent 对应的是所属区域的 id

· name 对应的是状态转移的名字

· source 对应的是该状态转移所对应原装态的 id

· target 对应的是该状态转移所对应转移后状态的 id

· visibility 对应的是状态转移的可见性(Unused)

· guard 对应的是状态转移发生的条件(Unused)

UmlEventUmlOpaqueBehavior(LEVEL_3)(Unused)

· _id 对应是该元素的 id

· _type 对应的是该标签的类型,在这里对应的是UmlEventUmlOpaqueBehavior

· _parent 对应的是所属状态转移的 id

· name 对应的是元素的名字

 

UML 顺序图( COLLABORATION_SUBSET


所包含元素:(引用自官方包源码)

        this.add(ElementType.UML_ATTRIBUTE);
       this.add(ElementType.UML_INTERACTION);
       this.add(ElementType.UML_LIFELINE);
       this.add(ElementType.UML_MESSAGE);
       this.add(ElementType.UML_ENDPOINT);
UmlAttribute (LEVEL_2)

· _id 对应的是属性的 id

· _type 对应的是该标签的类型,在这里对应的是属性 UML_ATTRIBUTE

· _parent 对应的是所在顺序图的 id(此处的属性和交互同级)

· name 是该属性的名称

· visibility 对应的是该属性的可见性

UmlInteraction (LEVEL_1)

· _id 对应的是交互的 id

· _type 对应的是该标签的类型,在这里对应的是属性 UML_INTERACTION

· _parent 对应的是所在顺序图的 id(此处的属性和交互同级)

· name 是该交互的名称

UmlLifeline (LEVEL_2)

· _id 对应的是生命线的 id

· _type 对应的是该标签的类型,在这里对应的是属性 UML_LIFELINE

· _parent 对应的是所属交互的 id

· name 是该生命线的名称

· isMultiInstance 对应的是该生命线是否多实例化(Unused)

UmlMessage (LEVEL_3)

· _id 对应的是通信的 id

· _type 对应的是该标签的类型,在这里对应的是通信 UML_MESSAGE

· _parent 对应的是所属交互的 id

· name 对应的是该通信的名字

· source 对应的是该通信所对应源生命线的 id

· target 对应的是该通信所对应目标生命线的 id

· visibility 对应的是通信的可见性(Unused)

· MessageSort 对应的是通信的种类(Unused)

UmlEndpoint (LEVEL_3)(Unused)

· _id 对应结束点的 id

· _type 对应的是该标签的类型,在这里对应的是结束点 UML_ENDPOINT

· _parent 对应的是所属交互的 id

· name 对应的是结束点的名字

 

二、总结自己在四个单元中架构设计及OO方法理解的演进

OO这门课确实通过project让我对面向对象思想有了比较好的了解。从寒假到暑假这接近半年的时间,虽然历经坎坷,但我对这门课的理解已经从Java课进化到了面向对象课,从半年前的一Main到底,到现在使用package结构,使用继承来分层管理数据,完成工程化开发,确实是收获了很多。总体来说,我的收获和实践属于“慢半拍”的节奏,一个单元结束了我才稍微理解了这个单元的思想。

第一单元的表达式求导,三次project的前两次我都是一Main到底,第三次分了不同的类来进行计算,但本质上还是面向过程的计算拆分,类与类之间耦合度高的可怕,继承和接口实现更是没用上。第二单元的多线程,直到三次作业全部完成,结合操作系统课程对进程和线程的讲解,我才对多线程思想略有一些认识,而三次多线程作业无不是遇见共享就加锁,对于电梯调度的算法也没有什么深入的研究。第三单元主要在于单元测试和自动化测试的训练,但作业的要求却让我们陷入了数据结构和图计算的深渊,三次作业费尽心思使图计算时间更短,而直到第三单元的博客作业,看着自己一无所知的自动化测试内容,我才勉强实现了使用Junit自行编写随机数据单元测试。第四单元UML模型的理解对于我来说有了很大的好转,在前面所有作业的基础上我明白了什么是继承和接口,什么是多线程,什么是单元测试,什么叫做面向对象,什么叫做用面向对象的思想管理数据。最后一次作业我写了很久,想方设法降低代码耦合度,拆分功能,提高代码复用率,在封装越来越多的时候使用package来管理代码,在我个人看来实现了一个像模像样的工程化代码。

总体来说,虽然每次都是慢半拍,不过好在都顺利完成了project任务,也在最后一次实现了一些学到的思想,我对自己这门课的收获总体来说是满意的。

 

三、总结自己在四个单元中测试理解与实践的演进

对于测试的理解和实践,如同上面所说对OO方法的理解一样,我同样处于一个“慢半拍”的状态。第一单元大家都在编写随机测试的时候我还停留在手动构造数据测试的水平。当第二单元多线程来临时我更是手足无措,多线程的测试本身需要运用多线程,而我对于测试和多线程都处于一知半解的状态,整个第二单元我几乎处于一个没有测试的状态。第三单元主要介绍JML和Junit,但直到第三次博客作业我才勉强用Junit写出了单元随机测试,也没能实现自动化测试。第四单元我又将大部分精力放在了架构设计上,测试也是马马虎虎。

总体来说我对于程序的测试做的是很不够的,最多的进度也不过是实现了Junit框架随机数据单元测试。不过通过上课、研讨课和企业研讨课的讲解,我对测试的方法和测试的重要性有了一定的认识。如果在实际工程开发中测试作为一块相对独立的工作进行开发,我想我也能够根据各种测试思想进行有效地搭建。

 

四、总结自己的课程收获
第一单元:

熟悉了Java语言,了解了面向对象与面向过程的区别,锻炼了编写较复杂代码的能力。

第二单元:

了解了多线程思想和实现,锻炼了多线程编程思维,进一步运用面向对象思想解决复杂算法问题。

第三单元:

学习了JML语言和规格的作用,具备了测试和功能安全思想,另一方面也复习了图结构和相关计算算法,进一步使用面向对象思想管理图结构,学会优化面向对象的算法。

第四单元:

学习了UML模型,了解了类图、顺序图和状态图的作用和建模方法,学会用UML模型管理和规划工程代码。另外,第四单元是前三单元的集大成,将前面各个单元作业没能很好地实现的思想一一实现,也是前三个单元的复习和总结。至此我拥有了编写较为成熟的工程化代码能力。

整个OO课程我收获很多,除了编程能力之外,我还在其中锻炼了坚韧不拔的意志和耐挫力。面对我不能理解的知识,面对一次次调试失败和强测挂点,抱怨和失落都是没有用的,唯有脚踏实地,一点点尝试一点点实现,才是编程能力进步的根本。

 

五、立足于自己的体会给课程提三个具体改进建议

第一点建议:上课与上机之间适当给予更长的时间。对于我个人而言,上课讲解的知识点往往很难立马理解融会贯通,加上面向对象课程都在讲解比较思想性的内容,所举的代码例子也需要更多时间阅读,通常我都需要通过反复阅读课件和编码实践才能理解这些思想,而上午上完课下午直接上机的安排对我个人而言相当不友好,可以说这学期所有的上机我都是很狼狈的。希望课程组考虑一下我这类需要课下较多时间消化的学生,给上课和上机之间多一些时间。

第二点建议:适当减少每个互测屋的人数。以我个人的经验,这几次有互测环节的project,我几乎没有一次是完整地读了七份代码。在互测环节有限的时间里我们还有别的课程、作业和活动要做,一旦要求复杂,阅读七份代码在时间和精力上是不现实的。

第三点建议:尽量不要朝令夕改。最后一次作业的改需求和改测试点风波确实在整个年级造成了很不好的影响,从我个人看来首先是指导书发布时需求就没有写明确,另外改测试点的操作实在是对人打击很大。除了最后一次作业之外,前面多次作业出现了改指导书、改时间线等操作。抛开技术问题,抛开教学任务和实际情况来说,随意更改已有的规定是非常不明智的做法,希望新一届助教团队能够重视这一点。

还有一点额外的小建议,对于整个六系的课程设计类课程而言,我认为助教的责任和权力过大了,助教仅仅是比我们大一届的学长,他们有更强的能力这没有人否认,但他们是否有权力决定我们的成绩,甚至决定课程的发展走向这里要打一个问号了,他们也许是优秀的工程师,但不一定是优秀的教师和优秀的管理者,甚至在学期中还出现了多次助教和学生的冲突。我认为老师们应该在课程中承担更多的责任,在必要的时候站出来向同学们解释课程组做决定做变动的原因。助教没有责任也没有资格把学院的教学方向扛在肩上。

posted @ 2019-06-24 20:39  走肖暂时无法接通  阅读(499)  评论(0编辑  收藏  举报