OO第四单元总结
作者:互联网
BUAA_OO_2022_第四单元总结
OO第四单元作业主题为UML图,具体的任务是给出UML图中的元素,我们将其存储起来并实现若干个查询指令,同时在第三次作业中,需要我们针对几个规则进行异常检测,下面我分享一下我在本单元的学习心得和作业完成情况。
目录第一次作业
架构设计
在所有三次作业中,我的整体架构都是:在MyImplementation类中存储建模中全部元素的信息并建立id到元素的映射,对于查询指令涉及的元素,我们也会建立name到元素的映射。以Class为例:
public class MyImplementation implements UserApi {
private HashMap<String, MyClass> id2Class; //为后续添加Operation等元素利用parentId去寻找Class提供映射
private HashMap<String, MyClass> name2Class;
...
public Map<Visibility, Integer> getClassOperationVisibility(String s, String s1) throws
ClassNotFoundException, ClassDuplicatedException {
//略过异常处理部分
MyClass myClass = name2Class.get(s);
return myClass.getClassOperationVisibility(s1);
}
}
在第一次作业中,对于UML图的分析仅限于类图,只需要考虑UML类图相关的建模即可,而对于UML类图的查询都是基于类名去做的,因此我们把类作为我们整个类图的结构的第一层就是显然的。
下面给出我在本次作业中的结构设计:
当我们读取导入的元素时,我们需要一级一级的去构造我们整个模型,也就是说,我们需要根据模型的级数去一遍遍的扫全部的UMLElement,在本次作业中,我们的模型一共有三级,因此我们需要扫三遍UMLElement:
public void startInsert() {
for (UmlElement umlElement : elements) {
firstInsert(umlElement);
}
for (UmlElement umlElement : elements) {
secondInsert(umlElement);
}
for (UmlElement umlElement : elements) {
thirdInsert(umlElement);
}
}
在实现查询指令时,也只需从类开始,一级一级往下去查询即可。
bug修复
本次作业中我在强测中没有出现bug。
第二次作业
架构设计
在本次作业中,UML图由原本的UML类图增加了UML顺序图和UML状态图,我们需要针对新增的两种UML图仿照UML类图进行建模,同时需要支持相对应的查询指令。
UML顺序图
我们注意到,在本次作业中,对UML顺序图的查询是基于UmlInteraction_name去进行的,因此我们将UmlInteraction放在我们的顺序图的第一级的位置。但是,事实上UmlInteraction并非UML顺序图的第一级,它的上边是有UmlCollaboration的,但本次作业并不涉及UmlCollaboration,因此我也没有管,这为下次作业的小重构埋下了伏笔
以下是我的结构设计:
可以看到,这里的结构设计还是省略了很多元素的,比如LifeLine中指记录了CreateMessage而没有记录其他Message,高情商的说,这为第三次作业的增量开发留下了一定空间,低情商的说,就是偷懒
UML状态图
UML状态图有个致命的问题,就是我们的第一级StateMachine和查询指令所涉及的重点State中间有着一个第二级Region,这使得,如果我们通过正常的建模,那么查询指令一级一级往下查就必然会经过Region这个中间商,但好在,作业保证了,一个StateMachine里有且仅有一个Region,因此我们可以通过建立region -> statemachine映射的手段,强行使得Region与StateMachine平级,将Region下的元素放在StateMachine下:
public void secondInsertStatus(UmlElement umlElement) {
if (umlElement.getElementType() == ElementType.UML_REGION) {
MyStateMachine myStateMachine = id2StateMachine.get(umlElement.getParentId());
region2StateMachine.put(umlElement.getId(), myStateMachine); //建立region -> statemachine映射
}
}
public void thirdInsertStatus(UmlElement umlElement) {
if (umlElement.getElementType() == ElementType.UML_PSEUDOSTATE ||
umlElement.getElementType() == ElementType.UML_FINAL_STATE ||
umlElement.getElementType() == ElementType.UML_STATE) {
MyState myState = new MyState(umlElement.getId(), umlElement.getName());
MyStateMachine myStateMachine = region2StateMachine.get(umlElement.getParentId());
//直接跳过region“越界访问”statemachine
id2State.put(umlElement.getId(), myState);
if (umlElement.getElementType() == ElementType.UML_PSEUDOSTATE) {
myStateMachine.addStartState(myState);
}
else if (umlElement.getElementType() == ElementType.UML_FINAL_STATE) {
myStateMachine.addEndState(myState);
}
else {
myStateMachine.addState(myState);
}
}
}
我的结构设计如下:
bug修复
本次作业我在强测没有出现bug。
第三次作业
架构设计
在本次作业中,我们引入了几类异常。需要在我们的UML图结构里支持对于异常的检测。由于本次作业中不存在新的UML图类型,因此我们并不需要设计全新的架构,对类图和状态图,只需要在第二次作业的架构中进行小量的增量开发即可。
顺序图架构重构
在R006异常中,需要让我们的LifeLine的name与其对应的Collaboration中的属性name相同,因此,我们不得不在我们的UML顺序图结构中加入Collaboration。
重构后的设计如下:
checkstyle
在本次作业和上次作业中我都遇到了文件超过500行的问题,我的解决方法是:增加工具类MyTool,主要处理之前在MyImplementation类中处理的建模任务,因此,MyImplementation类将只会处理剩下的指令查询和异常处理任务。
优化后的MyImplementation类如下所示:
public class MyImplementation implements UserApi {
private HashMap<String, MyClass> id2Class;
private HashMap<String, MyClass> name2Class;
private HashMap<String, MyInterface> id2Interface;
private HashMap<String, MyOperation> id2Operation;
private ArrayList<String> duplicatedClass;
private HashMap<String, MyStateMachine> id2StateMachine;
private HashMap<String, MyStateMachine> name2StateMachine;
private HashMap<String, MyStateMachine> region2StateMachine;
private HashMap<String, MyState> id2State;
private HashMap<String, MyTransition> id2Transition;
private ArrayList<String> duplicatedStateMachine;
private HashMap<String, MyInteraction> id2Interaction;
private HashMap<String, MyInteraction> name2Interaction;
private HashMap<String, String> id2EndPoint;
private HashMap<String, MyLifeline> id2Lifeline;
private ArrayList<String> duplicatedInteraction;
private UmlElement[] elements;
private HashMap<String, MyAssociation> id2Association;
private HashMap<String, MyCollaboration> id2Collaboration;
public MyImplementation(UmlElement... elements) {
this.elements = elements;
id2Operation = new HashMap<>();
id2Class = new HashMap<>();
id2Interface = new HashMap<>();
name2Class = new HashMap<>();
duplicatedClass = new ArrayList<>();
id2StateMachine = new HashMap<>();
name2StateMachine = new HashMap<>();
region2StateMachine = new HashMap<>();
id2State = new HashMap<>();
id2Transition = new HashMap<>();
duplicatedStateMachine = new ArrayList<>();
id2Interaction = new HashMap<>();
name2Interaction = new HashMap<>();
id2EndPoint = new HashMap<>();
id2Lifeline = new HashMap<>();
duplicatedInteraction = new ArrayList<>();
id2Association = new HashMap<>();
id2Collaboration = new HashMap<>();
MyTool myTool = new MyTool(elements);
myTool.insert1(id2Class, name2Class, id2Interface, id2Operation,
duplicatedClass, id2StateMachine, name2StateMachine, region2StateMachine);
myTool.insert2(id2State, id2Transition, duplicatedStateMachine, id2Interaction,
name2Interaction, id2EndPoint, id2Lifeline, duplicatedInteraction);
myTool.insert3(id2Association, id2Collaboration);
myTool.startInsert();
}
//原本这里会是Insert相关方法,但现在这里可以直接进入查询指令部分
}
bug修复
本次作业我在强测中同样没有bug,本次OO课的代码作业以最后一次作业强测满分完美收官。
架构设计思维及OO方法理解的演进
首先,我认为面向对象的一个重要特点就是:一个工程由不同对象分工合作地去完成,而每个对象专心做好自己的事情即可。这个特点贯穿了我整个四个单元十二次代码作业的架构设计思维以及对于方法的理解。
第一单元
在第一单元中,我们给出了表达式的结构组成,相当于给出了几个分工合作的对象,比如因子之间只负责乘法,项之间只负责加减法等,因此,我在实现每个部分的化简方法时,我只需要实现相对应的部分(乘法或者加减法)即可,专心做好自己的事情。
第二单元
第二单元的重点应该是多线程导致的线程安全问题的处理,但我任务,第二单元是我上面所说的架构设计思维的完美体现。首先,整个电梯作业基于生产者消费者模型所写,重点就是生产者和消费者,以及消费者之间(横向电梯和竖向电梯)如何分工合作,同时作为生产者和消费者,我们也要去做好我们的本职工作,即生产(增加请求)和消费(运送乘客) ,这便涉及到了每个类的方法应当如何设计。虽然我在第二单元遭遇了强测的滑铁卢,但我依然认为本单元对于面向对象思维的培养有着非常积极的作用。
第三单元
这一单元比较特殊,我们实际上是在官方给定的结构下进行方法的完善,因此这个单元重点培养的是我们对于OO方法的理解。
第四单元
第四单元和第一单元非常相似,唯一的不同大概是,第四单元需要由我们自己去建模,相当于是对我们的架构设计思维的最终考验,而后续指令的实现便是对我们对于OO方法理解的最终考验,我个人认为我算是比较好的通过了这两个考验。这一单元我的层级结构我个人认为还是比较优雅且直观的。
测试理解与实践的改进
我对于测试的理解主要分为两部分:数据构造和正确性检验。
在几次作业的实践中,我的本地测试全都是通过跑评测机的方式去进行的。在数据构造方面,前两个单元需要考虑的并不是很多,直接采用随机数据即可,而在三四单元,由于作业是指令的方式,同时存在着异常检测,因此为了数据能做到全面覆盖,就必须要考虑数据点触发异常的概率,单纯使用随机数据的话只会导致100%的异常率,而这是我们不愿意所看到的。
同时评测的方式由前两单元的正确性检验变成了三四单元的对拍,我认为,对拍其实是一种性价比比较高的检验方法,因为你不需要去写正确性检验相关的代码,同时在对拍人数比较多,数据点多的情况下采用对拍的方法也可以保证正确性。因此,我认为对于正确性检验比较困难的作业,采取对拍的方法都是不错的选择。
课程收获
首先,OO带给我最大的收获便是“入门”了java这门语言,熟悉了面向对象的代码书写方式。在半年以前我甚至不会写java的hello world,更不知道面向对象的代码是何物。而现在我已经可以写出一个两千行代码的基于面向对象的小工程了。我认为OO能做到这一点,开学前的pre功不可没,pre2从最基本的Class定义开始到面向对象三大基本特征再到最后的综合训练,循序渐进的带领我们进入java及面向对象的世界,使我们快速入门这门全新的语言。而后面的作业便是在一次次实践中,加深我们对于面向对象的理解。
我认为我在OO课上的收获便是认识了一些其他的元素,比如多线程,比如JML规格。之前我对于代码的理解只有“算法”二字,在大一的C以及DS课上,全部的课程内容和作业都围绕着算法去讲。而OO课上,我也是初步认识到了,代码最重要的还是服务于需求,算法只不过是我们采取的方法中的一种,模型的建立对于实现需求来说同样重要。
最后就是,我在OO课学习和完成作业的过程中结识了很多伙伴,在这学期也得到了他们的很多帮助,也许没有这些伙伴们的帮助,我的OO学习也相对来说不会这么顺利。
三个建议
1、第一单元的难度我认为可以考虑略微降低,因为此时包括我在内的大部分人都是刚接触java,直接上高难度任务很可能会让初学者吃不消。
2、指导书的表述希望可以希望可以更加清晰,第二单元我因为对指导书的理解问题很惨烈的挂了一次强测,第四单元中指导书也有多处表述存在问题的地方。
3、希望在电梯单元增加电梯的多样性,可以更充分地培养学生的多线程之间协作的思维。
标签:OO,HashMap,作业,private,umlElement,UML,第四,单元 来源: https://www.cnblogs.com/hdd1211/p/16423733.html