BUAA_OO第四单元总结
BUAA_OO第四单元总结
架构设计
第一次作业
第一次作业主要是针对对类图信息的查询。首先,由于\(UmlElement[]\)中信息并不按顺序,即一条信息的父节点并不一定下标小于此条信息。因此我进行了多次循环遍历\(UmlElement[]\),在每次循环遍历的过程中获得相应类别的UmlElement。
在建立各类类别的UmlElement的联系过程中,我主要是考虑了各类UmlElement的父节点的类别和查询类图信息指令的情况,采用了一下的结构:
- UmlClass
- UmlAttribute(s)
- UmlOperation(s)
- UmlParameter(s)
- UmlAssociation(s)
- UmlInterface(s)
- UmlClass(父类)
- UmlInterface
- UmlOperation(s)
- UmlParameter(s)
- UmlInterface(s)(父类)
- UmlOperation(s)
此外,为了建图时查询父节点的id方便,我多数采用了以其id作为key,其本身作为value的HasMap结构,例如HashMap<String, MyClass> classes和HashMap<String, MyInterface> interfaces,那么在UmlClass和UmlInterface下的节点在建图时便可以通过以父节点id作为索引进行查询,较为方便。
第二次作业
第二次作业增加了对状态图和顺序图的信息查询。设计思路与第一次作业相似,以各类UmlElement的父节点的类别和查询类图信息指令的情况作为切入点,我采取了以下架构:
状态图:
- UmlStateMachine
- UmlRegion
- UmlElement(s)(UmlPseudostate/ UmlFinalState/ UmlState)
- UmlElement(s)(UmlPseudostate/ UmlFinalState/ UmlState)(直接后继)
- UmlTransition(s)
- UmlEvent(s)
状态图比较困难的是\(getSubsequentStateCount\)和\(getTransitionTrigger\)。\(getSubsequentStateCount\)接口的实现主要通过每一个状态都存储了的直接后继状态实现,通过DFS进行对图的遍历(标记已经遍历过的点)获取所有遍历过的点即为所有可到达状态。\(getTransitionTrigger\)接口的实现主要是通过获取所有同名的UmlTransition,然后再获得其所有的UmlEvent,逻辑较为简单。
顺序图:
- UmlInteraction
- UmlLifeline(s)
- UmlMessage(s)(生命线接受的信息)
- UmlMessage(s)(生命线发送的信息)
- UmlLifeline(s)
顺序图的接口功能较为简单,在UmlLifeline下分类存储接受的信息和发送的信息即可。
此外,我还将MyUmlGeneralInteraction分成了三类:MyClassDiagramManagement、MyStateDiagramManagement和MySequenceDiagramManagement分别负责类图、状态图和顺序图的管理。
第三次作业
第三次作业为纠错,功能都较为简单,比较复杂的接口都可以通过DFS进行解决,比如循环继承可以通过DFS获得其所有的父继承然后判断其本身是否在里面;重复继承可以通过DFS,如果在遍历的过程中出现了重复则返回一个true,否则为false。
此外,纠错的接口我分别放置在了负责类图、状态图和顺序图的管理类里面。
四个单元中架构设计及OO方法理解的演进
第一单元
此单元是初识面向对象。现在回想起来,我对这个单元认识最深的应该是类的继承和多态的实现。采用二叉树的形式存储多项式,其中涉及的类包含加法表达式、乘法表达式、三角函数等等,所有的类都继承自抽象类Expression,并实现toString、求导等方法。求导方面,由于我采用了二叉树的结构,所以求导为递归调用即可。
在完成第三次作业以后,在与同学讨论以后,认为二叉树在长度优化方面比较困难,其一要进行许多的类判断(比如合并常数时要判断是否是Constant类,如果加式里其中之一是加式,又要进行对内加式的两个加式进行类型判断,极其困难),其二就是化简和换位置要进行树的遍历的操作。因此,二叉树结构在功能实现方面有比较大的优势,但在优化方面不够好。
第二单元
此单元是多线程的设计。我觉得难点主要是架构设计和线程安全设计,我的架构(第三次作业)主要为读取线程、调度器线程、多个电梯线程(电梯策略我使用了类似look的算法)和回收线程。读取线程负责读取乘客信息,传递给调度器;调度器线程负责分配此乘客至匹配度最高的电梯;回收线程负责把电梯送出的乘客回收至调度器(在调度器里进行进一步的查询:如果到达其目的楼层则将乘客移除,否则继续分配此乘客)。在此架构中,我一开始设计出现了环形死锁问题(有点像哲学家就餐问题),在与同学的讨论过后,我将流程比较简单的回收线程设置成了守护线程保证了线程资源之间不会成环。
第三单元
此单元是JML形式化描述的学习以及代码实现。我觉得这个单元是最为轻松的。只要按照阅读接口的规格,确定合适的容器,选择合适的算法这个流程实现每一个接口,基本都没有什么问题。比较坑的点我觉得是和\(queryBlockSum()\),可以通过并查集实现查询是否在于同一个连通块的操作,除此之外还有堆优化的迪杰斯特拉最短路径。
第四单元
第四单元的架构设计如上所示,其架构设计我主要从各类UmlElement的父节点的类别和查询类图信息指令的情况方面入手的,设计起来也较为方便。
四个单元中测试理解与实践的演进
第一单元
第一单元的测试主要是手动极限数据测试和评测机随机数据测试。评测机随机数据测试一般用于测试是否存在显而易见的bug,手动测试则采用不断嵌套函数、括号等方式测试程序的性能。
第二单元
第二单元的测试主要是手动构造(评测机的评测正确性并不会实现)。我仍记得在第三次作业中主要尝试了n个乘客从4楼到20楼的较为极端数据。
第三单元
第三单元的测试主要是针对某一个接口构造极限数据和与同学的对拍测试。与同学的对拍测试保证基本功能不会出错;针对某一个接口构造(例如围绕并查集和最短路径算法进行边界测试)主要测试TLE方面的问题。
第四单元
第四单元临近期末只在第三次作业中进行了对循环继承和重复继承/实现的手动数据构造测试。
总体上讲,我主要采用了
- 手动构造边界数据测试(针对编写时出现的思维惯性错误和程序性能不良)
- 测评机随机数据测试(主要测试出理解不当或实现不恰当的bug)
- 对拍测试(同上)
课程收获
经过此次面向对象课程,我个人感觉收获满满。
- 深化对面向对象的认识,更加关注各种类和类的功能,在编程时养成从各种类和类的功能的层面关注问题的思考方法。
- 习惯从程序的拓展性方面思考问题。多项式求导和电梯这两个单元的重构设计现在回顾过来仍然头皮发麻:往往都是在第二次作业中减少了对拓展性方面的思考而扑街。
- 学习了面向对象基本的继承、多态、接口等特征。每一个单元都有自己的主题:继承和多态、多线程、JML、UML,并且从零学习了Java语言的语法和使用,在后面的课程中逐渐熟悉了Java各种高效的操作。
立足于自己的体会给课程提三个具体改进建议
- 上机实验能否给出评测结果或者分数。
- 指导书方面希望可以更加准确一点(第一单元虽然形式化符号可以表达出可以出现三个符号,但是文字描述方面是不行的)
- 第四单元第一次作业可以给予更多的关于程序实现方面的提示(这个单元虽然较为简单,但是第一次作业我真的不知道要实现什么)。

浙公网安备 33010602011771号