BUAA 2021春季学期OO课程第四单元(UML解析)工作总结

本单元作业架构设计

本单元感觉对层次化设计的要求不高,没有需要我们去明显注意的层次化逻辑,而大部分的继承和关联关系以及包含在官方给出的包中。

本单元下,我直接采用了课程组设计的接口进行处理。根据功能分别分为CheckerStorerGetter三个主要的工具类和一个用于生成Storer的类Generator

  • Generator中分顺序图、类图、状态图三种图的形式进行混合解析,并将其转化为Storer中的存储形式。不同的元素类型对应了不同的解析方法。解析顺序随机,因此我分为两次进行遍历,第一次遍历不涉及元素间的关联关系,单纯将元素按ID和类型等自身因素进行解析并存储,第二次遍历在第一次遍历的基础上进行关联关系的建立。
  • Storer中存储了基本的图信息,并在此基础上存储了大量的Map用于加速查询
  • Checker主要负责对Storer中存储的内容进行检查,从而完成查询的功能需求。同时,Checker内部也持有相应Map用于记忆化搜索。
  • Getter主要负责对Storer中存储的信息进行提取和解析,并对Checker提供清晰的接口,比如提取某个类的所有父类/接口等。具体的解析逻辑放在Getter中,Checker只需要调用Getter即可。

本单元架构中大量以UmlElement这一顶层接口作为参数,而只在特定的情境下将其转化为更为具体的存在。这带来一个优点,即方法的通用性加强,一个方法能够用于多种情境。但是也有一个缺点,就是对变量功能的判断严重依赖于变量名。对于解决这个问题,可以采用泛型方法来实现同样的复用性。

本单元两次爆雷,都是因为对题目意思的理解出现了偏差,而没有被弱中测检查出来。这使我深深意识到正确且无歧义地传达自己的需求是多么重要。如果一个对于规格的描述能被两个不同的人按其各自的知识体系理解成两个不同的意思,那么这个描述就存在着风险。(怀念JML)

第十三/十四次作业

主要任务是图解析,主要重视性能和解析正确性即可。

我的一个失误在于,没有理解题目的意思:

对子类中的某个属性Attribute,如果这个属性是从父类继承过来的,那么这个属性属于父类,需要输出的是父类的名称而不是子类的。我事后觉得这个“属于”概念就非常模糊,子类继承了父类的属性,难道这个属性就不属于自己了吗?而且这个理解上的失误也没有被中弱测识别出来,而是在第十三次强测里大面积爆雷,40分把我抬走。

第十五次作业

主要任务在于错误Uml的识别,需要重视图算法的正确性。

我数据结构的基础不牢固,导致很多的图算法不理解,纯靠着自己的理解在写。这使得很多种不同的情况没能考虑清楚,则导致了性能和正确性方面的各种问题。同时也存在理解上的问题,比如没有考虑到一个接口多次直接继承另一个接口,然后又爆了一个点。

架构设计和OO方法理解的演进

第一单元:表达式求导

第一个单元强调“对象”性。对于一个简单且普遍的表达式解析问题,课程组要求我们从对象拆解的角度去考虑问题,而不是一个一个字符地去解析。而这个单元的架构设计也反映了OOP和POP的本质区别,OOP讲究拿一个具有复用性的对象去解决复杂的问题,其复杂度和问题的规模并不一定成正比。而POP的方法则会随着表达式的进一步复杂化而变得更加复杂,直到超出人类正常能够理解的范围。这个单元中强调了OOP的复用性

第二单元:多线程

第二单元则是第一次在我们的官方学习过程中引入了多线程编程的概念,并将其和OOP进行了融合。这个单元最大的特点在于通过多线程的情境说明了设计模式的重要性。OOP的设计模式的某些优势在单线程的情境下很难暴露出来,而在多线程情境下则很显著地强于POP的方式。如果说第一单元还能靠POP苟活,那么第二单元就必须去深入探讨对象的性质了。这个单元中对于OOP的理解就更为深化,必须考虑到代码的复杂程度,而需要进行解耦,以保证数据的相对独立性。

第三单元:规格化

第三单元是我个人体验最好的一个单元(因为我语文不好)。基于JML给出的规格冗长,有时候甚至超出了实际编程的代码长度。它全面吗?很全面,能够把几乎所有细节都解释清楚。但是它实用吗?我觉得在实际工作中如此复杂且详细地去进行描述所需要的时间和精力都是不一定合理的。而这个单元指出的一个OOP的重要问题就是规格化的重要性,只有有效的规格才能诞生有效的代码,才能在复杂度陡增的情况下依然保持较高的可拓展性和可Debug性。

