OO 第四单元总结 & 学期小结

OO 第四单元总结 & 学期小结

一、总述

本单元主要目标为学习基本的UML统一建模语言,并在此基础上实现对mdj源码的解析,官方包提供了初步的转化,我们需要运用一定数据结构进行组织,并提供相应的查询接口。本单元的学习中需要理解UML类图、时序图、协作图中的基本概念,并了解其mdj源码表示。

 

二、第十三次作业

1、题目要求

  • 本单元作业相信大家初看还是比较头疼的,可能看完指导书还是一头雾水,其实第一次作业要求我们解析的是UML类图部分,给出mdj源码,官方包为我们转化成以下元素,我们只需要自己架构,并完成相关查询接口即可。

2、UML类图 & 具体实现

第一次作业设计的仅为Uml类图部分。首先,会给出.mdj源码,官方包已经帮我们把这些”丑陋“的源码转化为一个个实例化的Uml对象,但这些对象是一些孤立的结点或者关系,还缺乏一个数据结构来把他们组织到一起。从这里开始就是我们需要完成的操作,我们需要来创建数据结构,来建立起一棵自己的Uml元素树,然后根据后续指令留出相关查询方法的接口。

弄明白这些,我们就可以开始着手工作了。这里面最重要的就是我们自己的Uml元素树的建立。

对于这些元素我采用了相对比较严格的依赖关系来建立,一共分为3轮。

Step 1: Class, Interface
Step 2: Attribute, Operation, RealizeInterface, AssEnd, Gen
Step 3: Association, Parameters

为了便于查询,本次我封装了MyClassMyInterface以及MyOperation三个类,按以下的结构进行组织,在内部预留出相关的属性和接口以便查询。

 

 

其余部分按照指导书展开即可,在群里面发现本单元大家面临的问题还比较多,可能有这些易错问题。

  • getClassImplementInterfaceList,要考虑继承方式间接实现的接口,注意不重不漏

  • getClassAttributeCouplingDegree,本指令的查询需要考虑继承自其各级父类所定义的属性,但不需要考虑实现的接口所定义的属性,注意每种Reference只记一次

  • getClassOperationCouplingDegree,只考虑自己定义的方法,注意错误类型的优先级更高且需要考虑所有参数,判重时只考虑传入参数,同时注意一一映射,Reference同上。

 

三、第十四次作业

1、作业要求

  • 本次作业新增了状态图和顺序图的解析,首先需要理解其层次结构,然后建立起对应数据结构,并实现查询

2、UML类图 & 具体实现

  • 第二次作业的层次化解析我是按这样来建立的

    Step 1: StateMachine, Interaction
    Step 2: Region, LifeLine
    Step 3: Message, State
    Step 4: Transition
    Step 5: Event
  • 为了便于查询,本次我封装了MyStateMachineMyRegion, MyState, MyInteraction, MyLifeline几个类,按以下的结构进行组织,在内部预留出相关的属性和接口以便查询。

     

     

  • 本次作业中较难的查询为判断是否为关键状态,在这里我选择了用bfs来实现:(支撑的数据结构见上图)

    ///////////////////// 根据题设抛出异常并判断结果 ///////////////////////////
    public boolean checkCritical(String stateMachineName, String stateName)
               throws StateNotFoundException, StateDuplicatedException {
           if (name2State.containsKey(stateName)) {
               ArrayList<MyState> statesList = name2State.get(stateName);
               if (statesList.size() == 1) {
                   MyState state = statesList.get(0);
                   if (finalStates.size() == 0 || state.getType() == ElementType.UML_PSEUDOSTATE
                           || state.getType() == ElementType.UML_FINAL_STATE) {
                       return false;
                  }
                   ArrayList<MyState> canArrive0 = getCanArrive(null);
                   ArrayList<MyState> canArrive1 = getCanArrive(statesList.get(0));
                   if (canArrive0.size() != 0 && canArrive1.size() == 0) {
                       return true;
                  }
                   return false;
              } else {
                   throw new StateDuplicatedException(stateMachineName, stateName);
              }
          } else {
               throw new StateNotFoundException(stateMachineName, stateName);
          }
      }
    /////////////////// bfs 查找可以达到的终点状态 /////////////////////
    public ArrayList<MyState> getCanArrive(MyState myState) {
           MyState begin = this.startState;
           Queue<MyState> queue = new LinkedList<>();
           queue.add(begin);
           ArrayList<MyState> canArrive = new ArrayList<>();
           HashSet<MyState> book = new HashSet<>();
           book.add(begin);
           while (!queue.isEmpty()) {
               MyState now = queue.poll(); // 返回并删除队首元素
               HashSet<MyState> nextStates = now.getNextStates();
               for (MyState state : nextStates) {
                   if (myState != null && state.equals(myState)) {
                       continue;
                  }
                   if (!book.contains(state)) {
                       queue.add(state);
                       book.add(state);
                       if (state.getType() == ElementType.UML_FINAL_STATE) {
                           canArrive.add(state);
                      }
                  }

              }
          }
           return canArrive;
      }

     

 

