OO第四单元总结 & 课程总结
2022北航OO第四单元总结暨课程总结
第四单元架构设计
本单元在理解UML图的基础上,实现对UML类图、顺序图和时序图的解析、指令查询和模型有效性检查。
实现思路
大致思路是先对UML模型进行解析,再实现指令查询的方法。
-
解析的思路是:在官方包中给定模型元素的基础上,根据需要实现自己的元素类,从上到下实现树形结构的模型。例如类元素应该包含属性、方法、父类和实现的接口等信息,但官方包UmlClass并不具备,因此在UmlClass的基础上实现MyClass类来包含这些信息。需要注意的是,解析时要遵循从上至下的原则,避免某些底层元素的上层属性还没有实现而无法解析。
-
查询的思路是:在已经解析好的模型基础上,依次实现接口中的方法。其中涉及到一些比较麻烦的查询指令要注意递归的合理实现,同时注意类似去重等细节。
架构图
- 类图
classDiagram
class MyClass
MyClass: -UmlClass umlClass
MyClass: -MyClass superClass
MyClass: -HashMap<String, UmlAttribute> id2attributes
MyClass: -HashMap<String, MyOperation> id2operations
MyClass: -HashMap<String, MyClass> childClasses
MyClass: -HashMapHashMap<String, MyInterface> implementsInterfaces
MyClass: +addAttribute(UmlAttribute attribute)void
MyClass: +addOperation(MyOperation operation)void
MyClass: +addChildClass(MyClass myClass)void
MyClass: +addImplementsInterface(MyInterface myInterface)void
MyClass: +getSubClassCount()int
MyClass: +getOperationCount()int
MyClass: +getOperationVisibility(String methodName)HashMap
MyClass: +getAttributeCouplingDegree(MyClass myClass, ArrayList<String> hasChecked)int
MyClass: +getOperationCouplingDegree(String methodName, MyClass myClass)List
MyClass: +operationWrongType(String methodName)boolean
MyClass: +operationDuplicate(String methodName)boolean
MyClass: +sameParaList(HashMap<String, Integer> list1, HashMap<String, Integer> list2)boolean
MyClass: +getImplementInterfaceList(HashMap<String, String> interfaceList)void
MyClass: +getDepthOfInheritance(int depth)int
class MyInterface
MyInterface: -UmlInterface umlInterface
MyInterface: -HashMap<String, MyInterface> superInterface
MyInterface: -HashMap<String, UmlAttribute> id2attributes
MyInterface: -HashMap<String, MyInterface> childInterfaces
MyInterface: -HashMap<String, MyClass> implementsClasses
MyInterface: +addAttribute(UmlAttribute attribute)void
MyInterface: +addSuperInterface(MyInterface myInterface)void
MyInterface: +addChildInterface(MyInterface myInterface)void
MyInterface: +addImplementsClasses(MyClass myClass)void
MyInterface: +getFatherInterfaces(HashMap<String, String> interfaceList)void
class MyOperation
MyOperation: -UmlOperation umlOperation
MyOperation: -HashMap<String, UmlParameter> id2parameters
MyOperation: +addParameter(UmlParameter umlParameter)void
class UmlAttribute
class UmlParameter
MyClass*--MyOperation
MyInterface*--MyOperation
MyInterface*--UmlAttribute
MyClass*--UmlAttribute
MyOperation*--UmlParameter
MyClass--MyInterface
- 时序图
classDiagram
class MyInteraction
MyInteraction: -UmlInteraction umlInteraction
MyInteraction: -HashMap<String, MyLifeline> id2lifeline
MyInteraction: -HashMap<String, MyEndpoint> id2endpoint
MyInteraction: +addLifeline(MyLifeline myLifeline)void
MyInteraction: +addEndpoint(MyEndpoint myEndpoint)void
MyInteraction: +getParticipantCount()int
MyInteraction: +lifelineNotFound(String lifelineName)boolean
MyInteraction: +duplicateLifeline(String lifelineName)boolean
MyInteraction: +neverCreate(String lifelineName)boolean
MyInteraction: +duplicateCreate(String lifelineName)boolean
MyInteraction: +getParticipantLostAndFound(String lifelineName)Pair
MyInteraction: +getParticipantCreator(String lifelineName)UmlLifeline
class MyLifeline
MyLifeline: -UmlLifeline umlLifeline
MyLifeline: -HashMap<String, MyMessage> sendMessage
MyLifeline: -HashMap<String, MyMessage> receiveMessage
MyLifeline: +addMessageSource(MyMessage myMessage)void
MyLifeline: +addMessageTarget(MyMessage myMessage)void
class MyMessage
MyMessage: -UmlMessage umlMessage
MyMessage: -MyLifeline sourceLifeline
MyMessage: -MyLifeline targetLifeline
MyMessage: -MyEndpoint sourceEndpoint
MyMessage: -MyEndpoint targetEndpoint
class MyEndpoint
MyEndpoint: -UmlEndpoint umlEndpoint
MyEndpoint: -HashMap<String, MyMessage> sendMessage
MyEndpoint: -HashMap<String, MyMessage> receiveMessage
MyEndpoint: +addMessageSource(MyMessage myMessage)void
MyEndpoint: +addMessageTarget(MyMessage myMessage)void
MyInteraction*--MyLifeline
MyInteraction*--MyEndpoint
MyLifeline*--MyMessage
MyEndpoint*--MyMessage
- 状态图
classDiagram
class MyStateMachine
MyStateMachine: -UmlStateMachine umlStateMachine
MyStateMachine: -MyRegion region
MyStateMachine: +addRegion(MyRegion region)void
class MyRegion
MyRegion: -UmlRegion umlRegion
MyRegion: -HashMap<String, MyState> id2states
MyRegion: -MyInitialState initialSate
MyRegion: -HashMap<String, MyFinalState> id2finalStates
MyRegion: -HashMap<String, MyTransition> id2transitions
MyRegion: +addState(MyState myState)void
MyRegion: +setInitialSate(MyInitialState initialSate)void
MyRegion: +addFinalState(MyFinalState myFinalState)void
MyRegion: +addTransition(MyTransition myTransition)void
MyRegion: +isState(String id)boolean
MyRegion: +isInitialState(String id)boolean
MyRegion: +isFinalState(String id)boolean
MyRegion: +findRoot(String id)ArrayList
MyRegion: +findTmpRoot(String id)ArrayList
MyRegion: +addRoots(String sourceId, String targetId)void
MyRegion: +addTmpRoots(String sourceId, String targetId)void
MyRegion: +getStateCount()int
MyRegion: +stateNotFound(String stateName)boolean
MyRegion: +duplicateState(String stateName)boolean
MyRegion: +noTransition(String sourceName, String targetName)boolean
MyRegion: +getTransitionTrigger(String sourceName, String targetName)List
MyRegion: +isAllCircle()boolean
MyRegion: +getStateIsCriticalPoint(String stateName)boolean
class MyTransition
MyTransition: -UmlTransition umlTransition
MyTransition: -ArrayList<UmlEvent> events
MyTransition: +addEvent(UmlEvent umlEvent)void
class UmlEvent
class MyInitialState
MyInitialState: -UmlPseudostate umlPseudostate
class MyFinalState
MyFinalState: -UmlFinalState umlFinalState
MyFinalState: -ArrayList<String> rootsId
MyFinalState: -ArrayList<String> tmpRootsId
MyFinalState: +addRoot(String newRootId)void
MyFinalState: +addTmpRoot(String newRootId)void
MyFinalState: +clearTmpRootsId()void
class MyState
MyState: -UmlState umlState
MyState: -ArrayList<String> rootsId
MyState: -ArrayList<String> tmpRootsId
MyState: +addRoot(String newRootId)void
MyState: +addTmpRoot(String newRootId)void
MyState: +clearTmpRootsId()void
MyStateMachine*--MyRegion
MyRegion*--MyTransition
MyRegion*--MyInitialState
MyRegion*--MyState
MyRegion*--MyFinalState
MyTransition*--UmlEvent
架构设计思维及OO方法理解的演进
- 第一单元是最痛苦的,三个星期的时间被OO折磨的生活失去光彩,三次作业也完成的勉勉强强,现在反思可能是预习阶段做的不够。但第一单元是从无到有建立OO思想和架构设计的重要一环。在这之前的程设课上代码量都不大,也没有架构设计的观念。但这一单元让我明白在敲代码前进行整体架构设计的重要性,同时要充分考虑代码的可扩展性,从而有效避免重构。同时在作业完成时根据题目要求着重如何实现对象,逐步摆脱之前面向过程的影子。但最终的架构实现也还是比较混乱。
- 第二单元印象最深,在面向对象的基础上着眼多线程这一重要功能的实现,从对多线程0了解到实现多线程安全交互的电梯,让我体会到了在多对象交互时线程安全的重要性与如何实现,同时对于CPU轮询问题的原因以及如何定位并解决也是从0到1的理解。这一单元的架构相比第一单元清晰了很多,三次作业依次迭代,完成的也比第一单元顺利了不少。
- 第三单元由于规格化的语言限制了架构,同时确保了没有二义性。本单元让我接触了JML规格化语言的阅读与应用。一开始也是一头雾水,但通过三次作业让我对JML规格语言,尤其是较复杂的JML的阅读理解有较大提升,对于复杂JML的阅读梳理出内层的几何含义,更有助于理解与代码的实现。同时让我意识到同一方法的具体实现具有多样性,如何高效的实现一个方法是本单元另一个重点。
- 第四单元以对UML图的解析和查询为重点,达到了解UML架构和实现的目的。一开始面对官方包中大量的代码和指导书简直不知所云,通过一点点阅读官方包及UML图的学习,我认为本单元的重点在于层次化的抽象,将UML图的不同元素按所属层次依次建模,从而更好的理解UML图的实质。
测试理解与实践的演进
测试是OO课程中很重要的一部分,是保证代码正确性的必要步骤。第一单元中几乎没有什么测试的观念,只是简单的构造几组数据,后来通过强测逐渐了解到课下自行测试的重要性,通过手动构造一些边界数据进行测试。第二单元多线程的不确定性导致测试有很大难度,主要都是针对可能出现的轮询进行测试。第三单元指令数据量较大且实现起来的细节很多,一粗心就容易出现问题,还很不好发现,通过和同学对拍可以快速的找出一些隐藏的问题。第四单元可以直接在StarUML中进行数据构造,主要针对每条指令一一进行测试,尤其是实现较复杂的指令是否会出现问题。
课程收获
- 首先是面向对象的程序设计思维和方法从无到有的建立。与之前的面向过程进行对比,更能理解OO的基本实现思路和应用场景,在面对问题时能够尝试用面向对象的思路进行分析并解决。
- 其次是每个单元重点涉及的知识点的掌握。包括多线程和线程安全的实现,契约式编程和复杂JML的阅读,还有UML图的理解及解析的实现等。
- 同时其它一些细节的收获。比如JAVA语法,通过四个单元一定量的代码开发从无到有掌握一门语言,也第一次接触并学会了使用git,在一个单元三次作业的完成过程中也体会到了项目的迭代开发等。最重要的是四个单元作业的完成是对自学能力的很大提升。
- 最后是不足,除去第三单元,其它都是第一次作业完成的比较好,第二次不如第一次,第三次又不如第二次。一方面可能由于第一次作业一般较简单,以及每单元一开始时总是信心满满的要好好完成,随着时间累加逐渐疲惫,单元结束时又觉得这单元终于熬过去了,最后一次作业也草草完成,感觉自己在整体的学习上缺少些始终如一的坚持。
三个具体改进建议
- 增长预习时间和预习程度
- 在OO前期,完成第一单元作业的时候感到很吃力。虽然寒假有预习任务,但只能帮助简单了解JAVA语法,预习的难度和第一单元的难度相比感觉相差有点大。寒假的时间较长,建议增长一些预习时间,同时增加一些关于递归下降等知识的预习。
- 调整上机实验的时间
- 上机实验是对课下作业有力支持,尤其是前两个单元,可以为作业提供很多思路,但安排在每周四导致上机时本次作业已经基本完成大致,即使有更好的方法也不好更改,或者是不能及时得到有效的思路导致前期花费大量时间走很多弯路。
- 指导书改进
- 指导书有时比较冗长,尤其是第四单元,在实现细节比较多的情况下很容易遗漏,可以把相关类信息进行集中叙述;以及虽然名字叫指导书但感觉更多还是叙述作业的题面及要求,对于作业的实现更多还是自己找资料自学,希望可以在指导书中增加更多“指导”内容的资料,比如一些有效的学习链接等,或直接增加到预习内容中。