面向对象第四单元总结&&学期总结

面向对象第四单元总结&&学期总结

一、本单元作业架构设计

在本次作业中,设计上分为两个阶段,第一个阶段是第十三、十四次作业,其在于对UML的建模与查询方法的实践,重点在于建模,第二阶段是第十五次作业,其要求在所建立的模型的基础上,对模型的有效性进行检查,重点在基于之前的设计对功能进行拓展。

1.1 UML成员及关系

1.1.1 类图结构

UML类图具有以下的基本元素,按元素类和关系类列出:

  1. 元素类
    1. UmlClass
    2. UmlInterface
    3. UmlOperation
    4. UmlAttribute
    5. UmlParameter
    6. UmlAssociationEnd
  2. 关系类
    1. UmlGeneration
    2. UmlInterfaceRealization
    3. UmlAssociation

其中顶层元素有UmlClassUmlInterface两种

次级元素有UmlOperationUmlAttribute

次次级元素有UmlParameter,其只从属于UmlOperation

UmlAssociationEnd是一个比较特殊的存在,其用于作为UmlAssociation的端点,可以引用UmlClassUmlInterface

而对于关系类的元素来说,UmlGeneration的两端只能为两个顶层元素中的同类,UmlInterfaceRealization只能由UmlClassUmlInterface进行继承。

在继承、实现时,除了直接继承和实现,我们还需要考虑间接的继承和实现。

1.1.2 顺序图结构

UML顺序图中也具有多种元素,按照画布类、实体类、交互类三类列出如下:

  1. 画布类
    1. UmlCollaboration
    2. UmlInteraction
  2. 实体类
    1. UmlLifeline
      1. UmlAttribute
    2. UmlEndPoint
  3. 交互类
    1. UmlMessage

顺序图的关系较为简单,其中只有两层画布,顶层为UmlCollaboration,下含UmlInteraction

其中则只有UmlLifelineUmlEndPoint两类相互发送消息的实体与复杂多样的UmlMessage

1.1.3 状态图结构

UML状态图中的元素可以按照画布类、状态类、转移类列出如下

  1. 画布类
    1. UmlStateMachine
    2. UmlRegion
  2. 状态类
    1. UmlPseudostate
    2. UmlState
    3. UmlFinalState
  3. 转移类
    1. UmlTransition
    2. UmlEvent
    3. UmlOpaqueBehavior

状态图的结构与顺序图类似,但是在转移是会有副作用,也就是UmlEventUmlOpaqueBehavior

1.2 需求分析

本次作业中,三种图片之间几乎不存在耦合,是三个不同的模型,可以分别分析

1.2.1 类图需求分析

类图需要进行的查询是8条指令

  1. 模型中一共有多少个类
  2. 类的(直接继承)子类数量
  3. 类的(仅自己定义的)操作数量
  4. 类的(仅自己定义的)操作可见性统计
  5. 类的(仅自己定义的)操作耦合度统计
  6. 类的(含继承类而来的)属性耦合度统计
  7. 类的(之间或间接)继承的所有接口统计
  8. 类的继承深度

1.2.2 顺序图需求分析

顺序图的查询有3个指令

  1. 查询某个Interaction中的Lifeline个数
  2. 查询某个Interaction中的Lifeline对象的创建对象
  3. 查询某个Interaction中的Lifeline对象收到了多少个Found消息,发送了多少个Lost消息
    1. Found为来自EndPoint的消息
    2. Lost为发送至EndPoint的消息

1.2.3 状态图需求分析

状态图的查询有3个指令

  1. 查询某一状态机中一共有多少个状态(包含InitialStateFinalState)
  2. 查询某一状态机中的某一状态是否为关键状态
  3. 查询某一状态机中引起两个状态之间(直接)迁移的所有触发事件

1.3 架构设计

对于每一类的图,我们都配备一个工厂类,由工厂来生产该类图的结构

1.3.1 类图架构设计

类图中需要重要体现的结构是包含、继承、实现、关联四种关系,而类图中有以下几种情况包含这一关系

Class -包含-> Attribute
Class -包含-> Operation
Interface -包含-> Attribute
Operation -包含-> Parameter
Class -单继承-> Class
Interface -多继承-> Interface
Class -多实现-> Interface
Class -关联-> Class
Class -关联-> Interface
Interface -关联-> Interface
Interface -关联-> Class

