OO第四单元

OO第四单元总结

本单元的任务是根据输入的UML图元素,支持对类图中相应关系的指令查询

架构设计

第一次作业

第一次作业要求我们根据输入的UML类图元素,支持类图指令的查询。经过详细阅读指导书以及PPT后,不难发现可以根据UML类图元素之间的层次化关系建立一张UML类图,便于指令的查询。

由此我们可以对UML类图关系图中需要与其他元素产生联系的中间节点构造一个包装类,在第一次作业中体现为MyClass,MyInterface,MyOperation这三个类,UmlAttribute、UmlParameter,可以作为MyClass和MyOperation的属性,UmlGeneration、UmlInterfaceRealization作为类和接口之间的关系,可以在MyClass类中设置父类属性,在初始化时添加对应的关系。

由于输入中的UML元素之间是无序的,因此可以在MyImplementation类的构造器中先将每个UML元素添加到HashMap中,其中key值为element的Id,value为对应的Uml元素或者包装类。在所有元素输入完之后,再根据UML类图的层次关系初始化构造UML类图。

第二次作业

第二次作业在第一次作业的基础上新增了对状态图和顺序图的指令查询。由于第一次作业已经打好了地基,可以继续沿用第一次作业的思路,根据顺序图、状态图之间的关系,采用包装类来构造顺序图和关系图。

但由于新增了两个图,如果继续按照第一次作业的方法,直接把类图初始化方法放在了MyImplementation类,就显得有些捉襟见肘了。根据面向对象的思维,我们可以把MyImplementation类和关系图耦合度降低,分出三个类(MyClassDiagram、MySequenceDiagram、MyStateDiagram)进行三种关系图的构造。

比如状态图,我们可以根据状态图的关系进行构造,其中MyStateMachine、MyRegion、MyState、MyTransition为包装类,UmlEvent作为MyTransition的属性、MyState有三种类型(一般状态、初始状态、终止状态),拥有对应的MyTransition属性,由此可以构建起状态之间的转移

image-20220625205739912

和状态图比起来顺序图更为简单一点,只需要构造MyInteraction和MyLifeline两个包装类即可,其中MyLifeline中有Creator,即创建它的Lifeline,为第二条指令服务。而指令 3:给定 UML 顺序图和参与对象,收到了多少个 Found 消息,发出了多少个 Lost 消息只需要在顺序图初始化时遍历所有的消息,根据关系对对应的MyLifeline添加Found消息数量和Lost消息数量即可。

第三次作业

本次作业是在前两次作业的基础上新增对9种异常的检查,基本上不用改架构,只需要在前两次作业的基础上增加一些异常的检测。看起来似乎不难,但需要注意的是有些地方很坑。

首先R004检查的是重复继承的类或者接口。但是由于类是单继承的,并且循环继承的情况已经在R003中被排除了,所以R004中无需考虑类的重复继承,只需要判断接口的重复继承

最坑的地方是R003的循环继承的检查,虽然课程组把数据限制在了300个UML元素内,但是根据我造的数据,先随机生成几十个接口,再两个接口间再随机继承,哪怕是这样完全随机的数据,如果循环继承的算法写的不好(直接暴力dfs找出每个点成的所有环,没有剪枝),就会tle,本地测试甚至300个元素的数据跑了一个多小时都没有跑出来。我的做法是遍历每个点,对每个点dfs看能否从这个点出发回到这个点,同时使用visited集合维护dfs中已经遍历的点,如果dfs中再遇到这个点就直接返回false,如果dfs中重新走到了这个点,也直接返回true。这样优化以后最差的情况也是遍历整张图,性能比前一种找环的方法提高了很多很多,一个多小时都跑不出来的数据只需要零点几秒。

数据生成与自动评测思路

第四单元开始时已经接近期末,本来不想搭建评测机了😥,但想着已经搭了三个单元的评测机,本着有始有终的态度,仍然继续搭建评测机。🤡

数据生成

在群里看到有些人认为本单元数据生成似乎有点难,但我个人感觉这个单元数据生成难度其实和前面三个单元差不多。显然随机生成数据是不能按照UML图源代码生成的(我也不会),不过幸好课程组给我们降低了难度,我们只需要根据指导书的要求生成UML图元素的子集即可。而不同UML元素的输入格式则可以根据官方输入样例和自己画一些UML图然后使用官方包进行导出查看,然后照猫画虎生成数据即可。

