BUAA_OO 第四单元总结
写在前面
UML是一种描述逻辑,提供了面向对象式的抽象与直观表述。本单元通过对UML语言内容的逐层深入(UML入门、UML模型关系、UML层次设计)进一步理解模型化设计的思想。下面对这一单元进行的实践操作进行小结,并对整个学期面向对象课程进行回顾总结。
第四单元作业总结
一、UML第一次作业
需求分析
概述
本次作业最终需要实现一个UML类图解析器,可以通过输入各种指令来进行类图有关信息的查询。(保证所建模的类图模型均可以在Oracle Java 8中正常实现)
要素
- 理清UML图-->mdj文件规则
- 理清mdj文件各元素含义
- 根据类图特点设计解析器架构,同时考虑以下拓展
- UML状态图
- UML顺序图
架构设计
思路
(1) 根据
UmlElement
的特点区分并确定需要建模成类的元素和建模成属性数据结构的元素。(2) 根据查询指令的特点和元素之间的关系(关联、继承、实现接口)确定算法的设计与耦合。
类图 (隐藏了属性及方法)
说明
类说明
MyModel
:包装类,用于将MyUmlInteraction
功能接口与具体实现逻辑分离。MyUmlClass
:Uml类,对类元素进行建模,与接口(MyUmlInterface
)平级,含有属性和操作两部分。MyUmlInterface
:Uml接口,对接口元素进行建模,与类(MyUmlClass
)平级。MyAttributeRecord
:属性集合,封装对属性的存储与管理行为。MyOperationRecord
:操作集合,封装对操作的存储与管理行为。MyOperation
:Uml操作,对操作元素进行建模。操作说明
类图解析器其中一个较麻烦的需求是对继承、实现关系的解析,并基于此进行关联关系、属性和操作的查询。因此有以下思路:
- 对于继承关系:实质为图关系,利用遵守Java 8规范的限制和dfs的思想对需要更新的目标数据进行更新即可(关联关系继承、属性继承、实现接口继承等),懒惰式遍历且仅遍历一次即可。
- 对于检索、判重等细节,合理利用数据结构即可。
- 对于时间复杂度,缓存过程数据即可。
二、UML第二次作业
需求分析
概述
- 扩展类图解析器,使得可以支持对UML状态图和顺序图的解析,并可以通过输入相应的指令来进行相关查询。
- 在所解析的UML模型基础上,按照规定的规则检查模型中是否存在违背规则的情况,并输出相应信息。
要素
- 理清UML状态图新增元素、新增操作
- 理清UML顺序图新增元素、新增操作
- 理清模型有效性检查规则
架构设计
思路
(1)同类图设计,对状态图和顺序图进行层次建模
(2)判断模型有效性检查功能与原类图模型功能耦合难易程度,新增层次模型管理抑或修改原类图功能。
总体类图
类说明
MyModel
:类模型建模MyStateModel
:状态图建模MyCollaborationModel
:顺序图建模
类模型类图
类说明
主要在UML第一次作业上增加了以下部分:
MyRepeatElementModel
:重复属性和关联对端检查规则MyGeneralizationModel
:循环继承检查规则MyMultiGeneralizeModel
:重复继承检查规则
实现细节说明
Rule1、2、3是逐条推进的,越后的规则面临的数据规范性越强。
- Rule1实现:使用HashMap等数据结构对
UmlAttribute
,UmlAssociationEnd
等元素进行操作即可 - Rule2实现:图算法思想,以类、接口作为结点,继承、实现关系作为有向边,使用tarjan算法求解有向图强连通分量即可
Rule3实现:同Rule2可使用图算法思想,并且Rule3检查说明数据满足Rule2,即必为有向无环图,简化问题求解,使用dfs思路即可。
状态图类图
说明
MyStateModel
:如前文所述,状态图建模MyUmlStateMachine
:对stateMachine抽象为类进行管理
实现细节说明
- 合并状态(pseudoState, finalState):使用HashSet存储即可合并。
- 后继状态查询:使用第三单元的思路,将id进行index转化,使用邻接矩阵存储图并采用floyd求连通性即可(主要是实现简单快捷,适用范围广)。
顺序图类图
说明
MyCollaborationModel
:如前文所述,顺序图建模MyUmlInteraction
:对UmlInteraction抽象为类进行管理MyUmlLifeline
:对UmlLifeline抽象为类进行管理
实现细节说明
- 层次化建模,使用如HashMap、HashSet等数据结构合理管理数据即可。
单元架构设计 & OO方法理解演进
一、第一单元:求导规则
关键词:JAVA语法入门、基本抽象设计、多态与继承使用
第一单元作业基本是本人初次接触面向对象程序设计,可以说主要将精力放在了Java语言特性的学习上;此外,通过课上的学习,自己对需求要素的抽象进行了摸索与探究,并在作业中进行尝试(类初步设计与管理,算法封装等),可以说是有些“刻意为之”,尽可能地尝试类抽象和方法抽象(实际上没有深入考虑行为抽象、过程抽象与数据抽象等);值得一提的是,在第一单元第三次作业中,使用了Java的类继承和多态的特性,将表达式求导这一行为进行抽象(接口使用与多态使用),将表达式进行数据抽象(继承),灵活简捷地实现了求导层次树,可以说是结合Java特性对面向对象基本的抽象思维和数据行为设计管理进行了实践。
二、第二单元:多线程设计
关键词:多线程设计、并发调度,设计模式
第二单元迈入多线程的领域。从内容上看,三次作业均涉及到多线程调度,线程安全控制,重点在与Java多线程机制的掌握与使用,而对Java多线程语法特性的实践也确实占据了前期的大部分时间,特别是线程安全相关内容(锁机制等);但在复杂的功能需求背后,真正需要我们进一步强化的仍然与面向对象设计本身密切联系。基于复杂的多线程功能需求,我们需要对代码架构设计,层次抽象等进一步理解与实践,具体来说,第一单元我们仅是基于抽象的形式(如继承、多态等特性)进行思维的锻炼,这一单元则迫使我们在架构上下功夫,如线程并发过程对数据访问控制,则要求我们对数据、行为功能的耦合进行分离,并合理组织数据,确定行为实现方案。除此之外,我们还接触到了基于设计模式的架构设计,如工厂模式、单例模式、观察者模式等等,通过对设计模式的具体实践,我们得以使用简便快捷的结构来体会层次化设计的妙处。
三、第三单元:规格化设计
关键词:规格契约,抽象编程,架构扩展性,设计原则
第三单元的模式又与前两个单元不同。本单元强调的是契约式编程,这对于我们来说又是全新的体验。作业的形式从 from scratch 转为了cloze(即通过接口和对象JML约束进行逻辑实现)。这一单元主要对面向对象思想中的抽象思维和契约设计进行了强化,之前都是面对完整的需求进行整体设计,在设计的同时进行一定的抽象与封装完成功能,而这里则是根据给定契约(已经设计好的抽象)来完成功能,规格-->逻辑和逻辑-->规格这两种方式训练了我们在契约式编程上的能力,可以说是简化了其他细节,点对点地强化抽象思维。除此之外,架构扩展性也是本单元的主题之一,三次作业实现了一个地铁线路管理系统,从基本的图结构到最终的系统结构,层次化设计的思想依然存在,而更重要的是结合抽象和层次化,分析任务需求对整体结构进行较全面的设计,这一点是本单元除契约编程外进一步给我启发的地方。设计原则同样也出现在了本单元的学习中,可以说是面向对象思维的精华部分,值得在日后实际工作中实践加深体会。
四、第四单元:UML设计
关键词:抽象逻辑描述,模型化设计
第四单元可以看作是整个面向对象课程的综合性实践。UML模型是对软件设计的有力描述与表示工具,通过对UML图解析器的具体实践(包括类图、状态图、顺序图,分别代表三种看待需求和问题的视角),加深了抽象化思维、层次化设计的锻炼。此外,UML模型图本身就是模型的建构,我们对模型图进行解析,相当于对建构(抽象表示)进行建构,类似于元学习,这大大帮助了我们对模型化设计的理解。
测试理解 & 实践演进
一、第一单元:求导规则
关键词:白盒测试、静态逻辑检查
第一单元由于功能较为简单,代码量较小,因此主要采取的测试策略是白盒测试与静态逻辑检查。效果也不错,直接通过逻辑验证保证了代码的正确性。除此之外,小数据测试用例也是采取的策略之一,如边界数据等,能够快速缩小测试范围。
二、第二单元:多线程设计
关键词:黑盒测试
第二单元涉及到多线程程序,因此第一单元采取的静态逻辑检查等策略显然失去了效果(并发的不确定性)。基于这一特点,本单元测试将重心转移到了黑盒测试上,具体来说就是根据问题的特点和输入输出格式实现对拍器,如通过电梯的指令输入可以直接将其转化为对输出结果的约束,然后通过该约束对程序的输出进行检查。黑盒测试的特点在于,实现黑盒的过程需要对问题进行全面的理解(加深了对需求的理解),经过实现付出之后是自动化测试的便捷。使用自动化测试使我们在这一单元bug蜜汁出现的时候得到了极大的帮助。
三、第三单元:规格化设计
关键词:单元测试、规格自动化测试
第三单元由于JML规格设计的特点,我们对单元测试这一种测试策略进行了深入地实践。通过规格的描述与限制,我们能够清晰地设计单元测试格式,使其完整地覆盖代码;同时基于JML我们也接触了如SMT Solver和JunitNG等规格自动化测试工具,可以看到自动化生成测试用例的强大之处。此外,上一单元使用的黑盒测试在本单元也有所使用。
四、第四单元:UML设计
关键词:综合实践、基于模型的测试用例设计
第四单元是一个综合性实践,因此测试方面也与之前不同。由于UML图的特殊性,我们更多的是通过对模型的层次化理解进行数据构造,相当于另一种程度对模型化设计的思考与实践。
课程收获
面向对象设计思想:
最主要的收获是对OO思想的全面学习和实践理解,从基本的JAVA语法出发针对单一功能的简单抽象封装,到代码整体架构的详细思考设计、层次化建模方法的理解,再到需求与功能拓展性、设计模式结合的整体架构思考,最后是综合性实践,可以说是纵向深入,横向扩展式地对OO进行了学习。
代码架构设计能力培养:
在OO课程之前,我们在CS核心课程群上初步锻炼了模块化设计方法(高内聚、低耦合原则);而在OO课程上,我们得以对之前学习的内容在软件层面上进行实践,同时通过不同的需求,从不同的角度(局部上JML规格、整体上每单元逐次扩展)对架构设计反复强调,强化锻炼。在架构设计方面得到了能力的提升。
测试技术实践:
OO实践的重要一环自然是测试技术的实践。要想在评测中拿到好成绩,课下采取各种测试策略是必不可少的。而通过OO课程,我们接触到了更多的测试技术和工具,体会到了测试的重要性,并且从实践中理解了各种测试技术的优缺点,可以在日后的代码编码过程中使用。
代码风格:
这一点非常接地气,一直认为代码风格是一件非常重要的事情。而OO课程对代码风格的硬性要求则是帮助我们在这一方面养成习惯,这些软实力都是将来工作不可或缺的一部分。
课程改进建议
理论实践结合:整体上我们对面向对象的各方面进行了一定的实践,对课堂上学习的方法论在具体问题解决过程中进行了体会;但是理论课上部分不易在实践中设计问题进行强化锻炼的部分基本上被同学们忽视了,建议在之后的课程中增加对理论课程部分知识点的练习与深入讲解。
反馈及时性和全面性:建议在之后的课程中增加对每次作业的反馈环节(选择优秀的作业或助教准备的范例公开提供参考学习);对实验课的内容也建议增加反馈环节,部分实验课侧重点与课下作业不完全重合,因此有必要对实验课内容进行补充说明。
课下作业相关:如何平衡需求的内容和考察点一直是OO课程设计的难点,因此在这里感谢助教们一学期的辛勤付出,同时也希望之后的课程在往届的不断探索下能够在这一点上越做越好,造福学弟学妹们。