所以对于类、接口、方法三种类需要重写,且关联两端的元素可能是类也可能是接口,所以其需要拥有一个共同的父类或接口。

1.3.1.0 共同父类设计

类和接口具有一样的共同的属性:

  1. ID号
  2. 名字
  3. 属性
  4. 可关联性

所以需要围绕上面四个属性来设计配套的方法

1.3.1.1 类设计

类在除了共同的父类属性之外,还有方法、子类、父类、实现的接口等性质,所以类还需要设计容器来存放这些属性

1.3.1.2 接口设计

接口还具有继承的接口这一性质

1.3.1.3 方法设计

方法唯一具有的关机是包含关系,其会具有传入参数和返回值

1.3.2 顺序图架构设计

顺序图的设计重点则是包含与消息

Collaboration -包含-> Interaction
Collaboration -包含-> Attribute
Interaction -包含-> Lifeline
Interaction -包含-> EndPoint
Interaction -包含-> Message
LifeLine -Message-> EndPoint
LifeLine -Message-> LifePoint
EndPoint -Message-> EndPoint
EndPoint -Message-> LifePoint

LifeLine 和 EndPoint 都可以作为消息的起始/终点,其需要具有一个公共的父类或接口

而Message会区分发送与接收的信息存入这一公共的接口中。

1.3.2.0 公共父类设计

LifeLine和EndPoint的共性只有ID和消息两种

1.3.2.1 LifeLine设计

LifeLine除了具有父类的特性外,还具有创建着这一属性

1.3.2.2 EndPoint

EndPoint没有别的性质

1.3.3 状态图架构设计

状态图实际上是一个有向图结构,其节点为State,边为Transition,而边上带有事件和副作用

所以状态图设计为一个只具有包含结构的图结构,重写State相关的类,加入出边容器和入边容器,其储存的对象为重写的转移类

重写的转移类中具有触发事件与副作用

1.5 第二阶段需求与设计

1.5.1 R001-元素名字为空

在属于类图的元素中除了以下几种元素之外,其余元素的name字段均不能为空

  • UMLParameter(Direction:Return)
  • UMLAssociation
  • UMLAssociationEnd
  • UMLGeneralization
  • UMLInterfaceRealization
实现思路

获取所有的UmlElement,对上述五种进行单独处理,遍历其余各种UmlElement,检查姓名是否为空。

1.5.2 R002-属性名字重复

在一个类中,其所有的Attribute和Association另一端End所构成的元素集合中,不能出现重名元素

实现思路

通过一个HashMap<String,Integer>容器,对于所有的名字进行统计,在完成统计后,找出容器中所有出现次数大于1的名字,其即为重复属性的名字。

1.5.3 R003-循环继承

类或接口的继承关系中存在循环继承的情型。

实现思路

对于类而言,其仅能进行单继承,所以所有类构成的继承图仅可能为若干环和若干链作为分支的图。可以使用链表判环算法来检查其是否有环。

但是对于接口而言,其具有多继承的能力,其构成的继承图就是一个普通的图。需要对于每一个接口使用dfs来判环

同时,需要由工厂类给出支持,穿出所有的类和所有的接口的容器。

1.5.4 R004-重复继承

类或接口(直接或间接地)重复继承了同一个类或接口

实现思路

首先明确,类由于单继承限制,是不可能出现重复继承的情况的,唯一可能的情况是某一父类继承了自己,但是在进行R003检查时被检查出来,不会进入R004

所以对于重复继承来说,只需要对于接口进行重复继承的检查。

重复继承的检查,采用bfs遍历,如果在bfs遍历的过程中,检查到了重复的接口,那这一接口便存在重复继承的情况。

在检查的过程中,需要维护一个HashSet的引用,保证对于每一个接口,只进行一次检查。

1.5.5 R005-接口不可见

所有接口的属性都需要是public

实现思路

对于所有的接口元素进行检查,如果属性不为Public,即抛出异常

1.5.6 R006-LifeLine引用不同Sequence属性

每一个LifeLine引用的Attribution都需要是同一Sequence内定义的

实现思路
  1. 需要在工厂类中将Attribute加入Lifeline中引用。
  2. 获取LifeLine的实体,检查Represent的Attribute的ParentID和Lifeline的ParentID是否相同。

