OO 第四单元暨总结性博客作业

第四单元UML架构设计

UML类图

  • 需求说明

最终需要实现一个UML类图解析器,可以通过输入各种指令来进行类图有关信息的查询。(保证所建模的类图模型均可以在Oracle Java 8中正常实现)

  • 架构设计

  • 类说明

这两次的作业架构几乎相同,所有数据结构均从MyUmlElement继承而来,每个类都有四个基础的属性:名称,id父结点以及类型,这样的结构便于统一传递MyUmlElement参数进行转化。DataBase里面装有所有解析的类别(attribute,operations...)便于统一进行建图与查找操作。

  • 操作说明
    • 主要操作在dataBase中。
    • parserInput实现对UmlElement到MyUmlElement各类的解析。
    • linkClasses,linkInterfaces,linkClassInterface,linkAssociation,linkAttrClass,linkOperClass分别完成类继承,接口继承,类实现接口,关联对端相连,属性与类相连以及操作与类相连。这些都是静态建图,只考虑了类或接口的直接继承和直接实现关系。
    • MyUmlClass中会将所有麾下的属性,操作,关联对象,参数,子类以及实现的接口记录下来。
    • 查找操作是基于这个类与接口的图进行dfs深度搜索。判重依据大多数是id,少量是name,其中存有dupMap的操作就会事先将重名的类或者操作或者属性记录下来。

UML类图、顺序图以及状态图

  • 需求说明
    • 本次作业,在上次作业基础上,扩展解析器,使得能够支持对UML顺序图和UML状态图的解析,并能够支持几个基本规则的验证。
    • 扩展类图解析器,使得可以支持对UML状态图和顺序图的解析,并可以通过输入相应的指令来进行相关查询。
    • 在所解析的UML模型基础上,按照规定的规则检查模型中是否存在违背规则的情况,并输出相应信息。
  • 架构设计

本次的架构设计是上一次架构设计的延伸,由于UML类图部分并没有很大的变化,所以有关classDataBase的部分并没有什么改动,只是将UmlStateMachine以及UmlInteraction的部分按照UmlClass部分进行了一个套用与实现。

  • 状态图模型:stateDataBase负责状态图的连接,其主要数据结构存储在MyUmlStates和MyUmlRegion中
  • pseudoState和finalState当做UmlStates来看待,只不过名字会替换成MyString中自己定义的对应类的名字。
  • 后继状态采用bfs来实现,直接针对建好的state图进行查找就好。
  • 顺序图模型:colabDataBase负责顺序图的连接,主要数据结构存储在MyUmlInteraction中
    • 参与对象是和所有lifeline进行ref的attribute的不同个数,这里实现的时候每次会先找到lifeline对应的attribute进行判重后计数。
  • 类图模型:classDataBase加入了对模型有效性检查的判断。
    • R001 只需检查当前class的属性以及对端的associationEnd的重名情况即可。
    • R002 由于成环只能是class之间或者interface之间所以只需要对继承关系对每个class或者interface进行dfs即可。
    • R003 对所有继承与实现形成的图进行dfs,如果发现有汇路,则说明该点S是重复继承了另一个interface或者class;之后换点进行dfs的时候,只要找到了之前找到的点S,那该点也一定是重复继承点。

四个单元中架构设计以及OO方法的理解

  • 第一单元:多项式求导

熟悉java语法,构造抽象层次并进行归一化处理

首先,“工欲善其事,必先利其器”。为了在oo这门课程中打下良好的基础,学习java语言便成了首要的环节。笔者首先大致浏览了java编程思想这一本书,对java的语法结构有了一个大致的理解。在这之后便是对面向对象机制的学习。尤其是在第三次作业中,表达式,项以及因子三个层次的概念逐渐明晰,而且求导运算可以被抽象为接口放到各个层次的类中,形成一个既有多态继承又有接口实现的求导树。同时表达式,项以及因子又构成组合模式,在同类项合并的时候组合模式的各层级又有交互。完成这样一个求导规则极大加深了笔者对多态的理解和应用。

  • 第二单元:电梯多线程

多线程的设计,同步与冲突的解决,多线程调试