我的数据生成的办法是每一种UML元素对应一个函数进行生成,在生成时需要根据UML图元素之间的关系进行有序的生成,同时在生成时对需要保存的元素之间的关系进行保存,比如

展开代码
##########Class Diagram###########
totalParentId = "ooooooo"
visibilities = ['public', 'private', 'protected', 'package']
NamesNoId = ['lab', 'oo', 'os', 'co', 'gpa']
# NamesNoId = ['lab']
normalType = ['short', 'byte', 'int', 'long', 'char', 'boolean', 'float', 'double', 'String']
# normalType = ['String']
operationType = normalType + ['void']
parameterDirection = ['return', 'in']
blankName = ['  ', '', '\t ', '\t\t\t']
operationIdList = []
classNameList = []
classIdList = []
interfaceIdList = []
classHasSuperClassList = []
classOfSuperClassDic = collections.defaultdict(list)
interfaceExtendDic = collections.defaultdict(list)
classRealizeInterfaceDic = collections.defaultdict(list)
operationIdMapClassId = {}
operationHasReturnParameterList = []
classAttributeNameMap = collections.defaultdict(list)
totalId = 0
classNameIsSameP = 0
attributeIsNormal = 0.4
attributeIsClass = 0.5
attributeTypeIsError = 0.3
attributeTypeIsParentClass = 0.8
parameterIsNoraml = 0.7
parameterIsError = 0
##########state diagram################
guardNameList = ['\" \t\"', '\"\t\t\"', '\"wwdl\"', '\"gpaGG\"', '\"KaoYanQvLe\"', '\"orzorzorz\"', 'null','\"pku\"']
stateMachineIdToNameDic = {}
statedMachineNameList = []
statedMachineIdList = []
stateMachineToRegionDic = {}
regionIdList = []
regionToStateDic = collections.defaultdict(list)
regionToStateNameDic = collections.defaultdict(list)
regionToStartStateDic = collections.defaultdict(str)
regionToFinalStateDic = collections.defaultdict(list)
transitionIdList = []
statedMachineNameIsSame = 0.05
stateNameIsSame = 0.05
transitionFromBegin = 0.2
##########sequence Diagram############
interactionIdList = []
interactionNameList = []
interactionToLifelineIdDic = collections.defaultdict(list)
interactionIdToNameDic = collections.defaultdict(list)
interactionToLifelineNameDic = collections.defaultdict(list)
interactionToMessageDic = collections.defaultdict(list)
interactionToEndPointDic = collections.defaultdict(list)
collaborationIdList = []
attributeIdList = []
collaborationAttributeDic = collections.defaultdict(list)
interactionToCollaborationDic = collections.defaultdict(str)
TransitionToEventNameMap = collections.defaultdict(list)
interactionNameIsSame = 0.05
lifelineNameIsSame = 0.05
messageType = ['createMessage', 'synchCall', 'deleteMessage']

保存某些元素之间的关系一是因为生成其他UML元素需要用到这些关系,二是在进行指令生成的时候也需要根据这些关系来进行生成。

下面说一下这几次数据生成的难点

第一次作业

由于不能循环继承,因此生成UMLGeneration元素时需要采用拓扑排序的思想生成一张有向无环图,在代码中的体现就是对ClassIdList和InterfaceIdList采取前面的元素继承后面的元素的办法,这样就保证了继承关系是无环的

第二次作业

这次作业数据不难生成

第三次作业

由于这次作业是对异常的检查,且每个数据只能触发一次异常,因此需要构造正常数据和异常数据,在R00X中保证只有对应R00X的异常。异常的数据也根据指导书来进行构造即可,难度不大,但是由于有9个异常,因此比较繁琐。

总体感觉

这次作业数据生成的难度其实没有这么大,只是需要细心阅读指导书,掌握UML模型元素之间的关系,再花上一点时间就可以生成具有一定强度的数据了。

但不得不说造评测机是的确是一件繁琐的事情,尤其是自己独立造,在完成第四单元评测机后我惊讶地发现哪怕是用Python写评测机,第四单元的评测机也惊人地达到了2223(数据)行+136(自动评测)行的长度,比我第四单元作业的代码行数还要多。

自动化评测

本次作业自动化评测和第一单元、第三单元一样对拍即可,因此沿用了第三单元的自动化评测

posted @ 2022-06-26 21:51  繁华丶人间  阅读(49)  评论(0编辑  收藏  举报