四、第十五次作业

1、作业要求 & 具体实现

  • 本次作业在前两次作业的基础上增添了9种错误的check,实现起来并没有预想中的轻松,比较考验前期架构,同时稍有不慎就可能遇到单个类超过500行的问题()。

  • UML类图,鸽了,本次基本沿用上次架构,但由于最大行数限制,本次将Myimplementation拆分成类图、时序图、状态图三个独立的部分处理进行解耦,查询接口分发到各个独立的模块。

 

五、架构设计思维及OO方法理解的演进

在本学期的OO课程中可谓收获很多,从几个月前一行java代码都敲不出的小白,到今天看着自己完成过的这么多作业,感触很深切。

  • 在Pre课程中,第一次接触到面向对象思维,在假期的尾声里学习类的封装,属性保护,方法调用等知识,开始有能力写出一份简单的java代码。

  • 第一单元的作业算是一次全新的体验,全新的表达式树为OO学习拉开了序幕,在第一单元里学习了递归下降法的建模方式,但写出的代码仍有很多面向过程思想的余孽,导致在后期虽然最终结构看似很简单,但代码过于复杂,有些牵一发而动全身之感。

  • 第二单元的电梯月里学习了多线程的知识,了解到如何确保多线程中的安全问题,同时对于轮询问题可谓是刻骨铭心(此处省略一万字)。在这一单元的学习中吸取教训,总结经验,正如总结Unit2博客中所写,于oo课程而言,这个结局不够圆满,但对于我个人而言,这个句号足够圆满。

  • 第三单元相对轻松,也更深刻的认识到架构的重要性,秉承着在每次作业留下足够空间的理念,每次改动量不是很大。第三单元重新深入学习理解了一些图算法,并在性能上做出优化。写出的代码也越来越面向对象。这一单元开始学会如何针对性的hack,构造边缘数据,在本学期最后一次互测中成功Hack到评测机一次(非恶意)。

  • 第四单元的学习重在理解,理解了Uml类图、顺序图、状态图的意义后完成作业会变得事半功倍,同时我们自己组织的结构也要根据需求来架构。整体而言本单元还算顺利,但由于期末压力比较大,加上已经写了一学期代码,而本单元大多数工作为大模拟,在最后一单元有些缺乏动力。

 

六、四个单元中测试理解与实践的演进

  • 四个单元中的测试方式有所不同。前两个单元由于答案并不固定,因此完成评测需要给出一套完整且正确的评测逻辑。第一单元可以通过给表达式赋值的方法来实现。第二单元则工作量较大,一方面多线程安全需要大量数据进行轰炸,另一方面评测逻辑需要完全手动完成,工作量较大。第三、四单元可以采用“随机数据生成 + 对拍”的方式来完成,相对而言比较轻松。

 

七、课程收获

  • OO课程难度很早便听说过了,亲身体会下来,虽然艰难但是对能力的培养是毋庸置疑的,高强度的训练对码力的训练提升作用是显著的。在学习中也逐渐从面向过程编程转化为面向对象思考,学会考虑增量开发需求,追求架构逻辑的清晰合理。在本课程中我的收获也很大,很难想象在四个月前还连一行java都不会写,现在可以一天手搓千行代码。OO课程可以称得上是6系真正的精品课程。

 

八、课程建议

  • 增加一些对于设计模式的教学,可以在这方面开设训练或者实验,在本学期末端的实验难度明显上升,但相比前两单元与作业联系并没有那么紧密,可以适当修改,引导学习更多的面向对象知识。

  • 第四单元可以进一步优化,需要自己去理解的内容比较多,同时写起代码感觉像是写一些“大模拟”,缺乏知识性的学习,或者说能力上的培养,内容有些“枯燥”。

  • 最后是关于课程评测环节的建议,中测和强测之间梯度比较大,可以在中测中适当加一两个更高强度的点,这样可以减轻很多的压力。此外互测环节有些违背初衷,虽然本学期已经做出改革,缩短了互测时长,但整体而言并没有起到学习架构的作用,更多的还是随机数据轰炸式的恶意hack。可以精选一些优秀架构让大家来学习,回归互测的初衷。

 

posted @ 2022-06-26 17:51  warriors2001  阅读(7)  评论(0编辑  收藏  举报