这一单元的设计重在要理解java多线程的内部实现原理,包括每个实体从建立到消失的过程中各作用域在堆栈的可见期。多线程的调度问题主要来自不同线程同时访问共享变量的时候。访问时如何保证更改的同步性以及如何控制访问共享变量对象的访问顺序都是需要慎重考虑的问题。笔者在做此系列作业时,着重阅读了java编程思想和java concurrency这两本书籍,尽管这样在实际实现的时候仍然遇到了不少麻烦。如果说上一单元我们构建的是一个多态的静态图的话,这一单元我们就在构建一个动态的多个对象的时序图。为了使这个时序图系统运作正常,我们要将各个“子系统”(线程)的数据结构,行为以及对共享对象的访问设计得尽可能直接而简单,不要出现两个线程交互过多的情况,这样较为清晰地完成多线程的架构。同时,在这一阶段笔者接触到了工厂模式,单例模式以及观察者模式等等设计方法,这些方法也让我们体会到了多线程设计的精妙之处。

  • 第三单元:规格设计

按图索骥,架构协同与扩展

这一单元主要是让我们掌握如何抽象自己的架构并将其转变为一种“通用”的jml语言,同时训练我们能够把jml抽象的架构转变为真正的实现的能力。在程序员的实际交流时,通过规格交流远比通过代码和注释进行交流要方便准确得多,因为规格是程序员程序里逻辑的浓缩,规格可以很好的将程序语义确定化,减少对细枝末节的过分关注,从而大大加快代码语义的理解。本单元的三个作业中都是在给定接口的规则上面进行自己对规格的实现,同一个规格可以由五花八门的实现方式,但最终的结果仍然是一致的,这也体现出了规格的厉害之处。同时这次作业的架构扩展性也体现的淋漓尽致,从最简单的path到最终的railway system,每一次作业都是对上一次接口的继承和完善。虽然实际需求中几乎都是将寻求层层拆分为小的结构,类似railway system -> path的感觉,但是能够从小的结构预测能使用它的大的架构也是一个十分体现水平与能力的地方,它体现了一个计算机工作者对一种数据结构的理解和应用能力。这些都是值得笔者日后在学习工作中慢慢总结体会的东西。

  • 第四单元:UML设计

上帝视角,窥架构全貌

UML语言是对软件设计的抽象描述工具,它通过独有的代码和图示方式展示着程序自己的结构。与此同时,UML语言本身有他的数据结构和架构,所以解析UML语言既是一种很好的对多层次模型的抽象与建模,更是一个能让我们理解实际程序中各个对象在类图,顺序图或是状态图的关系的过程。UML的三种图结构教会了我们如何在不同的层次上面审视同一个对象以及对象之间的关系传递与变迁。

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

  • 第一单元:多项式求导

从简单单例测试到组合单例测试

第一单元的测试是透明化的白盒单例测试。在静态考虑了所有可能的结果之后就会将这次的作业较不错地做出来。在增加了多种求到规则后无非就是增加了单例可能的情况,只需要耐心进行实例构造就可以完美通过。

  • 第二单元:电梯多线程

分级的输出测试,逻辑约束测试

这一阶段的测试最显著的特征就是debug模式的失效性,因为你停住的只能是一个线程,而对另一个进程的进行情况完全未知。这种情况的测试就是对所有生成的调度情况进行检查,看其是否违背逻辑发生顺序,通过一个脚本程序进行判断。在判断多线程的发生先后情况时需要进行print调试,在print信息中加入类的层级以及线程id等方便区分的特征,观察他们的出现时序已达到观测多线程调度的目的。

  • 第三单元:规格设计

分层次的自动化测试

第三单元的测试主要集中在通过学习jml规格化工具调用smt进行自动化格式检查,JunitNG测试样例自动生成的检查。这里体现了java层次化测试的思想,即测试时只针对几个模块进行,缩小bug出现的潜在范围,加快测试进程。

  • 第四单元:UML设计

架构方面的对象关系,UML图有效性测试

UML图将类,类的状态迁移以及类之间的协作关系完整而清晰地呈现出来了。在构造测试用例时,要从整体类间关系考虑,构造出不符合java规定的反例进行测试。