1.5.7 R007-LifeLine在销毁后收到消息

Lifeline不能在Delete消息之后在收到消息

实现思路

对于每一个LifeLine,遍历其收到的消息列表,当检查到第一个销毁信息时,判断此时是否已经到达消息列表最后一个,如果不是,则代表在被销毁后收到了消息

1.5.8 R008-FinalState存在迁出

FinalState不能有迁出行为

实现思路

获取到所有的FinalState,检查其toTransition的数目

1.5.9 R009-状态具有两个相同条件的迁出

同一个状态的不能有条件相同的迁出

  • 如果存在一个状态的所有的迁出 Transition 的所有触发事件(Trigger)中有两个name字段字符串相同的 Trigger,那么这两个 Trigger 所在的 Transition 必须拥有不为空 且逻辑上不能String.equal()成立的守护条件(Guard);
实现思路

​首先需要获取所有的状态

​对于所有的状态的迁出Transition进行遍历,使用O(n2)的方法来一一对比

二、设计思路的演变

2.1 第一单元

在本学期的第一次作业中,我就体会到了设计的重要性。

在完成第一次作业时,并没有对与先对作业架构进行设计,而是直接上手开始编码,导致编码的思路一直是最先想到的思路,没有得到优化改进。糟糕的架构和思路导致代码非常复杂,同时在编写的过程中,由于处于边写边构思的状态,所以在编码时效率低下且容易出错,每次发现一个问题,就需要进行局部重构。第一次作业完成时代码量很大,但是其中有很多冗杂的部分。

但是第一次作业的效果并不好,在强测、互测中都被Hack了很多次,体现了屎山的不易维护性。

第二次作业我就选择了全体重构,同时面对下发的需求,先进行设计的构思并撰写文档,完成后再开始编码。

先对需求分析并进行设计后,效率得到了很大的提升。第一次作业虽然拿到需求就开始编码,但编码的过程足足消耗了3天半的时间。而先对需求分析和设计之后,虽然分析设计的过程需要大约一天的时间,但是面对已经构建好的框架进行编码,同样也只需要一天左右的时间就可以完成。

从第二次作业开始,我就遵循了先分析构思,再编码实现的流程。

2.2 第二单元

在第一单元中总结出的先分析构思,再编码实现的流程在第二单元中也同样的好用,但是在第二单元中暴露出来分析构思环节中存在的问题。

在第一单元中,我采用的构思仅仅触及到架构的层面,分析所涉及到的数据,根据其归属和操作对其分类,并将其封装为多个对象,再根据对象之间的关系来决定类的组织。完成到这一步构思部分就结束了。而对于每个类之中的方法的实现,仍然是在编码的时候再决定。

在第二单元中,这一因素就导致了我的电梯调度算法,是在所有架构的编码都完成后,最后再来对函数进行的补全。由于在设计时并没有考虑算法的适应性,架构的限制导致了有的算法实现起来并不容易,在实现对这一架构适配的LOOK算法的过程中出现了失误。第二单元的三次作业每一次都会在强测中出现一个点的超时。

2.3 第三单元

在第三单元中并不需要对架构进行太多的设计,但是这一单元需要对一些算法进行设计,结合上一单元的经验,这一单元将具体需要实现的算法也加入了设计的部分。同时在对拍器的帮助下,实现了第三单元的无伤通过

三、课程收获

本学期的OO课程给我最大的收获,就是对于一个较为复杂的需求进行解构、连接、逐个击破的能力和实践。

在这个学期之前,接触的代码,都是分散和小量级的代码,并没有模块和耦合这一说法,同时这些代码只写一次,并不会有增量开发的需求。

但是在oo中就不一样了,每次作业都是一个小的系统,需要自行设计一些模块去构建,还需要控制模块间的耦合度,使在增量开发的时候最小化的最模块内部进行修改。

每一次作业的体验可以说都是全新的。

四、建议

  1. 希望能在作业中加入一些鲁棒性的内容和考察,例如在第三、四次作业中的官方包对于非法输出的实现。
  2. 希望在每一次作业的提示部分中,增加一些对于设计模式的建议和应用提示。
  3. 希望能引入一些开发流程相关的内容。
posted @ 2022-06-27 10:32  鲁文澔  阅读(49)  评论(2编辑  收藏  举报