BUAA-OO-Unit4 Summary & Lecture Summary
BUAA OO Unit4——UML解析 & 课程总结
本单元为解析UML文件,而UML在之前的单元一直是作为一个画图的文件,但其若是一个语言,自然有属于自己的语法,自己的范式,本单元就是从UML语言出发,结合其规范,对UML进行解析,本质就是解析文本文件提取需要的信息
Unit4
架构设计
这次的最大的敌人感觉是500行的限制。我按照UML元素的类型进行建模,对需要复杂操作,有从属关系的元素建一个类
diagram包里面是有关图的类型的建模,因为做到第三次的时候行数超了,就再对模型进行了提炼。建立新的抽象类。在每个具体的diagram里面进行对元素的解析,在Implementation中调用相对应的解析方法或者计算方法即可,也是对程序的进一步封装
public class MyImplementation implements UserApi {
//储存每一个UMLElement
private final HashMap<String, Object> id2elements = new HashMap<>();
//类图
private final ClassDiagram classDiagram = new ClassDiagram(id2elements);
//序列图
private final StateDiagram stateDiagram = new StateDiagram(id2elements);
//状态图
private final SequenceDiagram sequenceDiagram = new SequenceDiagram(id2elements);
//需要解析时,调用对应图的方法
private void parseClass(UmlClass umlClass) {
classDiagram.parseClass(umlClass);
}
//题目要求的方法也封装在对应的Diagram里面
public UmlLifeline getParticipantCreator(String interactionName, String lifelineName)
throws InteractionNotFoundException, InteractionDuplicatedException,
LifelineNotFoundException, LifelineDuplicatedException,
LifelineNeverCreatedException, LifelineCreatedRepeatedlyException {
return sequenceDiagram.getParticipantCreator(interactionName, lifelineName);
}
//判断是否合乎RUle,也是如此
public void checkForUml003() throws UmlRule003Exception {
classDiagram.checkForUml003();
}
}
对于所有的UMLElement,用一个map进行储存,其中key为ID,value为具体的Element或者是衍生类(如MyClass)这种的,这样在寻找Parent或者与其他类相关时,会很方便,因为UML中对于其他类的连接都是建立在ID的基础之上的。其中所有的Diagram级别的元素共用一个Map,这样每个元素在内部都可以访问所有的UMLModel
//类图的初始化
public ClassDiagram(Map<String, Object> id2Elements) {
this.id2elements = id2Elements;
}
此外还有一点需要注意,UMLElement出现的顺序是随机的,因此可能先出现UMLAttribute再出现所对应的UMLClass这样的情况,因此我们在建模的时候,要多循环几次,按照层次,每次把同一层次的元素提取出来,一层一层建模
public MyImplementation(UmlElement... elements) {
for (UmlElement element : elements) {
if (element instanceof UmlClass) {
count++;
parseClass((UmlClass) element);
} else if (element instanceof UmlInterface) {
parseInterface((UmlInterface) element);
}
}
for (UmlElement element : elements) {
if (element instanceof UmlAttribute) {
parseAttribute((UmlAttribute) element);
} else if (element instanceof UmlOperation) {
parseOperation((UmlOperation) element);
} else if (element instanceof UmlAssociationEnd) {
parseAssociationEnd((UmlAssociationEnd) element);
} else if (element instanceof UmlGeneralization) {
parseGeneralization((UmlGeneralization) element);
} else if (element instanceof UmlInterfaceRealization) {
parseInterfaceRealization((UmlInterfaceRealization) element);
} else if (element instanceof UmlStateMachine) {
parseStateMachine((UmlStateMachine) element);
} else if (element instanceof UmlInteraction) {
parseInteraction((UmlInteraction) element);
}
}
for (UmlElement element : elements) {
if (element instanceof UmlAssociation) {
parseAssociation((UmlAssociation) element);
}
if (element instanceof UmlParameter) {
parseParameter((UmlParameter) element);
} else if (element instanceof UmlRegion) {
parseRegion((UmlRegion) element);
} else if (element instanceof UmlLifeline || element instanceof UmlEndpoint) {
parseLifeline(element);
}
}
for (UmlElement element : elements) {
if ((element instanceof UmlState) || (element instanceof UmlFinalState)
|| (element instanceof UmlPseudostate)) {
parseState(element);
} else if (element instanceof UmlMessage) {
parseMessage((UmlMessage) element);
}
}
for (UmlElement e : elements) {
if (e instanceof UmlTransition) {
parseTransition((UmlTransition) e);
}
}
for (UmlElement element : elements) {
if (element instanceof UmlEvent) {
parseEvent((UmlEvent) element);
}
}
}
通过这样就可以依次按照层次将每一个元素存储起来,并建立其中的联系
学期总结
思维与方法理解和提升
-
第一单元是表达式展开,主要是想初步接触面向对象的思想,感受OO方法的魅力,感受一切都是“对象”,学会从一个问题中抽象出若干对象。从全局来看,表达式本身可以看作对象,而我们再对表达式进行细分,表达式由一个个项通过 + 或者 - 来连接,因此项也能看作对象,重复过程有一个分解成一个个因子。这个单元的练习就是教会我们通过如何从问题中抽象出一系列对象,建立一个层次化的结构,从而降低了问题的复杂度。我的程序也逐渐从面向过程转变到了面向对象。
-
第二单元是电梯调度,其重点是对象的交互,与第一单元注重其行为截然不同。所有的对象都只有和其他的对象建立联系、进行交互,才可以实现一个更大的功能。因此掌握多线程是必然的需求,我们需要结合实际场景对线程安全问题进行分析和解决,找出存在着线程安全的地方,在安全与效率之中找到平衡。学习各种各样的模式以及与其适应的场景。这个单元让我掌握了对多线程的了解,感受到了对象交互的魅力,分析线程安全、是否死锁的过程也帮助了我OS有关线程的学习。
-
第三单元是JML规格,需要能够理解JML规格语言,并能基于规格进行代码实现。这个单元我感受到“契约式编程”的高可靠性、高复用性、便于测试。此外契约式编程也不仅仅是一板一眼的按照他所写的规格,我们应该准求神似,能将其JML展示的契约内化,在满足要求的前提下尽量的满足高效性。
-
第四单元是UML建模语言,要求理解UML语言中各个元素和模型以及它们之间的关系,据此为每一个元模型建立对象,并使所有对象形成一个层次化结构,最终实现对UML的解析。这个单元使我们进一步感受到UML语言的面向对象性质,如何正确的封装对于实现本单元来说是比较重要的,在这个过程中我们可以进一步加深对面向对象思想的理解。
测试方法的提升
- 第一单元时,我只是编写数据生成器与python的sympy进行对拍,进行黑盒测试,因为第一单元总体的代码量尚可,且每个模块之间的逻辑关系尚可,因此这样的测试能够帮我定位并改正bug。因为本单元处理的表达式也不是很复杂,所以我也没考虑事先的问题。
- 第二单元因为多线程的不确定性,每次的输出过程都不是一致的,因此不太会写正确性的比对数据,所以我采用的是手搓数据。将可能出现的情况进行分类,结合一些中间输出过程与自己对程序的预计的处理流程进行比对,并以此判断是否有bug。但由于忽略了时限问题,没有考虑边际数据,导致自己策略上存在着一些问题,第二单元的最后一次作业出现了超时的问题。
- 第三单元学习Junit的测试方法,并开始对架构进行单元测试。所谓单元测试,也就是当写好一个功能后,用Junit构建测试类进行测试,可以及时对出现bug的地方进行修改,极其方便定位。此外这一单元也要考虑边缘数据的影响,这里我一般会用限制范围5-10倍的样例测试一下。这次使用数据生成和答案比对与同学的程序对拍,在这一单元中测数据较弱的情况下,确实救了我一命
- 第四单元本质上就是生成类似UML那样的数据格式,本质上是随机生成文本数据,增加一些限制,比如类不能多继承这样的。但我实验了一下觉得这次还是用将各种元素可能出现的情况罗列出来做全面化测试效果更好,因为这次的数据可能出现的情况不是很多,可以一一罗列,根据每种情况画出UML图,进行测试,可以保证程序正确的全面性。
课程收获
- 对Java语言获得了初步的使用体验,初步建立了面向对象的思想,并且掌握了很多基本的设计模式以及其应用场景,感觉到了其中的魅力
- 对拍能力有了较大提升,无论是写数据生成器方面还是自动测评机方面,在此过程中对shell的一些命令的使用有了更深的了解,可以写一些简单的脚本/
- 互测过程中提升了发现bug的能力,对自己的程序更加能针对性测试,静查自己程序bug的能力也得到了提升
- 通过从未有过的代码量的练习使得我对一些看上去繁杂的问题也没有那么害怕,也养成了先分析设计形成架构的初步习惯,不再像之前那样不管三七二十一就开始敲代码。并且一学期的coding,也使我第一遍写出来的代码不再充满bug,更能准确地表示我脑中所想的雏形。
改进建议
- 希望能在上机的时候知道每次提交的正确性,并且在训练之后能公布正确答案
- 提交不合法信息时能稍微提升一下是哪里出现的错误,方便修改数据
- 预习阶段可以稍微提一下多线程相关的简单内容,比如线程的构建等等之类的,一下子就面对多线程有点慌
- 作业之间的跨度希望能再相对平缓一点,这次第一单元前两次作业难度之间跨度有点大,且预习作业和第一单元难度跨度也有点大,刚开始有些许的不适应。