面向对象程序设计第四单元总结--UML建模语言

何牧-21101036 2024-06-15 12:14:36

对于 UML 的理解

在撰写第一单元的博客时,作业要求我们绘制自己程序架构的 UML 类图。当时我以为 UML 就只是一种用于绘制面向对象程序中各个类之间的关系的绘图工具,其主要作用为给人(编程者)提供一种对于程序系统的全局景象,以便进行程序设计开发。

在学习本单元的过程中,我逐渐有一个疑问:如果 UML 是对人类友好的,那为什么在 UML 的标准中还有这么多复杂的元素以及它们形成的结构?如果只是为了画图,设计例如 UMLClass、UMLOperation、UMLCollaboration 等类型的元素真的有必要吗?几个矩形再加上几条线不就可以完美完成图形的绘制吗?事实上,我觉得对于人类而言,只需要点、线、面这些几何元素就可以构成一幅图形,但是对于计算机而言这些或许并不够。回想当时学习数据结构的时候,我们经常会在草稿纸上绘制树、图、链表这些数据结构的草图。我们在绘制这些草图的时候,确实纸上只需要有几个圆圈几个箭头,但是如果要让计算机去实现这些数据结构,就不仅仅只有这些几何元素了。有些人可能会说,那不对啊,比如说计算机当中的其他绘图软件,他们存储的不就是各个几何所在的位置吗?不需要搞那么复杂啊!此时再反观 UML 这三个字母的含义:Unified Modeling Language,统一建模语言,也就是说,UML 本质上来说其实是一种语言,一种为了建模而生的语言,这个语言的目标不仅仅是为了记录几何图像。为了对程序设计中的复杂情况进行建模,必须要包含各种元素以及它们之间的关系,仅仅只有几何元素是绝对不行的。

本单元中,我们使用 StarUML 对各类的 UML 图进行绘制,而在增删元素的时候经常会发现,某一个元素虽然在画布中被删掉了,但是却在右侧的导航器中仍然存在,并且在项目的 mdj 文件中也仍然存在。这种不一致性一开始让我相当困惑。后来偶然有一次在进行某种操作时 StarUML 询问我要不要把这个操作同步到图(diagram)中,我才意识到 StarUML 中的视图实际上只是模型的一部分,我们所看到的图像并不是完整的模型,它只是给人类理解这个模型提供的一种途径。真正完整的模型保存在 .mdj 文件中。这更加印证了 UML 是为了建模而生的一种语言,显示几何图像只是用于观察模型的一种方式。

本单元作业架构设计

大致设计流程

在进行本单元的架构设计的过程中,我先设计出了一个基本的 UML 类图模型,然后基于此编写各个类的代码,最后再向 UML 类图添加属性、方法、参数等等元素。

具体设计过程

本单元要求实现一个图书管理系统,能够完成用户的借阅、预约、查询等需求。

在题目指导书的描述中,提到了以下这些地点:

  1. 书架(也叫图书存储处、与后面的 “书架” 区分)

  2. 预约处

  3. 借还处

  4. 飘流角

因此,我首先就对这四个地点进行了建模,分别建立一个类;

然后由于这些地点应该都是图书馆的一个部门,因此先设立图书馆类,然后再设立一个 Department 接口;

上述四个地点对于图书馆类来说是组合关系,即只有图书馆存在时这四个部门才能存在,这些部门不能单独存在;同时上述四个地点都属于部门,因此都实现了 Department 接口;

新增一个 Student 类,用于代表来借书的学生;

注意到不管是学生还是四个部门,其都会存储书籍,因此抽象出一个书架类(非图书馆的那个书架部门)用于专门存储书籍。该类与学生类、图书存储处类、预约处类、借还处类以及飘流角类都是聚合关系。

有了书架类以后,还需要书籍类用于代表一本书,由于书籍可以摆放在书架上,也可以单独存在,因此该类与书架是单向关联关系。

最后还需要图书预约类用于存储用户对某个图书的一个预约,该类与书籍类、学生类有关联关系,与预约处类有聚合关系。

上述部分是初步的架构设计,设计中只有程序需要包含的各个类以及它们之间的关系。

