2021 BUAA OO UNIT4 总结及课程总结
第四单元作业的架构设计
整体的输入输出设计如下图。
- 首先,由课程组下发的包解析mdj文件,得到一组
UmlElement...
- 输入
UmlElement...
,构造出1个MyUmlParser
-
MyChecker
对MyUmlParser
进行模型有效性检查 - 如果模型有效,则根据不同的
Query Command
对相关的图进行查询
其中,我的MyUmlParser
构造逻辑是这样的:
一共有22种UmlElement
,包括UmlClass
, UmlCollaboration
, UmlStateMachine
等。
这些UmlElement
之间存在着一个类树的层次关系。比如说UmlParameter.parentId
就一定是UmlOperation.id
。我自己总结出的层次结构如下3图(箭头由UmlElement A
指向UmlElement B
表示:A, B
之间存在B.parentId
为A
的关系)
构造时,先addElement
储存到各自的容器中,再进行解析工作(比如解析继承关系、关联关系等等),按照由底至上的顺序解析。
比如,解析状态图时,先从最底层遍历HashMap UmlEventMap
,把前置triggers
的信息补充到相应的MyUmlTransition
中。由底向上,得到一个完整的MyUmlStateMachine
。具体的逻辑看代码。
附自动生成的UML图
四个单元中架构设计及OO方法理解的演进
1、第一单元初识面向对象,架构的idea是基于求导数学知识的理解而得到的。先考虑有什么对象(表达式、项、因子),再考虑对象与对象之间的关系(基于求导法则带来的关系)、考虑如何管理对象及对象有什么行为(如何解析、构造、存储、使用),最后总结出整个解决方案的流程(解析输入 -> 各对象的构造与管理 -> 求导 -> 结果优化 -> 输出)
2、第二单元引入了多线程(并发)及调度机制。重点在于识别线程及其共享数据,建立线程安全的协作结构。我运用了生产者-消费者模式(站在前人的肩膀上开展工作总是能走少很多弯路),同时为保证线程安全花了不少心思。
3、JML规格为我第三单元的架构(核心在于图的邻接表结构、图的动态构造及维护)提供了主要思路。我的代码重点在于根据功能及性能需要增加中间数据模型及中间行为(比如说增加了对中间状态的缓存)
4、第四单元引入了UML模型,比之前的任何一次作业都多了更多不同类型的对象,因此构造层次、对象之间的关系更为复杂。数据结构上,由于抽象出来之后,存在一些图结构(包括树、有向无环图等),第三单元的架构给了我挺有用的参考。
四个单元中测试理解与实践的演进
没有能力设计并实现简易评测机,也没有渠道合作测试,我的测试都是偏手工+黑盒测试,因此代码bug还挺多的。
1、第一单元
手工+黑盒的测试,重点在于对边界test case的设计。
对二八原则有了实质性的理解:“80% 的软件缺陷常常生存在软件20%的空间里” -- 在自测和中测环节,我的bug在WF判断中频发:因递归下降造成的数组越界、解析提前结束、解析本应结束但继续读字符。后来的强测和自测,我确实也是在WF判断中翻车了
2、第二单元
多线程bug的定位(借助一些工具,如Jprofiler),如何在多线程中debug,待暑假后补充。
3、第三单元
第三单元引入了Junit这种测试方法,但是我对Junit的使用还停留在熟悉和尝试的阶段。
这一单元,性能测试很重要。如何提高性能,在一番修bug之后,我得出两种方法:一是关注时间复杂度,改进算法;二是增加对中间状态的缓存。
最近参加的一个MS模拟面试,里面有提到关于手撕代码的一个很重要的地方。只给一个问题:“给定一个长整型数组,如何高效判断里面有无重复的数”,怎么样才是一个好的回答呢?
哈希的思路挺简单的,但还有别的。
在手撕时,不妨换位思考,变成一个测试者:
- 函数定义好后,输入是什么,要给出输入检查
- 数据范围(数组有多长,数组几TB那怎么处理)
- 在什么环境下(简单硬件?分布式?网络?)处理这个问题。
不同情况都有不一样的解法。在面试官讲解完后,我觉得这一套东西其实我们oo课设也有关注到部分(除了考虑环境)
4、第四单元
手工黑盒测试为主。
课程收获
架构究竟是什么,它藏在我的代码项目中。
如果有人问我:这个单元的作业,你是怎么做的?我会这么回答:我构造了哪些类,这些类是怎么从输入中得到信息构造出来的;类和类之间的关系是什么,类和类划分为什么层次,类各自有什么行为(operations);最终结果是经过怎样一系列的处理得到的。(数据抽象和行为抽象)我为什么要这么设计解决方法,从中参考了什么经典的设计模式,可以在哪里改进。
我在想,架构是这些吗?那放到工业领域,那些资深的架构师,他们做的是什么呢?这几个问题,我还没有答案,我也会带着这些问题在CS的后续学习中继续探索。
同样的,如果有人在面试的时候问我,请说说你对面向对象编程的理解(https://www.zhihu.com/question/32085928)
我还没有一个至少成型的回答,但我可能从这些方面结合我的4次作业说一说。
面向对象程序语言有一些特别的语法和概念,“抽象,封装,继承,多态”,这些是来辅助我们进行面向对象编程的。
类class是我们对问题分析后抽象出来的东西,将数据和行为(统称为类的成员)捆绑在一起。在对类进行设计时,我会先考虑设计什么数据结构(有什么属性field)来实现它的各种行为(method/operation)
我们可以创建类型的实例,不同的实例包含不同的数据,从而其表现出来的行为也会不同,尽管其代码是一样的。
封装,通过关键字public, private, protected,使得类的成员得以有选择性的暴露,一些成员只在类型的内部使用,被称之为私有的(private),一些成员可以被派生类型使用,称之为受保护的(protected),一些成员可以被任何东西使用,称之为公开的(public)。
继承可以从一个现有类型派生出新的类型来,派生类继承了基类的所有成员,也可以新增只属于自己的成员。在任何情况下,派生类类型的实例可以被当做基类类型的实例来使用。
虚方法为派生类修改基类的行为提供了一个途径,通过重写(override)虚方法可以修改基类某些方法的行为。当派生类实例被当做基类实例来使用时,这一行为的区别将会被体现出来,这种在运行时不同类型的实例在同样的代码中呈现出完全不同行为的现象被称之为多态。
在实际开发时,有一些好用的代码复用的技巧被提炼成为设计模式,比如。。。
有遗憾的地方,这个学期跟以往的每一个学期都很不同,身心因为客观主观的原因只能“能做多少尽力多做一些”。很喜欢oo课的模式和氛围,遗憾的是我一直调整和适应,但拿不出最好的身心状态完成每一周的不间断的学习,希望在暑假把落下的重要的补回来。
三个具体改进建议
1、老师讲课我不容易听明白。可以提前上传PPT让学生预习,同时上课时我可以打开PPT对照着听。
2、增加多线程的预习部分。
3、PPT制作:在复习和回顾PPT时,感受不友好,问题在于:制作没有层次(希望可以明细为类似章、节、条的树状结构);现在的pdf版本不如ppt版本,因为存在内容上的覆盖;建议ppt上的问题给出相应的答案