OO第四单元总结

OO第四单元总结

​ 本单元是通过编写代码解析UML图,同时了解UML相关知识。

第四单元架构

​ 本单元的层次架构基本已经确定了,可以根据UML中的类型类编写相应的类。只是对于最底层的类型(event,attribute,Patameyer),以及一些描述中间过程的类(继承关系,实现关系,关联关系,transition等),我们可以不用实现。因此需要自己实现的类有MyClass,MyInteraction,MyInterface,MyLifeline,MyOperation,MyRegion,MyState,MyStateMachine。为方便实现MyInmplement中的方法,我还构造了一个Tools类。

先说每一个类内部的情况。一个上层的类除了应该记录自己的有关数据,还应该包含其下层的类,比如class中应该存有attribute和operation等。Interaction中应具有llifeline等。此外对于状态图中,每一个MyState中还需记录他能迁移到达的所有state,这是为了方便查找和构造出一个状态迁移图。我个人觉得这一部分大家的设计应该都差不多。

设计不同的地方在于对于一些较复杂的指令如何实现。比如像第一次作业里的计算类的属性耦合度,不只计算类自己的,那么如何把父类的属性计算进来就是需要考虑的了。

​ 由于在第三单元设计中很多指令体现了“维护”的重要性,我在这里也采用了维护的方式。以计算类的属性耦合度为例,在解析UmlElement[ ]的过程中,就在每一个MyClass中存好了他的所有属性,包括直接的,也包括通过类的继承关系得到的属性。这样在后面就可以直接拿过来用了。

​ 在本单元中,由于element之间没有明确的顺序,因此需要按一定顺序进行解析,无论采取哪种方式,都应该先得到所有的类,再去解析类中的方法和属性,但为了实现“维护”,我解析类图的过程会比这个还更复杂一些,具体如下。

​ 第一步:找到所有的class和interface,进而创建MyClass和MyInterface

​ 第二步:找到关于接口的继承关系,在这个过程中实现关于接口父类的“维护”(也就是说当一个接口A有一个父亲B的时候,要干如下几件事:1,A要存储他的这个父亲B;2,在B中存储一个子接口A;3,A还要存储这个B的所有父接口;4,A目前下辖的所有子接口也都通过递归的方式继承B和B的所有父亲,这里之所以说是递归是因为不仅A的直接子类要继承,A的间接子类也要继承。)

​ 第三步:找到类的属性和方法,创建MyOperation,在MyClass中存储他自己的属性和方法。

​ 第四步:找到所有的Realization,(也就是说当一个类A直接实现了一个接口B的时候,要干如下几件事:1,A中存储接口B;2,B中存储着类A)

​ 第五步:找到类之间的继承关系,并“维护”,与第二步类(比如,当类A继承类B的时候,要干如下几件事:1,A中存储父类B;2,B中存储子类A;3,A存储B的所有父接口,也存储B的所有属性(包括间接与直接);4,A目前下辖的所有子类通过递归的方式都存储B的所有父接口和属性,这里的子类与第二步中的类似,包含直接子类和间接子类)

​ 第六步,找到所有的Parameter,在MyOperation中存储它们。

​ 不得不说,为了实现“维护“真的耗费了我 不少脑细胞(x)。上面这六个步骤说起来简单,但由于一开始受到思想上的束缚,我并没有想着分这么多步骤,想把中间的几个重要步骤都在一次实现了,差点GG。

​ 当然,这只是类图的过程,顺序图和状态图并不太需要“维护”,而且顺序图和状态图的操作可以和上述步骤一起执行,整体上依然是六步。上面的6步也不全是固定的顺序,比如第六步就比较灵活。

有了维护,在处理指令的时候就简单多了,第一次作业的指令6和指令7就很好实现。但是到了第三次作业,维护方法又遇到了困难。上面的第二步和第五步涉及到了递归,在前两次作业数据是保证没有循环继承的,但是第三次作业不一样了,如果采用递归,就需要设置额外的约束条件,否则在递归时每一个父类调用方法时也会让自己的所有子类调用这个方法,造成死循环。而且在第三次作业中,”先建立好MyImplement,再进行check“,这就对维护式更不友好了。举个例子,对于循环继承,如果仅需找到错误,那在递归中一发现错误停止即可,但是由于要找到所有循环继承的类,因此MyImplement的构建过程不能随意停止,需要彻底完成,这对递归的考验是更大的。

