OO第四单元总结
第四单元代码架构
-
作业架构
-MyClass -MyOperation -MyParameter -MyAttribute -MyInterface -MyAttribute -MyGeneration -MyClass -MyInterface -MyStateMachine -MyRegion -MyTransition -MyState -MyCollaboration -MyAttribuye -MyInteration -Lifeline -EndPoint -Message
-
代码架构如上所示,根据UML本身具有的层次关系建模,通过基于已有的UMLElement包装成新的类,比如MyClass。这样的设计目的是增加原有的类所不具备的属性,以及方法,从而实现满足题目要求。例如在MyClass中含有MyOperation,MyAtribute类型的数组,MyOperation下面又有MyParameter,来实现对层次化关系的建模。通过这样的建模方式,对于指令的查询也就是通过层层调用即可。比如查询类的有关信息,可以直接调用类的方法,类的方法调用过程中又有可能调用到下一级,比如MyOperation的方法,使代码更简洁,层次清晰
-
在代码实际编写的过程中使用了较多的HashMap,以及HashSet,因为这一次的作业涉及到大量的索引类型的查询,比如通过名字查询以及通过id查询,还有查重等。这个时候使用Hash类的容器可以使得代码更加简单。
- 比如名字查询,并且要能实现有名字重复就报错,可以利用HashMap很简洁的实现:
private final HashMap<String, UmlLifeline> name2LifeLine = new HashMap<>(); public void addLifeLine(UmlLifeline umlLifeline) { id2LifeLine.put(umlLifeline.getId(), umlLifeline); if (name2LifeLine.containsKey(umlLifeline.getName())) { name2LifeLine.put(umlLifeline.getName(), null); } else { name2LifeLine.put(umlLifeline.getName(), umlLifeline); } } //查询有关名字对应的umlLifeline,如果不含有key就是不存在这个名字,如果有key但是为null,就说明是重复 if (!name2LifeLine.containsKey(lifelineName)) { throw new LifelineNotFoundException(interaction.getName(), lifelineName); } else if (name2LifeLine.get(lifelineName) == null) { throw new LifelineDuplicatedException(interaction.getName(), lifelineName); }
- 利用HashSet,重写equals和hashCode来实现Operation查重:利用两个容器一个Arrilist一个HashSet,如果两个size不一样说明有重复。
@Override public boolean equals(Object obj) { if (!(obj instanceof MyOperation)) { return false; } if (!operation.getName().equals(((MyOperation) obj).getName())) { return false; } if (this.parametersMap.size() != ((MyOperation) obj).parametersMap.size()) { return false; } HashMap<NameableType, Integer> other = ((MyOperation) obj).parametersMap; for (Map.Entry<NameableType, Integer> entry : parametersMap.entrySet()) { NameableType key = entry.getKey(); int value = entry.getValue(); if (!other.containsKey(key)) { return false; } if (other.get(key) != value) { return false; } } return true; } @Override public int hashCode() { return Objects.hash(operation.getName()); }
-
对应较为复杂度的查询功能,比如关机状态查询,循环继承等,都是通过dfs算法实现。由于这次作业的数据量不是很大,所以dfs的时间空间代价在合理范围内,并且通过递归的方式实现,可以在递归的时候同时修改有关的数据,使得下次再递归到的时候可以直接返回上次递归的结果,从而减少递归的次数,以及多次查询相同元素的代价
四个单元中架构设计思维及OO方法理解的演进
- 第一单元 表达式化简
- 第一单元主要是为了让大家体验面向对象中的层次化设计,因为表达式中天然存在着表达式,项,因子等层次化关系,所以可以利用面向对象的思维很好的包装起来,在解析的时候自顶向下的解析,递归下降
- 第二单元 多线程电梯
- 第二单元的内容难度较大,主要是学习多线程的有关知识,需要解决互斥同步的关系,主要的方法就是利用锁。此外这一个单元中更加体会到了增量开发的要求,从第一次到第三次作业出现了横向电梯,横纵方向的请求等等,我们需要尽可能在不改变已有架构的前提下实现增量开发,这就考验了我们的代码设计能力
- 第三单元 JML
- 这个单元主要学习有关JML的知识,能够通过阅读JML来实现需求者的需求,并且保证代码能满足规格,体会到了规格化设计的严谨性
- 第四单元 UML
- 这个单元继续学习面向对象中的层次化设计,新增加的内容就是学习UML模型,理解UML模型中的层次化设计理念。
测试理解与实践演进
- 第一单元
- 主要利用python的numpy库直接来实现正确性检验,然后利用正则表达式来生成数据,生成数据的时候也采用了层次化的细想,基于形式化表达式来自下往上的生成表达式
- 第二单元
- 第二单元主要是通过手动构造一些数据来测试,但是由于多线程输出的不确定性,在用肉眼判断正确性的时候出现了错误,导致了一些bug
- 第三、四单元
- 主要是利用生成随机数据和指令,和同学对拍的方式,并且记录运行时间
课程收获
在四个单元的学习中,学习了java语言的使用,面向对象的有关设计思想,多线程有关的知识,基于规格的编程,UML模型的有关知识,同时在写作业的时候还收获了一些课外知识。比如在第一单元中学习了递归下降的有关知识,在第二单元中学会了生产者消费者模型,单例模式的使用来简化对象共享问题,第三第四单元中复习了图论有关的算法,比如最短路径,环等等。并且在OO学习的过程中始终严格要求代码风格,所以养成了在写代码无论是python还是C,都维护良好的代码风格,注意代码的架构以及可维护性等的习惯
改进建议
- 减小作业代码的量,每周一个大作业并且实现代码迭代开发对于我来说还是压力太大了,尤其是每个单元的第一次作业,都很难很快的掌握这个单元的要领,花费大量的时间与经历。
感觉整个学期不是在写OO就是再检测OO - 希望能提供更多的测试样例,以及加强一下公开的测试数据的强度。因为在每次OO的作业中,在强侧之前都无法获得很多有关代码的正确性的反馈,这给正确性检测带来了极大的难度,导致用来测试的时间甚至超过了代码本身编写的时间,然而这门课学习的是面向对象的思维,而不是如何用python生成测试数据,这样多少有点舍本逐末,并且花费学生更多精力
- 降低互测和性能分的占比,以及取消能扣别人的分这一制度,可以自己能加分的,但不应该扣别人的分,北航本就内卷严重,何必搞得更乌烟瘴气。