BUAA-OO-第四单元总结
一、第四单元架构设计
以第三次作业为例,整个架构可以大致分为三个模块,即类图、顺序图和状态图。
类图
类图中主要有三类节点,class、interface和operation。Uml图中的Mould类是ClassNode和InterfaceNode的父类,结合了二者的共有部分,如拥有的属性和方法、ID、name等成员属性,以及一些检查合法性和处理指令的方法。Mould类中存储属性、方法、关联端点,OperationNode类中则存储该方法包含的所有参数。这样形成层次分明的关系,在执行指令或检查合法性时也能层层往下调用。
顺序图
顺序图是比较简单的链型关系,体现了顺序图层次关系,即顺序图下存储所有的Interaction,Interaction存储其包含的Lifeline,而分析指令要求,Lifeline只用存储found和lost消息即可。在执行指令时同样类似于类图,顶层类使用负责调用下一层类的方法,具体实现则只需要交给下一层类。
状态图
状态图的设计从结构上非常类似于顺序图,StateGraph存储所有的状态图节点,StateMachineNode存储RegionNode(实际上如果只考虑本单元作业,这个类其实没有必要设计),RegionNode下包含所有该状态图中的所有状态节点,同时每个状态节点又用邻接表的形式存储TransitionNode和与之相连的状态节点。
数据解析方式
从设计上不难发现,本单元作业的数据有很明显的层次关系,这也就要求我们要按层次进行数据解析。具体而言我根据自己的设计分为五层解析。
- 解析class, interface, interaction, stateMachine, collaboration
- 解析operation, associationEnd, generalization, realization, attribute, lifeline, endpoint, region
- 解析parameter, message, state, association
- 解析transition
- 解析event
值得一提的是,尽管从层次上来看,association的层级应该高于associationEnd。但由于本次作业中关注的不是和类同一端的端点,而是另一端的端点,因此笔者采用了先解析associationEnd,再解析association的方法。
指令执行过程
由前文可知本单元架构设计具有明显的层次性,这样的好处是在执行指令或检查合法性时,其方法的调用过程也有极强的层次感,这样每一层只用处理这一层该处理的事,剩下的交给下一层即可,这样的结果是逻辑清晰,容易定位错误。这里以状态图的指令2(给定状态机模型和其中的一个状态,判断其是否是关键状态)为例,简单介绍调用过程。- 1 /* MyImplementation 直接调用StateGraph的方法 */
- 2 public boolean getStateIsCriticalPoint(String stateMachineName, String stateName)
- 3 throws StateMachineNotFoundException, StateMachineDuplicatedException,
- 4 StateNotFoundException, StateDuplicatedException {
- 5 return stateGraph.getStateIsCriticalPoint(stateMachineName, stateName);
- 6 }
- 7
- 8 /* StateGraph 简单判断异常后调用StateMachineNode的方法 */
- 9 public boolean getStateIsCriticalPoint(String stateMachineName, String stateName)
- 10 throws StateMachineNotFoundException, StateMachineDuplicatedException,
- 11 StateNotFoundException, StateDuplicatedException {
- 12 ArrayList<StateMachineNode> stateMachines = name2StateMachine.get(stateMachineName);
- 13 if (stateMachines == null) {
- 14 throw new StateMachineNotFoundException(stateMachineName);
- 15 }
- 16 else if (stateMachines.size() > 1) {
- 17 throw new StateMachineDuplicatedException(stateMachineName);
- 18 } else {
- 19 return stateMachines.get(0).getStateIsCriticalPoint(stateName);
- 20 }
- 21 }
- 22
- 23 /* StateMachineNode 直接调用RegionNode的方法 */
- 24 public boolean getStateIsCriticalPoint(String stateName)
- 25 throws StateNotFoundException, StateDuplicatedException {
- 26 return region.getStateIsCriticalPoint(stateName);
- 27 }
- 28
- 29 /* RegionNode 判断异常后,调用StateNode的方法 */
- 30 public boolean getStateIsCriticalPoint(String stateName)
- 31 throws StateNotFoundException, StateDuplicatedException {
- 32 ArrayList<StateNode> states = name2StateNode.get(stateName);
- 33 if (states == null) {
- 34 throw new StateNotFoundException(machineName, stateName);
- 35 }
- 36 else if (states.size() > 1) {
- 37 throw new StateDuplicatedException(machineName, stateName);
- 38 }
- 39 else {
- 40 if (isConnect == 0) {
- 41 isConnect = origin.isConnect();
- 42 }
- 43 if (isConnect == -1) {
- 44 return false;
- 45 }
- 46 else {
- 47 StateNode state = states.get(0);
- 48 if (state.getIsKeyState() == 0) {
- 49 state.setIsKeyState(origin.isConnect(state));
- 50 }
- 51 return state.getIsKeyState() != 1;
- 52 }
- 53 }
- 54 }
- 55
- 56 /* StateNode中用来判断是否是关键状态的方法 */
- 57 public int isConnect(StateNode node) {
- 58 LinkedList<StateNode> queue = new LinkedList<>();
- 59 HashSet<StateNode> vis = new HashSet<>();
- 60 vis.add(this);
- 61 queue.add(this);
- 62 StateNode cur;
- 63 while (!queue.isEmpty()) {
- 64 cur = queue.removeFirst();
- 65 if (cur.isFinal()) {
- 66 return 1;
- 67 }
- 68 for (Map.Entry<TransitionNode,StateNode> entry:
- 69 cur.nextNode.entrySet()) {
- 70 StateNode next = entry.getValue();
- 71 if (next.equals(node)) {
- 72 continue;
- 73 }
- 74 if (!vis.contains(next)) {
- 75 vis.add(next);
- 76 queue.add(next);
- 77 }
- 78 }
- 79 }
- 80 return -1;
- 81 }
复制代码 二、四个单元中架构设计思维及OO方法理解的演进
第一单元
第一单元是我真正意义上第一次采用面向对象的思想去解决问题(Pre的作业主要还是熟悉java语法),面对复杂的表达式,面向过程的编程思想显得无从下手。这因为如此,我才更深刻地体会到面向对象分析解决问题的优势,将复杂的表达式层层解析为一个个对象,使用递归下降的方法对其进行解析和处理,最终迎刃而解。但是现在再回头去看第一单元的代码,相比于第四单元还是有很明显的“面向过程”的影子,这也导致部分模块的处理显得尤为臃肿,方法复杂度也非常高。
第二单元
第二单元主要学习多线程编程以及设计模式的应用,这也是我第一次学习使用多线程的方法编写代码,对线程同步互斥的理解还非常浅,导致处理线程同步和线程安全的问题上花费了大量的时间和精力。但同样的,这个单元的作业给我带来的进步也格外显著,不光是熟悉了多线程的使用方法,更重要的是学习到生产者消费者模型和流水线模型,通过在作业中设计这两种模型也加深了对面向对象编程的理解,将调度器、托盘、需求、电梯等设计为对象,分别思考他们的功能,最终作为一个个模块组合为项目,这也让我体会到面向对象编程“分治”的特点。
第三单元
第三单元的核心是学习JML规格化语言,没有太多需要自己设计架构的地方。此外也借此复习了图论的相关算法,并了解到各个基础算法的优化方式。不过这一单元课程组提供的代码架构也确实让我学习到不少经验,这在我第四单元的架构设计中其实也有一定体现。把person、relation分别看做图的节点和无向边,构建起来网络模型,并针对这个网络进行一些功能拓展(如分组,发送信息)。
第四单元
第四单元的架构设计相对于其他单元来说比较简单一些,因为本身UML图就具有非常明显的结构,只要根据各个元素之间的关系层层分析,模仿UML图本身的结构进行设计就好。这个单元主要还是更加熟悉和理解UML图元素,并使用面向对象的思想来解析UML图(其实也非常简单,很容易想到把各个元素作为对象)。
三、四个单元中测试理解与实践的演进
四个单元都是与同学合作完成评测机的编写,并一起对拍,受益良多。
第一单元
第一单元是使用同学写的数据生成器随机生成数据,并利用python的sympy库进程正确性验证。尽管没有实际动手去写评测机,但还是深刻的认识到自动评测带来的便利性和优势,同时也从第一单元同学写的评测机中认识到了一些不足,比如没有完全实现自动,出现问题的数据由于过于复杂难以迅速定位错误的地方等,为之后我编写评测机提供了宝贵的经验。
第二单元
第一单元作业认识到使用评测机debug和互测带来的事半功倍的效果,于是从第二单元开始我也编写了评测机。吸取第一单元的教训,我学习到了使用python的os库生成数据后,自动运行jar文件将生成的数据作为输入,得到输出结果后按一定逻辑进行评判。因为第二单元多线程异步性的特点,没办法使用对拍,于是只能自己分析程序运行逻辑来进行评测,这其实存在一定风险,原因是不一定能考虑全所有的情况(第二单元第二次作业也正是这个原因,没有测出作业存在的bug)。另一方面多线程的评测需要高并发地执行程序,否则很难暴露出线程安全、死锁等问题。
第三单元
有了前两次的测试经验,第三单元的评测机写起来还是比较顺利的。但是由于第三单元需要更多考虑算法的时间复杂度,评测机只能作为正确性和功能性的验证工具,压力测试还是需要自己针对算法构造数据。当然除了自动评测之外,第三单元还学习到了一个重要的测试手段——JUnit,但JUnit同样要求测试者要充分考虑各个方法的前置条件等。
第四单元
第四单元的测试机主要是图的构造,指令只需要遍历验证即可。类似于作业的解析方式,数据生成同样是根据UML元素之间的层次关系,自顶向下地进行图的构造,重点在于要控制出现异常的概率,以及如出现关键状态的保证。由于整个过程都是随机生成的,所以对于关键状态的控制还是比较玄学,基本是通过尝试不同参数,找到一个比较容易出现关键状态的参数。
四、课程收获
首先本学期oo课程带来的最大收获就是学习到面向对象的思想,不光是在作业上,包括后面几次的评测机编写,其实都或多或少体会到面向对象的优势。另外也学到很多知识,包括git的使用,单例、生产者消费者等设计模式,markdown的使用,uml图和jml语言等。
另外,一次次作业的迭代开发也让我意识到设计和架构的重要性,一个好的架构能够帮助程序员更加方便和顺利地维护项目、拓展功能,尽量减少各个模块之间的耦合度,防止修改或增加一个功能,会导致其他模块的功能受到影响,最终导致迭代难度过高而重构。
当然还有代码风格的变化,一学期的作业都要求我们按照一定的代码规划进行编写,我也切实感受到经过oo课程的实践,自己代码风格的规范化。比如在os挑战性任务中会习惯性地增加空格,不至于看上去那么紧凑;也会自主地使用规定的方法对变量和方法进行命名,增加代码的可读性。
五、课程改进建议
1.希望能在pre增加一些多线程的知识,第二单元是大多数同学第一次接触设计模式和多线程,难度确实很大,加上对多线程的理解不到位,导致后面的作业也会出现或多或少的问题。
2.希望互测数据不规范时,课程组能够为同学指出具体是哪里不规范,尽管课程组可能是想让同学仔细阅读分析,但很多时候真的很难找到原因。
3.虽然可能不太现实,但希望能适当在第三或第四单元选择两次作业减少一些量,压缩成一次作业,提前一周结束课程设计,让同学有更充分的时间准备考试,烤漆压力确实太大了。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |