OO2022第四单元个人总结

本单元的主要目标是实现具有处理UML预处理后语句的一个解析器类的程序,并具有相关查询与报错的功能,本质上讲仍然可以看成是根据一串pcode生成模型并进行解析处理的程序,整体难度不算太大,比较考验图论功底。

本单元架构设计

image
这图看着乱七八糟的,所以简要说明一下个人架构,整体模型构建主要由三个大类完成,一个是实现UserApiMyImplementation类,一个是负责缓存模型的ModelingCaching类,还有一个是负责错误处理的RuleChecker类,对输入的处理大体思路如下:
把输入内容UmlElement[]放到ModelingCaching类的构造函数中进行处理,根据不同图的特征来决定要通过几次循环遍历来进行建模(目的是在建造层次关系时能清楚的找到其parentId对应的element),如对于时序图而言有如下的层次关系(Collaboration->interaction->lifeline\endpoint->message)所以需要四次循环,而我实际上使用了5次循环来进行建模(stateMachine有五层)。同时为所有可能的ElementType分别构造以id为键自己为值的Hashmap存入ModelingCachine的属性中,方便后续的调用。

public ModelingCaching(UmlElement[] elements) {
        initFirstLevel(elements);
        initSecondLevel(elements);
        initThirdLevel(elements);
        initForthLevel(elements);
        initFifthLevel(elements);
    }
private void initFirstLevel(UmlElement[] elements) {
        for (UmlElement element : elements) {
            elementMap.put(element.getId(), element);
            if (element.getElementType().equals(ElementType.UML_CLASS)) {
                classElementMap.put(element.getId(), element);
                addClass(new MyUmlClass((UmlClass)element));
            } else ...
        }
    }
private void initSecondLevel(UmlElement[] elements) {
        for (UmlElement element : elements) {
            ...
        }
    }

为了清楚的变现出所有UMLElement之间的层次关系,我为所有具有子层次的Element都分别构造了单独的类并将其所有子层次分别存入类中,例如下面的类:

public class MyUmlTransition {
    private final UmlTransition umlTransition;
    private final HashMap<String, UmlEvent> eventMap = new HashMap<>();
}

另外为了统一地处理时序图中的参与对象和状态图中的所有状态,我还分别构造了MyParticipant类和MyGeneralState类并让所有相关的类继承这两个类,方便某些指令的处理。
RuleChecker中的所有方法都是静态方法,在进行checkRule相关指令的时候,其流程如下:MyImpletation调用ModelingCaching,再由ModelingCaching静态调用RuleChecker,针对类里缓存的一大堆HashMap直接进行统一处理,事实上MyImplementation类的所有方法都是主要由调用ModelingCaching的相关方法来实现的。
最后迷迷糊糊写下来总代码量也是小过了2000行。
image

第一次作业

第一次作业主要是对类图的相关处理,对于判断两个方法的参数所组成的多重集是否相等,我使用了 HashMap 进行比较,键和值分别为对应参数类型和出现次数,除了这点以外,没有太多需要注意的地方。
bug方面由于写的时候没注意不小心把return参数也放进参数列表了,就WA了一个点。

第二次作业

第二次作业新增了时序图和状态图的处理,基本只涉及了简单图论问题,算法上没有什么要注意的点,不过通读官方包后不难发现类的属性、接口的属性、时序图的Role这三者在定义时其ElementType都是UML_ATTRIBUTE,和助教giegie讨论了一下后,得到如下的答案,在第二次作业前所有指令都只会当前图的闭包内实现,所以不用担心会在某个图中调用其他图的Attribute。但是在进行缓存时由于写法的问题部分同学可能会出现一些异常,这点是需要注意的。

第三次作业