第四单元:UML

第四单元考察阅读理解能力,我阅读理解能力不行,爬了。剩下的部分就和第一单元差不多,我觉得课程设置的主要目的可能并不是考察我们的编程能力,而是希望我们自己去学习UML的.mdj文件的构造机理和UML下的各个对象的含义。这个单元体现了OOP如何具象化地表示,表面上是考察对UML图的解析,实际上是考察我们如何将OOP的思想通过UML图的方式进行层次化可视化的表示

对测试理解与实践的演进

测试对我来说一直是一个非常尴尬的问题。为什么说这个问题很尴尬呢?因为我对自己对于题目的理解并不自信,有可能根据错误的理解构造了错误的样例,通过了本地测试但是依旧爆雷。因此我在构造样例时仅针对性能进行检查而不涉及逻辑。

对于逻辑的检测通常是基于对拍器和自动样例生成程序。依靠着数据轰炸和多方理解的矫正,对程序的BUG进行定位。但是这个测试手段严重依赖于样例生成的随机性,不能保证绝对的正确性。

而随着学习深入,我逐渐开始考虑程序的“函数测试”,即针对特定函数进行样例的构造,并且学习到了样例的构造逻辑(如何判断边界条件等),以及如何借助已有的JUnit、JProfiler等工具进行测试和性能分析。

课程收获

OO课给我介绍了一门以前非常反感的语言:Java。以前觉得Java非常繁琐,一大堆奇奇怪怪的类,跟C#一个样子。对于一个只学了C和Python的人来说,没有main函数的日子实在是太古怪了。但是随着使用Java的时间逐渐增加,我感觉Java非常友好,它的编程体验非常舒适。我能像Python那样快乐调包,又能像C/C++一样用{}宣誓人类的主权,同时Java的反射机制和IDEA的精巧设计也使得编程的过程非常Smooth。以前觉得C++啰里啰嗦的地方,在Java里得到了显著的改善,这得益于Java对OOP更加严格的支持。

同时OO课程带来的另一个收获就是让我窥见了大型软件项目的一角。这其中包括对于代码的静态分析(圈复杂度等),也包括对于规格的理解,以及如何从代码层面保证更好的拓展性和协作性。OO课程的要求加深了我对于代码的风格以及代码异味的理解,让我对于如何写出优美的代码有了更加科学的认识。CheckStyle,yyds!

课程建议

  1. 设计模式的内容不是很多。预习的时候就应该讲一些设计模式,而且应该把设计模式的理念提升到课程的设计层次,考察同学们对于设计模式的理解和掌握,将设计模式渗透到课程的要求中,而不要放任我们自己去写一些奇奇怪怪的架构(虽然有的时候性能会更好,但是无益于加深我们对于OOP的理解)。设计模式这么重要,是不是我们之后还另有一门课专门学习设计模式?(小声)

  2. 测试的训练需要加强。我们如何进行软件测试?如何科学地构造测试样例?如何提高测试的完备性?我觉得软件测试有一套科学的方法论,但是感觉课程明明对我们的测试能力非常demanding,但是却没有在课程中涉及很多的软件测试的理论。当然,软件测试一直是一个哲学的问题,或许是因为百家争鸣各有千秋,所以不好当做课程的内容?

  3. 对于课程组的指导书中的规格还是需要更加细致,反馈的机制也应该更加科学。一万个读者心中可以有一万个哈姆雷特,但是我们得保证只有一本指导书。虽然课程组现在利用讨论区答疑能够解决大部分的问题,但是讨论区中的大部分问题并没有被有效地归档,也没有反馈到指导书中(除非指导书写错了或是尤其模糊),这导致某些问题只对少部分人可见。这需要考虑到我们对歧义的敏感程度。作为一个读者,对于“A是B还是C”这个具有歧义的地方,如果在阅读指导书时认为“A就是B”,但是实际上讨论区的某个问题指出“A是C”,此时既然我对“A就是B”并不存疑,那么我就不会去讨论区再去找相应的问题,更不会知道“A是C”这个事实。因此希望课程组能够对讨论区中提出的问题及时反映到指导书中并进行通知推送,在可能具有歧义的地方进行标注,引导我们去讨论区特定帖下查看。

posted @ 2021-06-23 11:01  neumy  阅读(107)  评论(0)    收藏  举报