接下来编写代码,以书籍类为例子,对题目中的需求进行分析,其应该包含了如下这些属性:

 private BookType bookType;    //书籍类型:A,B,C,AU,BU,CU
 private final String bookId;  //书籍名称(ID)
 private int borrowCount;      //借还次数,为了让书籍转正(完整借还一次才+1)
 private Student donator;      //捐献者,只有漂流处的书才有该域(为了给捐献者加信誉分)

设计完属性后,再考虑该类需要给其他类提供的接口方法:

 public Book(BookType bookType, String bookId); //构造方法
 public BookType getType();    //各种 getter 方法
 public String getId();        //各种 getter 方法
 public int getBorrowCount();  //各种 getter 方法
 public Student getDonator();  //各种 getter 方法
 public boolean isFormal();    //查询是否是正式书
 public void borrowCountOnce();//完成一次完整借还以后调用,借还次数+1
 public void upgrade();        //对当前的书籍进行转正操作

最后编写上述方法的方法体,代码编写的步骤就算完成了。

完成了代码编写以后,把每个类的各种属性以及方法填写到类图中,完成类图的绘制:

架构设计思维演进的过程

U1:第一单元编写的程序最接近于我们以前的程序训练过程:单线程、算法驱动。在这一单元的学习过程中,我更多的是去关注如何把脑中所想的算法转化为面向对象程序。虽然说各种类的层级关系(比如说表达式由项构成、项由因子构成)体现了面向对象的思想,但我其实并没有特意关注程序设计过程中面向对象的那一部分,我只是把面向对象作为一种工具来使用。

U2:在第二单元的主题是电梯调度,特点是多线程、设计模式导向。我在初期的架构设计中就有意识的以面向对象而非面向过程的思维方式来进行设计。在架构中使用了非常多面向对象的特性以及设计模式:比如说用工厂模式来制造电梯、用单例模式来处理输入输出、用消费者生产者模式来处理请求的分发以及接收。虽然说在后续的编程过程中基本上一直都处于修并发 bug 的状态,但是前期的这种面向对象思维训练我觉得对于我面向对象思维的提升是很有帮助的。

U3:第三单元的主题是规格化设计,在这一单元中我们主要做的事情是根据 JML 规格来编写各种方法。虽然说本单元我们并没有直接从零构建起一个架构,但是在为已有的架构编写代码的过程中,我们也能够体会到一个好的架构应该具备哪些特点。除了对于面向对象思维的进一步思考以外,我也了解到了 “契约式编程” 这一编程方式。

U4:第四单元的主题是 UML 通用建模语言。这一单元让我们能够站到更高的角度上去思考规划我们的架构:先抛开代码、抛开 java、抛开任何的具体实现细节,思考为了实现某一个功能,我们应该设计怎样的程序系统,设计哪些模块,以及这些模块之间应该如何互相协作。这一单元让我体会到了面向对象编程的实质。

测试思维演进的过程

总的来说,在这个学期的 OO 课程作业中,我采用了以下这些测试方法:

  1. 面向固定数据对整体程序测试:

    我们在第一单元、第二单元中使用的测试方法,当整体程序完成以后给定一个固定的测试数据,然后观察程序的整体输出是否符合要求。

  2. 面向固定数据对单元进行测试:

    我们在第三单元中使用的测试方法,让某一个类或者某一个类的某一个方法进行单步的状态转移,查看前后的状态变化是否符合规约。这种对于某个程序单元的测试方式往往能够在前期就发现问题,而不用等到整体程序全部构建完以后再进行测试。

  3. 面向动态数据进行测试:

    我们在第四单元中使用的测试方法,根据程序已有的输出情况来决定后续的测试数据序列,这种测试方法我认为其相比于固定数据来说灵活性更强,更符合我们对现今的软件系统的需求。

课程收获

  • 逐步构建了面向对象思想

  • 有了中型项目的代码编写、组织经验

  • 初步入门并发编程、了解并发 bug

  • 学习了 JML、UML 等业界的通用标准

  • 学习了很多 Java 语言特性

  • ......

...全文
68 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