面向对象设计与构造:OO课程总结
第一部分:UML单元架构设计
第一次作业
UML图
- MyUmlInteraction类实现接口方法,ClassUnit和InterfaceUnit管理UML图中的类和数据单元
- MyUmlInteraction类整合UML类图中的所有数据元素,并用Map建立相应的Id到UmlElement的映射
- ClassUnit除了记录自身的属性,关联和实现接口外,采用All-XXX的形式记录来自父类的上述元素继承和自身的上述元素
- InterfaceUnit分别记录了自身继承的父类接口和继承的所有父类接口
递归回溯
需要查询和记录父类的信息时,采用了递归回溯的思想,下面以getAllAttribute方法为例
//MyUmlInteraction.java
private Set<String> getAllAttribute(String classId) {
ClassUnit target = getClassUnitById(classId);
if (target.getId().equals(target.getFather())) {
return target.getAttributes();
}
if (target.getAllAttributes() == null) {
ClassUnit father = getClassUnitById(target.getFather());
target.setAllAttributes(getAllAttribute(father.getId()));
}
return target.getAllAttributes();
}
//ClassUnit.java
private Set<String> attributes = new HashSet<>();
private Set<String> allAttributes = null;
...
public void setAllAttributes(Set<String> attributes) {
allAttributes = new HashSet<>();
allAttributes.addAll(attributes);
allAttributes.addAll(this.attributes);
}
public Set<String> getAllAttributes() {
return allAttributes;
}
- 该方法完成的功能:返回Id为classId的类所包含的所有属性
- 第一个if语句判断此时classId对应的类是否为顶层类(在ClassUnit中fatherClass的Id全部初始化为自身的Id)
- 如果该类不是顶层类,需要找到所有父类包含的所有属性。allAttributes如果为null表示查询该类所有属性的操作还未进行,需要递归查找父类的所有属性,并添加进allAttributes数据结构中;allAttributes不为null说明已经记录好了该类所有属性,直接返回数据结构即可
第二次作业
架构与代码实现
说实话我感觉第二次作业工程量巨大,为了保证扩展性,要维护大量的数据结构@H_502_65@
有向图图查询
addEdge:有向图加边,传入的两个String为类或接口的Id,nodeMap建立Id到node编号映射
public void addEdge(String fromId, String toId) { if (!nodeMap.containsKey(fromId)) { nodeMap.put(fromId, nodeCount++); } if (!nodeMap.containsKey(toId)) { nodeMap.put(toId, nodeCount++); } map[nodeMap.get(fromId)][nodeMap.get(toId)] = 1; }
floyed:图更新算法
getReachableNodeCount:寻找该结点后续可达结点
public int getReachableNodeCount(String id) { if (!nodeMap.containsKey(id)) { return 0; //未加入有向图中说明id对应的类或接口无继承或被继承关系 } if (!finished) { //finish为graph的全局变量,因为图建立好以后只需跑一次floyed算法 floyed(); finished = true; } int nodeId = nodeMap.get(id); if (reachableCount[nodeId] != maxValue) { //如果已经统计过一次直接返回结果 return reachableCount[nodeId]; } int answer = 0; for (int i = 0; i < nodeCount; i++) { if (map[nodeId][i] != maxValue) { //map[i][j]均初始化为maxValue answer++; } } reachableCount[nodeId] = answer; return answer; }
isCircle:是否存在自身到自身的循环。这里主要看
map[id][id]
是否为maxValue,如果不是则存在自环
时序图和状态图
类图
保留第一次作业实现的功能
重复继承的检查
public void checkForUml009() throws UmlRule009Exception { Set<UmlClassOrInterface> answer = new HashSet<>(); //检查类是否重复实现接口 for (String i : classList.keySet()) { ArrayList<String> temp1 = getAllImplementedInterfaces(i); Set<String> temp2 = new HashSet<>(temp1); if (temp1.size() != temp2.size()) { answer.add(classList.get(i));//类实现的所有接口列表中存在重复元素 } } //检查接口是否重复继承接口 for (String i : interfaceList.keySet()) { ArrayList<String> temp1 = getAllInterfaceFathers(i); Set<String> temp2 = new HashSet<>(temp1); if (temp1.size() != temp2.size()) { answer.add(interfaceList.get(i));//接口继承的所有接口列表中存在重复元素 } } if (answer.size() != 0) { throw new UmlRule009Exception(answer); } }
- 主要的思路是使用Arraylist和Set去查重,getAll-XXX方法均返回
Arraylist<String>
- 主要的思路是使用Arraylist和Set去查重,getAll-XXX方法均返回
循环继承的检查采用有向图的自环检查即可
第二部分:课程收获
本来觉得,这十五次作业我只是在一味地设计与编码,并没有将某次架构深入极致或收获颇丰。但回过头来想想,我发现这更像是一种体验,好像自己的设计能力是比无头苍蝇好一点了,代码也敲得快了,各种工具也会用了,JML和UML也会写会画了。虽然不知道影响多大,但也算熬过了本次巅峰体验@H_502_65@
架构
表达式求导,规格和UML单元在我看来,更多的是在做数据结构的事情:如何封装数据,如何解析数据,如何设计查询和修改的接口。所以对于实际问题,我的思路逐渐成型:
电梯单元在我看来,更多的是在维护线程安全,因此我的做法是:
- 画流程图(非常重要,甚至涉及架构的正确性)
- 流程图实质上是状态图,所以要求状态的完备性,确保所有的输入对应到的所有后继状态
- 在流程图找到可能会起冲突的临界区,用矩形框圈起来标识
- 分析冲突区域,找到起冲突的数据单元,隔离相应的增删查改操作
- 画流程图(非常重要,甚至涉及架构的正确性)
- 划分数据单元,将线程相关与数据相关进行隔离(通俗地说,维护数据的类就不要有run方法)
关于OO方法理解的进演
重提SOLID原则
- SRP(单一责任原则):避免类的功能重合和一个类做太多事
- OCP(开放封闭原则):对扩展开放,对修改封闭
- LSP(里氏替换原则):所有引用基类的地方必须能透明地使用其子类的对象
ISP(接口分离原则):避免接口的责任重合和一个接口做太多事情
- 接口分离的难点在于对方法的抽象,遗憾的是我们的作业大多是根据官方接口去实现程序
DIP(依赖倒置原则):模块之间尽可能依赖于抽象实现
- 简而言之,多采用基于抽象类的代码设计模式,其实我们的作业设计也差不多采用这种模式
- 本学期课程我很少用设计模式去进行架构,看来需要更多的实践才行啊 ~
测试
愿以后的工作没有互测,不做社畜,少受社会的毒打,不用霸王洗发水@H_502_65@
生成测试数据
测试实践
- IDEA源代码打包jar→测试数据in.txt→输出结果out.txt→脚本对拍(fc对比文件差异)
JML检查工具系列:针对规格化程序设计的规格语言测试,生成测试样例
Junit:单元测试,针对某一方法进行单独测试
第三部分:课程建议
一,精简理论课内容,从架构难点深入讲解
- 理论课的PPT实在是缺少场景例子,尤其涉及架构的理论知识冗余,各种名词晦涩难懂
- 一遇到具体如何架构的地方感觉就会浅尝则止,庞大的代码工作量无法预留更多时间进行架构上的探索
- 理论课的内容完全可以收录许多精品贴(比如对各种UMLElement元素的解析)
二,实验上机后放出实验内容,给出标程
- 实验上机的内容实属良品,尤其是画UML图等很考察我们在短时间内进行初步架构设计的能力
- 不放标程,不让我们回头寻思一番,实验分数没有意义
三,指导书需要更加明确,对有争议的地方及时更新
- 重点在刚刚结束的第十四次作业,指导书的质量在逐渐下滑(就事论事)
- 这里说的及时更新应该是在周六晚前解决大部分疑问,重点是不影响架构设计的进程
四,建立良好的测试数据库机制(下届)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。