课程收获

为期一学期的oo课程已然结束。回顾这一个学期的课程,真的是喜忧参半,自己在学习的心态上也经历了些许波动,下面分点来谈谈自己的课程感受。

  • 从面向对象的思想出发设计架构

首先作为一个非oi出身的大一没怎么练习编程的计算机新手,之前写程序的感觉就是循环循环再循环,标志位标志位再标志位,写出的程序大多冗长而没有清晰结构。但是在学习了面向对象思想的时候,在写程序的时候会自动将不同模型抽象出不同的对象,同时将这些对象进行纵向与横向比较,进而完成继承,组合以及实现的关系模式。这样每一次遇到一个实际的项目,我们就都会在脑海中抽象出来一张横向类比扩展,纵向深度扩展的UML图,这样撰写出的代码便有极大的规律可循。

  • 从对象调度的角度理解java进程

在oo课程之前,对线程的并发同步控制只停留在操作系统的pv操作中,并没有调试过很大的程序了按照顺序执行过一些列有冲突的需求操作。在进行电梯系列的额课程设计时,这个能力的培养就显得尤为关键。包括如何让cpu有效运行状态最大(轮询尽量小)以及如何修改架构及代码方式以使得最小的范围内存在同步冲突。这一系列作业的实现让笔者的java的控制流程与产生消失的流程有了深刻的了解和认识。

  • 从针对不同对象层次进行测试的方法保证测试效率

在面向对象和软件开发中,测试是一个必不可少的任务。为了能在oo测评中拿出高分,就要保证写出的代码能经历多个方面的易错点攻击。通过形式化规格的学习,我们了解到如何将千变万化的程序抽象成为同一种规格语言进行统一,如果针对这种规格进行测试,我们便可以较全面地穷举出潜在的bug位置,同时定位到一个简单的类,极大地简化了debug的难度和工作量。同时还有UML建模进行设计层面的检查,从总体上把握各个对象之间的关系,为构造测试样例提供了极大帮助。

  • 代码风格的提升

十分感谢课程组提出的代码规范性检查的要求。这个要求一旦硬性,笔者在写程序的时候便会十分注意代码可读性与质量。久而久之checkstyle报出的错遍越来越少,取而代之的是早已熟记于心的标准面向对象的编程习惯。这种习惯的养成就应该做到像这样无声无息但又令人印象深刻。

提出的三个建议

  • 在公开优秀代码的基础上进行优秀代码讲解

在笔者进行oo作业的练习中,开始的几次作业是真的想写出面向对象风格的代码,奈何笔者当时的水平有限,无法将对象从控制中完全抽离开来,同时对java库熟悉度不够,有很多自行造轮子的情况。笔者认为在各个阶段的起始作业更应该对该模块代码的品读环节,也就是说课程组在布置较难的作业时事先提供一些环境不同但是机理相似的代码,这样便于学生先从他人的优秀代码中吸取精华,便于后续开发。

  • 管理高工的助教能够尽可能与官方组同时发布消息

由于天生的院系背景和排课设置,大三下才修这一门课的高工基本已经没有像大二时对待计组或者操作系统时的热情了,不会有几个人会时刻关注规则是否更新。如果这时候助教不能及时在群里面通知一下,可能就会有的同学已经完成了本次任务,殊不知后来改动后源代码或者需求有所变动。这种变动虽然很细微,但往往对结果有着不可逆的致命影响,导致无谓失分。

  • 对上级实验和课下作业部分进行设计意图反馈

在完成每次课下作业或者课上实验时,没有一个很好的机会进行设计层面的交流,这样就造成了下一次在这次基础上进行设计的时候重构的太多。希望每一次作业之后助教和老师能把当次作业或者上机的训练意图说清楚,尤其是上机提供必要的反馈,因为每一次上机往往都是对新学习事物的第一次尝试,此时如果有错误没有及时纠正是会代入到后续的课下设计中的,这种做法就会大大增加重构的几率。

猜你喜欢

转载自www.cnblogs.com/pianomposer/p/11075086.html