第三次作业新增了对错误的判断,个人感觉只有R003 R004是需要重点关注的。对于R003判断成环可以直接topo,如果觉得topo麻烦的话也可以看一下从自己出发能否访问到自己,然后便利所有点(没限制复杂度就是爽。对于R004判断重复继承,仍然可以topo,采用topo+dp,dp去存当前点到入度非0的点的所有路径数量,topo的时候根据dpi去找答案就行,当然也可以直接拉一个HashMap去存所有点的入度,如果从当前点出发建立的map有入度大于1的点,那就把这点的相关路径也放答案里,不过要注意的是可能出现有两个source和target一样的继承关系出现,这种需要特判一下。
然后再说回UML_ATTRIBUTE的问题,当我们在判断Lifeline与其所代表的Role是否同属于一个图下时,这里就会产生对闭包外的id的查询问题,如果在第二次作业构建的时候最这里处理的不够细致,很可能会出现NullPointerException的异常,这里也是需要注意的。这个问题我的处理方法如下,因为笔者在进行模型缓存时采用的是跟据层次来确定循环便利的次数,也就是说在进行UML_ATTRIBUTE缓存之前,所有的UML_CLASSUML_INTERFACEUML_COLLABORATION是已经以HashMap的形式存在于ModelingCaching中,所以根据当前element的parentId就可以判断出其应该是属于什么种类的attribute。
NND补充一下BUG,我在建模型的时候是根据继承关系建造层次关系的,结果我自己写R004的时候脑子一🐯,给父类指向子类当箭头方向去dfs了,麻。
更多的也没什么要注意的了,这单元整体上还是比较简单的。

OO课程总结

总结自己在四个单元中架构设计思维及OO方法理解的演进

第一单元我学会了要将独立的元素尽量分离开,并把能细分的部分尽量进行细分,减少出错的可能,同时层次化的设计也更有利于后续拓展,同时我意识到一定要确定好架构在进行构筑,如果后续要出现架构上的重构,其时间开销会很大。
第二单元我学会了多线程设计的相关模式,更深一步理解了多线程并发的安全性问题和锁机制、连接池机制等,使我对设计安全性有了更深的体会,同时对临界区的设计也有了一定的心得。
但是出于性能考虑这两个单元还不是很能很好的体现OO思想,有些情况下为了必要的性能,牺牲架构和设计也确实是在所难免。
第三单元主要是讲JML规格相关问题,从这一单元我充分认识到了如何才能描述清楚一个方法可能带来的结果,同时也对OO设计的规范化有了一定的理解。
第四单元在前三个单元的基础上我从一开始就实现了高度层次化的设计,故在第四单元后面两次作业中,我都完成的非常快速,同时也对OO的设计模式和设计方法能带来的便利性有了更深一步的体会。

总结自己在四个单元中测试理解与实践的演进

由于自己没什么时间,测试这部分主要还是由自己手动捏造极端数据实现的,总体上没出太多问题,但是如果有时间的话还是应该尽量写评测机和同学对拍,这样的效率也更高一些。
至于如何捏数据,基本就是对着数据规范去,往上下限分别去构造足够极端的数据。

总结自己的课程收获

经历了一学期的OOP思想的灌溉,我对AOP设计的理解也有了些许的深入,同时由于没怎么进行过OOP方面的工作,对于JML和并发也是有了一个全新的理解,一学期下来我对JAVA相关源码的认识和对程序设计的理解都有了很大的提升。

立足于自己的体会给课程提三个具体的改进建议

1.首先我认为OO这门课程的所有参与学生都应该彻读《代码整洁之道》,甚至可以把这个要求放在pre里一同作为要求项目,不能只依靠直觉来认为自己的代码是优雅的,这样无论是互测还是实验,都对看代码的人员是个不小的包袱。
2.当前研讨课的分值占比设置我觉得有待商榷,我对于当前研讨课的收获感觉是甚微的,是否大家聚在一起每个人都发言讨论其效果就一定是正向的?这个问题我觉得不能理想化看待,当研讨课也成为了OO这门重课之中的一个压力点时,我感觉其效果未必就会有早年不讨论的好,所以从我个人角度来看的话,还是更希望研讨课能把占比放低一些,我个人的理想研讨课占比程度应该也就到5%。
3.希望BUG修复阶段能新增助教审核通过或不通过以邮件形式通知的功能,对时间安排比较紧的人来说不知道什么时候审核通过确实是一件非常麻烦的事,还得时不时上网页看一眼,弄个树莓派抓包来自己手动搓邮件来起到通知作用到也可以,不过网页真的允许频繁访问吗。
4.我认为到OO课后期就已经可以适当向同学们介绍AOP方面的知识作铺垫了。相比较于软件学院,计算机学院在大三之前开发类课程资源非常匮乏,所以在为数不多的开发类课程链中,是不是可以考虑在每个开发类核心专业课程的学期末为下一个阶段的开发类课程开个头,我在进行数据库课程学习中能够非常明显地感觉到同学们在开发方面,基本是选择前端的成员居多,大家对于后端开发都有着陌生感,我认为在OO课后程就可以为大家学习后端开发开个头了,而最好的方式莫过于系统性的介绍AOP开发思想来启发大家对后端开发相关知识的学习(如此重要且复杂的编程思想竟没有一门课程进行讲解真的是非常遗憾),一方面这能够促使大家对后端开发有初步认识,另一方面也能让同学们进一步了解J2EE的相关知识点,至于没有时间去讲这些东西的问题,个人认为后面几次研讨课可以适当取消掉,因为确实是感觉收获甚微(毕竟都快学期结束了再来讨论各种编程技巧蛮怪的)。

感想

作为一个21年OO第一周摸鱼结果寄了慌忙退课,22年OO又卷土重来的彩笔,一学期下来感受还蛮多的。一方面是会怀疑,而且是经常性的怀疑为什么自己当初第一周没多难的代码就寄了呢,思来想去我总结了俩原因,一是pre没做完,二是对JAVA不熟练,那为什么今年又做得比较顺利基本都是一天写完的呢,思来想去可能有三个原因,一是没上OO那年为了不浪费时间跟着21学了点软工,二是编译原理确实能修炼JAVA技术,三是连着两个学期加一个假期苦修了SpringBoot,硬要说的话可能还有一个原因就是我有一段时间用JAVA打leetcode(结果现在为了机试还得重操C++),说白了就是四个字“手不生了”。

22年以后上OO的同学们如果缘分到了看到这篇博客且刚好发愁写不出来代码的话,我建议看一眼吴际老师的博客,里面有一篇讲完成500行规模代码的文章,希望能对你有所帮助。如果说对JAVA的上手都有所困难的话,有两个办法,一是赶紧做pre(有理由认为JAVA上手都有难度应该是没做过pre),另外一个是抽空做Jetbrain academy的CoffeMachine课题,个人完成过这个,比较通俗易懂,而且细节足够丰富,链接如下:https://hyperskill.org/projects/33?category=2&track=17
我相信在一番努力之后会有好的结果的。

虽然知乎上对OO骂声不断,对于17年以前的OO我也甚感陌生,但我只能说现在的OO模式除了研讨课以外,在制度上已经趋于完备了,对课程有怨言之前我永远建议优先审视自身的问题。感激吴际老师在当初退课之余给我提的诸多建议,将我从摆烂佬正式拉回大部队,后面体制诡异的课程非常多,希望大家要珍惜OO这门来之不易,经过了数代人不断改良的好课,我也提一嘴好了,HansBug牛逼。

posted @ 2022-06-22 11:54  Horatio201  阅读(36)  评论(0编辑  收藏  举报