BUAA_OO_Summary_StageFour
OO第四单元博客总结
本单元三次作业的架构设计总结
前两次作业主要是完成了对uml核心图中类图、顺序图、状态图的解析
给出由mdj文件解析而来的关键元素表,由我们从零散的信息中找出联系,复原uml模型图,检查并实现相关的统计查询功能。
第一次作业
关于第一次作业给出的元素各属性及框架结构,参考某学长博客
//level 1
UmlClass
_id 对应的是类的 id
_type 对应的是该标签的类型,在这里对应的是类 UML_CLASS
_parent 对应的是父类的id,如果是顶层父类,对应的是 UmlModel 的 id
name 对应的是类的名字
visibility 对应的是类的可见性
UmlInterface
_id 对应的是接口的 id
_type 对应的是该标签的类型,在这里对应的是接口 UML_INTERFACE
_parent 对应的是父接口的id,如果是顶层父接口,对应的是 UmlModel 的 id
name 对应的是接口的名字
visibility 对应的是接口的可见性
//level 2
UmlAttribute
_id 对应的是属性的 id
_type 对应的是该标签的类型,在这里对应的是属性 UML_ATTRIBUTE
_parent 对应的是所在类的 id
name 是该属性的名称
visibility 对应的是该属性的可见性
type 是该属性的变量类型
UmlOperation
_id 对应的是该操作的 id
_type 对应的是该标签的类型,在这里对应的是操作 UML_OPERATION
_parent 对应的是所在类的 id
name 是该操作的名称
visibility 对应的是该操作的可见性
UmlGeneralization
_id 对应的是继承关系的 id
_type 对应的是该标签的类型,在这里对应的是继承关系 UML_GENERALIZATION
_parent 对应的是继承关系中子类的 id
name 是该继承关系的名称
source 对应的是该继承关系所对应子类的 id
target 对应的是该继承关系所对应父类的 id
UmlInterfaceRealization
_id 对应的是接口实现关系的 id
_type 对应的是该标签的类型,在这里对应的是接口实现关系 UML_INTERFACE_REALIZATION
_parent 对应的是接口实现关系中实现接口的类的 id
name 是该接口实现关系的名称
source 对应的是该接口实现关系所对应实现接口的类的 id
target 对应的是该接口实现关系所对应接口的 id
UmlAssociation
_id 对应的是关联的 id
_type 对应的是该标签的类型,在这里对应的是关联 UML_ASSOCIATION
_parent 对应的是相互关联的两个类中的其中一个的 id
name 对应的是关联名称
end1 对应的是其中一个 UmlAssociationEnd 的 id
end2 对应的是另一个 UMLAssociationEnd 的 id
//level3
UmlAssociationEnd
_id 对应的是关联端的 id
_type 对应的是该标签的类型,在这里对应的是关联端 UML_ASSOCIATION_END
_parent 对应的是所在的关联的 id
name 是该关联端的名称
reference 对应的是该 UmlAssociationEnd 所对应的类的 id
UmlParameter
_id 对应的是参量的 id
_type 对应的是该标签的类型,在这里对应的是参量 UML_PARAMETER
_parent 对应的是所在操作的 id
name 是该参量的名称
type 对应的是变量类型
direction 对应的是该参量的传递方向,指的是传入参数或返回值
-
第一次作业只需要支持对类图的解析,个人考虑在初始化类的时候进行uml图的联系的存储和简单的类的搭建。
-
存储方式:实现
MyUmlClass
类和MyUmlOperation
类-
每个MyUmlClass
类记录了uml图中的一个类,其中属性是提供的UmlClass
类,该类下的所有operation和所有attributeprivate UmlClass umlClass; private ArrayList<UmlAttribute> attributes; private ArrayList<MyUmlOperation> operations;
-
MyUmlOperation
类存放方法,其中属性是提供的UmlOperation
类,该方法的所有参数,以及该方法的的参数特征(即统计该方法是有无参数传入和有无返回值)private UmlOperation operation; private boolean[] para = {false, true, false, true};//有参数传入,无参数传入,有返回值,无返回值 private ArrayList<UmlParameter> parameters;
-
-
在要实现的类中添加如下属性
private HashMap<ElementType, ArrayList<UmlElement>> elements = new HashMap<>();//按类存放所有元素 private HashMap<String, UmlElement> umlElementHashMap = new HashMap<>(512);//存放每个id索引element private HashMap<String, MyUmlClass> classHashMap = new HashMap<>();//索引MyUmlClass private HashMap<String, MyUmlOperation> operationHashMap = new HashMap<>();//索引MyUmlOperation
-
其中关于类与类,类与接口,接口与接口之间的关系,并没有在实现的两个类中记录,是因为考虑到实际在uml图中实现的时候,一个uml类的方框中不会记录这些关系,所以本人也将这些关系记录在了需要实现的目标类
MyUmlInteraction
中,没有做其他操作。
第二次作业
第二次作业新增状态图和顺序图
关于第二次作业新增的元素各属性及框架结构,仍参考某学长博客
//状态图
//Level1
UmlStateMachine
_id 对应的是状态图的 id
_type 对应的是该标签的类型,在这里对应的是状态图 UML_STATE_MACHINE
_parent 对应的是其上级组织的 id
name 对应的是状态图的名字
UmlRegion
_id 对应的是区域的 id
_type 对应的是该标签的类型,在这里对应的是区域 UML_REGION
_parent 对应的是所属状态图的 id
name 对应的是区域的名字
visibility 对应的是区域的可见性(Unused)
//Level2
UmlState
_id 对应的是状态的 id
_type 对应的是该标签的类型,在这里对应的是状态 UmlState 、 UmlPseudoState 或 UmlFinalState
_parent 对应的是所属区域的 id
name 对应的是状态的名字
visibility 对应的是状态的可见性(Unused)
UmlPseudoState
_id 对应的是状态的 id
_type 对应的是该标签的类型,在这里对应的是状态 UmlState 、 UmlPseudoState 或 UmlFinalState
_parent 对应的是所属区域的 id
name 对应的是状态的名字
visibility 对应的是状态的可见性(Unused)
UmlFinalState
_id 对应的是状态的 id
_type 对应的是该标签的类型,在这里对应的是状态 UmlState 、 UmlPseudoState 或 UmlFinalState
_parent 对应的是所属区域的 id
name 对应的是状态的名字
visibility 对应的是状态的可见性(Unused)
//Level3
UmlTransition
_id 对应的是状态转移的 id
_type 对应的是该标签的类型,在这里对应的是状态转移 UML_TRANSITION
_parent 对应的是所属区域的 id
name 对应的是状态转移的名字
source 对应的是该状态转移所对应原装态的 id
target 对应的是该状态转移所对应转移后状态的 id
visibility 对应的是状态转移的可见性(Unused)
guard 对应的是状态转移发生的条件(Unused)
UmlEvent(Unused)
ame 对应的是元素的名字
UmlOpaqueBehavior(Unused)
_id 对应是该元素的 id
_type 对应的是该标签的类型,在这里对应的是UmlEvent 或 UmlOpaqueBehavior
_parent 对应的是所属状态转移的 id
name 对应的是元素的名字
//顺序图
//Level1
UmlInteraction
_id 对应的是交互的 id
_type 对应的是该标签的类型,在这里对应的是属性 UML_INTERACTION
_parent 对应的是所在顺序图的 id(此处的属性和交互同级)
name 是该交互的名称
//Level2
UmlLifeline
_id 对应的是生命线的 id
_type 对应的是该标签的类型,在这里对应的是属性 UML_LIFELINE
_parent 对应的是所属交互的 id
name 是该生命线的名称
isMultiInstance 对应的是该生命线是否多实例化(Unused)
//Level3
UmlMessage
_id 对应的是通信的 id
_type 对应的是该标签的类型,在这里对应的是通信 UML_MESSAGE
_parent 对应的是所属交互的 id
name 对应的是该通信的名字
source 对应的是该通信所对应源生命线的 id
target 对应的是该通信所对应目标生命线的 id
visibility 对应的是通信的可见性(Unused)
MessageSort 对应的是通信的种类(Unused)
UmlEndpoint(Unused)
_id 对应结束点的 id
_type 对应的是该标签的类型,在这里对应的是结束点 UML_ENDPOINT
_parent 对应的是所属交互的 id
name 对应的是结束点的名字
-
存储方式:
-
顺序图通过
MyUmlInteraction
类进行存储,类中属性包括:private UmlInteraction umlInteraction; private ArrayList<UmlLifeline> lifelines; private ArrayList<UmlMessage> messages; private ArrayList<UmlEndpoint> endpoints;
-
状态图按层次依次进行存储,最上层
MyUmlStateMachine
类中属性包括:private UmlStateMachine stateMachine; private MyUmlRegion region;
第二层
MyUmlRegion
类中属性包括:private UmlRegion region; private UmlPseudostate pseudostate; private UmlFinalState finalState; private ArrayList<MyUmlState> states; private ArrayList<MyUmlTransition> transitions;
第三层
MYUmlState
和MyUmlTransition
类中属性分别包括://MyUmlState private UmlState state; private ArrayList<UmlOpaqueBehavior> opaqueBehaviors; //MyUmlTransition private UmlTransition transition; private ArrayList<UmlOpaqueBehavior> opaqueBehaviors;
-
第三次作业
第三次作业是在前两次作业前加上对uml图的一些条件的检验,总共八个检查方法
由于在前两次作业中比较好的对每种图进行了存储,也建立了新的类进行存储,因此八个方法也基本上比较好实现。
基本上最难的也就是对将class和interface当成图上的点来使用,在类中将继承关系和实现关系进行记录即可,对图进行一些dfs、bfs也非常方便,在此就不赘述了
四个单元中架构设计及OO方法理解的演进总结
-
第一单元——表达式求导,我按照因子的类别建立相应的类来存储,并且建立了抽象父类
Factor
,并对每个因子都覆写求导方法,总的来说算是比较好的完成了作业的要求,尽管第二次作业直接重构,但是第三次作业稍微的实现了部分的迭代开发的思想。 -
第二单元——电梯多线程,这一单元迭代开发实现的比较好,基本上都能够直接延用上次的代码,可惜在最后一次作业中还是出现了线程安全的问题。对调度的管理上划算比较合理,调度器与电梯分离,调度器考虑将请求分配给哪个电梯,每个电梯只需完成本单元第一作业的工作即可,这样可以方便的改变单个电梯的调度策略,或者调度器的调度策略,也有了一些层次化、模块化的思想。这个单元还是很考察各类的设计能力的,对于共享变量的共享,各线程之间的合作需要有一个合理的设计,尽管写的时候没有太多的修改重复,但是早就听过OO课的电梯难题,其实是在设计上花了不少的功夫的。
-
第三单元——JML,这一单元的架构几乎是按照官方代码来走的,所需要做的只是建立必要的存储容器进行缓存,在本单元最后一次作业中,才出现了一些需要略微考虑到算法的方法。但是JML万万不可直接对着JML的要求低头狂写,JML只是提供对你代码的要求而不是你的实现,代码的实现还是需要总览全部需要实现的方法对每个类都进行认真的设计。这一单元通过对规格的进一步认识,对于面向对象的理解也是在逐渐加深,也更加的注重一些细节。
-
第四单元——UML,这一单元的架构是按照uml元素的层次关系构建的,使得元素间建立由高到低的存储关系。这一单元其实我认为是比较考察设计的层次性与逻辑的,它将所有元素拆开并将两两之间的关系给你,需要你通过本身对UML的理解,将所有元素放回原位,这一单元的作业非常巧妙,既加深了你对UML模型化的理解,同时在面向对象的设计思想中也让你对这些对象的抽象、分析、组合能力有了较大的提升。
-
总的来说,所实现的代码越来越有层次和逻辑了,有一定的扩展能力,初步达到了迭代开发的要求。在慢慢的向我们想达到的方向发展——尽可能是以轻量级的调整算法来改变,而不是重量级的调整架构。
四个单元中测试理解与实践的演进总结
除了第四个单元的uml图实在不知道怎么测试只能通过手动画图转为数据进行普通的测试之外,前三个单元都是通过手动构造边缘数据+评测机大量随机数据来测试的。
但是自己写的评测机难免会出现一些问题,比如因为电脑问题导致测试数据量不够大或者测试不够全面(例如第二单元的多线程bug不可再现或者bug出现的可能性极端小在自己的评测机的样例数目等级上发现不了,或者第三单元忘记构造一些极端数据检查是否超时),而这些都造成了我互测中被hack出了bug,只有第一单元是无伤过真的是呜呜呜=_=
个人认为针对多线程来说,线程安全问题确实是无法有效检查出来的错误,需要在设计时多加思考,写代码时多加思考,测试时多加思考,总之就是要疯狂思考各种执行顺序,即使有一种情况会造成安全问题那么这个设计都是不通过的。
除此之外,对于有性能要求的代码,要尽量多的手动构造极端数据,并对该方法进行大量重复测试,对于这种有性能要求的代码一般无非是采取缓存,标记和对算法进行改进的方法。
课程收获总结
第一单元主要是学习了什么是面向对象,是对OO入门的过程,将自己从面向过程编程的思维定式中释放,掌握了常用的容器以及正则表达式(香是真的香,爆栈就很惨了)的相关知识
第二单元引入多线程,学习了多线程的相关知识,在实际作业中对生产者消费者模式有了较为深刻的理解,但是线程安全问题导致的玄学debug我真的吐了
第三单元则学习了JML相关的知识,领略了规格化开发,也不知道必不必要的学了一波Tarjan算法,但是一定要注意的是即便有了JML我们还是需要认真的进行架构设计,盲目实现JML是最不可取的
第四单元,学习了UML模型,学到了UML中各种元素的组成及每部分的意义。UML对于以后的代码设计及理解还是用处很大的。没有好的测试方法就认真联系了一波小黄鸭测试法,仔细检查肉眼debug
OO的课程是非常算是非常系统、完善的一门课程,并且自由度非常大,在你的实现过程中,每个人都有着不同的设计思路,但是在各种各样的设计中,每个人都在向着面向对象的思路去靠拢。
总的来说,OO课还是令人受益匪浅的,如今每次代码前都会仔细思考设计架构,考虑中其中的可扩展性和层次与结构是否清晰合理,我认为还是有所进步的。并且我充分了解了测试的重要性,后两单元出现的bug都是由于对自己程序测试不充分导致出现被hack。了解了java的需要多设计模式,如工厂模式、观察者模式等,可惜还没啥机会付诸实践,但是了解了这些设计模式能帮助我在项目中读代码,能更好地理解别人的代码并且思维上更开拓了。
立足于自己的体会给课程提三个具体改进建议
-
感觉上课内容很多时候跟作业关系没有那么大,课程相对讲得比较深入,我认为有时先从贴近作业的角度入手会比较好。感觉可以在课上多增加一些代码实现的事例,可以使得同学们更好的理解
-
不是很明白实验课的意义在何处,感觉实验课时间还是过于的短,在实验课上理解代码时间还是稍显仓促;为了实验课学习的设计模式等仅在实验课上仓促实践感觉也没有太深的领悟,效果不是那么好;并且感觉OO本身就有多次作业和课堂检测计入成绩,好像不必要需要实验课成绩
-
感觉互测有点失去本来的意义了,互测本应该是认真学习他人代码,但是6-8人一屋的结果导致了同学们拿着手写评测机,讲重点放在测试而不是相互学习上
线上学习OO课程的体会
由于疫情的原因,导致只能线上学习OO,所幸这门课本身自学成分居多,也并没有影响到教学质量,甚至感觉线上也非常不错,虽然与老师同学不方便面对面讨论,但是夜深人静的时候一个人专心揣摩设计、敲代码、debug也是非常不错的体验。
尽管只能线上讨论,但是同学们和助教们的积极性都非常高,OO作为一门以作业为重点的课程,压力都在平时,同学之间的讨论也带给了我非常大的帮助。