对于顺序图和状态图,我认为没什么可以拿出来说的,那就不多说了。可能涉及到一些图论相关知识,都是打一下学的,拿过来用就好。

​ 最后虽然有惊无险的完成了任务,但是不得不说维护真的加大了我不少工作量。现在回头一看,维护在这一单元并不占优势。

​ 1,数据量并不大,构建和指令加一起不过500条,外加CPU有10s,就算不维护也不会出问题。

​ 2,消耗空间会变大,比如在每一个类中要存储他的所有父类,相比于只存储直接父类空间开销大(当然,同样因为数据量较小不会出问题)。

​ 3,第三次作业的check真的对维护不友好。

课程架构设计思维的演进

第一单元:递归新思维

​ 在这一单元我已经认识到为了实现多层括号,必须实现实现递归。但是在递归的时候又担心“递归无穷无尽”。最后我终于明白:递归只需要关注两件事:递归的停止条件,一个递归函数完成的时候它达到了什么样的结果。

​ 在这一单元中,最底层的是数字和x的幂函数,因此递归到这一层时就会停止,停止条件是可以实现的。

​ 同时,在这一单元中当一个递归函数停止的时候,他将返回一个表达式,这样递归函数的结果也就知道了。

第二单元:多线程的实现

​ 多线程在我看来其实就是互相通信沟通。无论是信号量,还是锁,还是其他的方法,都是一个线程向外界发出信息申请得到资源(CPU等);在得到资源之后又向外界发出信息,不让外界其他线程再占用资源;在放弃资源(CPU等)的时候再发出信号并唤醒其他线程。

​ 因此,要想让多线程的效率高,就应该尽量让共享资源在该发挥作用的时候发挥作用,当一个线程不需要某资源的时候应该尽量放弃,比如不应该把sleep写在同步块里。

​ 此外,为了保证安全,需要考虑死锁,我采用的方法是当一次需要多个资源的时候按一定顺序上锁,这样就不会存在一个线程拥有A,等待B而另一个线程拥有B,等待A了

第三单元:规范描述以及维护的重要

​ 首先,我学习了一种让代码“严谨”的方法。口头的描述并不能提出准确严谨的规范,甲方的需求总是千奇百怪的。JML提供了中准确描述需求的方式。JML只约束前提(required)和结果(ensuers),对实现过程并不关系,在严谨的基础上还给了程序员灵活的施展空间。但是其缺点就是“不说人话,读起来过于复杂”。

​ 其次,我意识到了维护的重要性,可以采用空间换时间的方式提高程序性能。

第四单元:维护不能瞎用

​ 在一些情况下维护并不适用,比如数据量较小,维护所需空间过大,或者数据中存在错误需要后续check时。(没错,就这一句话充满了辛酸的故事)。

测试理解与实践的演进

​ 在第一单元中想找到问题主要是通过测试极端数据,比如爆int,超多层括号,零次幂等等。

​ 在第二单元中问题变得“薛定谔”起来,有些问题是不能重现的,一旦发现问题就要赶紧记录下来。测试时的重点其实还是各种极端,比如突然有许多人从同一楼层进入,等时间间隔的来人等等。也可以查一下细节,比如电梯人数限制。

​ 在第三单元中最主要的是性能考察。qgvs这样的指令需要维护。

​ 当然,学习批处理等对测试的进行是有帮租的。

课程收获

​ 1.了解了git这种版本管理工具,再也不用担心改完代码有问题又改不回去了。

​ 2.学习了java程序语言,作为一种面向对象的语言,给我提供了一种除了面向过程以外的编程思维

​ 3.java中有许多工具类是不用自己重新编写的,我学会了自己查找资料利用现成的工具,“不要重复造轮子”

建议

1.我认为一个单元几次作业的迭代可以模拟程序员不断接受“需求”改进代码的过程,但是每一次之间的提升应该均匀一些,比如第一单元。

2.第二单元不同的算法都各有利弊,强测的数据决定了性能分的高低。我个人感觉这样有些问题。可以提前给出测试数据的大致状况,不至于让一些算法很强而其他算法很弱。

3.第三单元即使考虑了性能因素,也可能因为别人的数据量过大被hack,建议延长cpu时间

posted @ 2022-06-29 12:14  罗夏0324  阅读(24)  评论(0编辑  收藏  举报