BUAA_OO_第四单元以及期末总结
一、第四单元架构设计
类图如下图所示
本单元是要实现一个JML解析器,自己主要新建的类有
分了MyClassModel,MyCollaboration和MyStartChart三个类分别完成三种图的统计工作。在第三次作业中,为了进一步功能细分化,又设立了MyCheck类进行前置性检查,前置性检查中的所有信息统计与主体类完全独立,避免了由于数据不规范导致主体中的数据统计出现问题。
其中MyOp是为了完成类图中对于UmlOperation的统计而设计的,存储Operation的Parameter和name,其余UML元素的类采用的官方包里的内容。
核心算法
在第一次作业中,采用HashMap代替数组,存储了大多数信息。为了实现
public int getClassAttributeCouplingDegree(String className)
throws ClassNotFoundException, ClassDuplicatedException {
return myClassModel.getClassAttributeCouplingDegree(className);
}
@Override
public List<String> getClassImplementInterfaceList(String className)
throws ClassNotFoundException, ClassDuplicatedException {
return myClassModel.getClassImplementInterfaceList(className);
}
@Override
public int getClassDepthOfInheritance(String className)
throws ClassNotFoundException, ClassDuplicatedException {
return myClassModel.getClassDepthOfInheritance(className);
}
这几个方法,大量采用了递归搜多来书写函数。
第二次作业中,为了实现这一个方法
public boolean getStateIsCriticalPoint(String stateMachineName, String stateName)
throws StateMachineNotFoundException, StateMachineDuplicatedException,
StateNotFoundException, StateDuplicatedException {
采用了bfs的方式进行判断
vis.clear();
queue.add(beginId);
vis.add(beginId);
boolean ans2 = false;
while (!queue.isEmpty()) {
String now = queue.poll();
if (umlStates.get(now).getElementType() == ElementType.UML_FINAL_STATE) {
ans2 = true;
}
for (String nex : state2stateTransitions.get(now)) {
if (!vis.contains(nex) && !Objects.equals(nex, noValidId)) {
vis.add(nex);
queue.add(nex);
}
}
}
在第三次作业中,为了实现CheckforUml003,采用了对每一个点进行dfs判断自身是否在环上。
public void check003() throws UmlRule003Exception {
HashSet<String> ans = new HashSet<>();
//类
for (UmlClass umlClass : preUmlClasses.values()) {
HashSet<String> vis = new HashSet<>();
if (dfs1(umlClass.getId(), umlClass.getId(), vis)) {
ans.add(umlClass.getId());
}
}
//接口
for (UmlInterface umlInterface : preUmlInterfaces.values()) {
HashSet<String> vis = new HashSet<>();
if (dfs2(umlInterface.getId(), umlInterface.getId(), vis)) {
ans.add(umlInterface.getId());
}
}
HashSet<UmlClassOrInterface> tureAns = new HashSet<>();
for (String id : ans) {
tureAns.add((UmlClassOrInterface) umlElements.get(id));
}
if (!tureAns.isEmpty()) {
throw new UmlRule003Exception(tureAns);
}
}
private boolean dfs2(String aim, String id, HashSet<String> vis) {
boolean ans = false;
vis.add(id);
for (String id1 : preGeneralizationSource2TargetInterface.get(id)) {
if (Objects.equals(id1, aim)) {
return true;
} else {
if (!vis.contains(id1)) {
ans |= dfs2(aim, id1, vis);
}
}
}
return ans;
}
private boolean dfs1(String aim, String id, HashSet<String> vis) {
vis.add(id);
if (!preGeneralizationSource2Target.containsKey(id)) {
return false;
}
String id1 = preGeneralizationSource2Target.get(id);
if (Objects.equals(id1, aim)) {
return true;
} else {
if (vis.contains(id1)) {
return false;
} else {
return dfs1(aim, id1, vis);
}
}
}
第一单元
主要在努力遵守归一化的原则,力求更多的体现每一个类的共性,在这个过程中,体会到了归一化原则的威力,归一化的定义让Expr在Term类中的递归处理变的自然而然。在第三次和第二次作业中,体会到了设计的原则是追求正确性和性能的平衡,两者不可偏废。
第二单元
在第一单元归一化原则的基础上,进行方便多线程运行的设计(线程安全),更多地去进行线程类、共享资源类和中央控制器类的设计。由于时间不足,后期进行的主要是需求性增量开发,尽可能减少对于代码的改动,更多的进行类、函数和属性的增加。
与此同时,这一单元在优化上的探索也让我感触颇深,没有一种算法是完美的。最佛系的算法——自由竞争算法的表现竟然一直很优秀。
第三单元
本单元是契约式编程,对于契约的理解是一个很重要的环节,充分理解契约之后,基本不需要进行过多的架构设计,仅仅需要想办法高性能地实现契约的功能。当然为了避免代码超过500行和层次清晰,我将核心算法代码(两点间最短路径、最小生成树等)抽离了出来,放在了另一个类里。
第四单元
感觉这一单元主要还是面向过程编程,为了使代码层次清晰,我们抽离出三个不同的图表类负责不同的查询操作。设计函数遵循功能单一化的原则,让函数功能清晰,各司其职。
三、测试理解与实践
第一单元
主要采用的还是原始的手造数据进行测试,但测试效果欠佳,基本测不出什么bug,还是更多的通过对代码的分析来找出错误。
第二单元
构造了windows的命令行脚本和C语言的数据生成器,进行测试。相对来说更便捷了,也可以看一看运行时间。体会到了随机性数据的优点。
第三单元,第四单元
因为题目要求很清晰,主要采用与同学对拍的方式来比对对于题目的理解是否一致。
总结
总的来说,因为自己一直没有重视测试能力的培养,自己对于测试的理解和测试的能力都还是不是很到位的,这就导致了自己保证正确性的手段非常有限。
四、课程收获
1、面向对象设计的基本思维
2、一些具体的程序实现方法
第一单元:递归下降法解析文本,正则表达式解析文本
第二单元:一些设计模式,如单例模式,工厂模式。
第三、四单元:重温了之前学习过的算法,体会了算法在具体问题中的应用。
3、多线程设计的相关知识
4、契约式编程的相关知识
5、JML语言的相关知识
6、java的语法
五、改进建议
1、其实很多时候感觉课上的内容虽然很精彩,很有价值,但是和我们课下作业是有点脱节的。期望老师可以在课上多一些对于作业内容的指导与解析。因为个人感觉作业的挑战性还是很大的,自己的能力还是比较有限的,虽然和同学交流是个很好的途径,但是自己很期望能听到老师对于作业的指导与建议。感觉自己在在多进行几次实践之后在去做作业的效果会好得多。