2020春软件构造lab3实验报告
2020年春季学期
计算机学院《软件构造》课程
Lab 3实验报告
目录
1 实验目标概述 1
2 实验环境配置 1
3 实验过程 1
3.1 待开发的三个应用场景 1
3.2 面向可复用性和可维护性的设计:PlanningEntry 1
3.2.1 PlanningEntry的共性操作 1
3.2.2 局部共性特征的设计方案 2
3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案) 2
3.3 面向复用的设计:R 2
3.4 面向复用的设计:Location 2
3.5 面向复用的设计:Timeslot 2
3.6 面向复用的设计:EntryState及State设计模式 2
3.7 面向应用的设计:Board 2
3.8 Board的可视化:外部API的复用 2
3.9 PlanningEntryCollection的设计 2
3.10 可复用API设计及Façade设计模式 2
3.10.1 检测一组计划项之间是否存在位置独占冲突 2
3.10.2 检测一组计划项之间是否存在资源独占冲突 2
3.10.3 提取面向特定资源的前序计划项 2
3.11 设计模式应用 2
3.11.1 Factory Method 3
3.11.2 Iterator 3
3.11.3 Strategy 3
3.12 应用设计与开发 3
3.12.1 航班应用 3
3.12.2 高铁应用 3
3.12.3 进程应用 3
3.12.4 课表应用 3
3.12.5 学习活动应用 3
3.13 基于语法的数据读入 3
3.14 应对面临的新变化 3
3.14.1 变化1 3
3.14.2 变化2 4
3.14.3 变化3 4
3.15 Git仓库结构 4
4 实验进度记录 4
5 实验过程中遇到的困难与解决途径 4
6 实验过程中收获的经验、教训、感想 5
6.1 实验过程中收获的经验和教训 5
6.2 针对以下方面的感受 5
1 实验目标概述
本次实验覆盖课程第 3、4、5 章的内容,目标是编写具有可复用性和可维护 性的软件,主要使用以下软件构造技术:
子类型、泛型、多态、重写、重载
继承、代理、组合 常见的 OO 设计模式
语法驱动的编程、正则表达式
基于状态的编程
API 设计、API 复用
本次实验给定了五个具体应用(高铁车次管理、航班管理、操作系统进程管 理、大学课表管理、学习活动日程管理),学生不是直接针对五个应用分别编程 实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其实现,充 分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可复用性) 和更容易面向各种变化(可维护性)。。
2 实验环境配置
简要陈述你配置本次实验所需环境的过程,必要时可以给出屏幕截图。
特别是要记录配置过程中遇到的问题和困难,以及如何解决的。
在这里给出你的GitHub Lab3仓库的URL地址(Lab3-学号)。
https://github.com/ComputerScienceHIT/Lab3-1180300503.git
3 实验过程
请仔细对照实验手册,针对每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
3.1 待开发的三个应用场景
我选择的三个应用场景:
航班管理
高铁车次管理
学习日程管理
这三个场景的异同点:
位置的数量:分别为1个、2个和多个
仅有学习日程的位置可更改
航班为单个资源,高铁为有序多个资源,学习日程为无序多个资源
仅有高铁车次可阻塞
时间均在创建时设定
3.2 面向可复用性和可维护性的设计:PlanningEntry
该节是本实验的核心部分。
3.2.1 PlanningEntry的共性操作
其中包括:
1.活动的创建
2.计划项的状态的设置
3.计划项名称的设置
4.为计划项分配资源
5.判断计划项是否可以被取消(阻塞)
3.2.2 局部共性特征的设计方案
所有的局部共性操作均放在PlanningEntry接口中,在CommonPlanningEntry加以实现,比如start,end,cancel之类的状态改变函数。在三个应用中,时间,资源,位置的设置有很大的区别,需要在各自的子类中加以实现。
3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案)
-
航班计划项
航班计划项中包含资源的设置,时间的设置,位置的设置,需要设置日期,在FlightEntry中继承CommonPlanningEntry,其余的操作在各自的app函数中加以实现 -
高铁计划项
与航班类似,区别就是有经停站的影响,所以位置和时间都设置为了List列表,由于单个资源为车厢,而不是一整个高铁,所以资源项也为List列表,代表车厢的集合。 -
课程计划项
课程计划项也与航班计划项类似,但是位置只有一个。
3.3 面向复用的设计:R
-
飞机:
包括飞机的编号,类型,满员数,机龄等,除了Getter函数之外,含包括判断是否两架飞机相同的判断函数。 -
高铁车厢:
包括车厢的编号,类型,生产日期,满员数,除了各自的Getter函数之外,还包括判断两个车厢是否为同一个车厢的判断函数。 -
教师:
包含教师的ID,姓名,性别,职称,均采用String类型,除了Getter函数之外,还包括判断是否两个教师为同一个教师的判断函数。
3.4 面向复用的设计:Location
根据不同的计划项,位置信息包括位置的名称和是否可以共享,除了getter函数之外,还包括判断两个位置是否相同的判断函数。
3.5 面向复用的设计:Timeslot
有不同的构造函数,可以添加一个时间(比如出发和到达),可以添加两个时间(比如经停站中,到达和出发时间),另外,Timeslot中含有几个static函数,来判断时间是否符合规范,判断两个时间的先后顺序,判断时间与日期是否相同等
3.6 面向复用的设计:EntryState及State设计模式
采用State模式,state是一个接口,多种不同的状态继承该接口,在应用中直接调用子类来实现多种状态的转换。
3.7 面向应用的设计:Board
Borad不要求复用,所以只需在各自的子类中实现即可。不同的Board类型大致一样,输出符合要求的计划项。并以表格的形式显现出来。
3.8 Board的可视化:外部API的复用
3.9 PlanningEntryCollection的设计
该ADT是PlanningEntry的集合类。
该ADT未显式的表达出来,在各自的app中通过一个List集合将所有的计划项加入进去,通过确定的输出可以进行表达。
3.10 可复用API设计及Façade设计模式
PlanningEntryAPIs中有所有函数的子类,通过Façade设计模式,在调用方法的过程中直接调用PlanningEntryAPIs中的方法实现对底层函数的调用。
3.10.1 检测一组计划项之间是否存在位置独占冲突
基本的思想是输入确定的信息,根据给定的时间与计划项,逐个遍历计划项,若是俩个计划项占用位置相同并且时间存在重叠,则产生了位置冲突。
3.10.2 检测一组计划项之间是否存在资源独占冲突
与处理位置冲突相似,基本的思想是输入确定的信息,根据给定的时间与计划项,逐个遍历计划项,若是俩个计划项占用资源相同并且时间存在重叠,则产生了资源冲突。
3.10.3 提取面向特定资源的前序计划项
在输入必要信息后,遍历计划项,如果存在计划项在指定计划项之前(结束时间早于指定计划项的开始时间),并且所用资源相同,那么更新当前计划项,在找到更符合要求的计划项后,继续更新计划项,直到遍历完为止。
3.11 设计模式应用
请分小节介绍每种设计模式在你的ADT和应用设计中的具体应用。
3.11.1 Factory Method
在PlanningEntry以及其子类中运用Factory Method,在今后的app中,不必直接new一个子类,而是通过PlanningEntry中的方法进行初始化。
3.11.2 Iterator
在Board类中,通过迭代器模式对计划项的集合逐个输出。
3.11.3 Strategy
采用 Strategy模式,对寻找资源的前序计划项设计两种算法,并逐个应用,有良好的效果。
3.12 应用设计与开发
利用上述设计和实现的ADT,实现手册里要求的各项功能。
只需保留你选定的三个应用即可。
3.12.1 航班应用
一共有13个具体应用,列出前三个应用。
-
管理资源
-
管理位置
-
新增计划项
3.12.2 高铁应用
一共有14个具体应用,列出前三个应用。
-
管理资源
-
管理位置
-
新增计划项
3.12.3 课表应用
一共有13个具体应用,列出前三个应用。
-
管理资源
-
管理位置
-
新增计划项
3.13 基于语法的数据读入
修改“航班”应用以扩展该功能。
3.14 应对面临的新变化
只考虑你选定的三个应用的变化即可。
3.14.1 变化1
将每个FlightEntry中的位置增加,存储两个或三个位置,这样可以较为简单的解决经停站问题。
3.14.2 变化2
判断是否取消时删除分配状态即可。较为简单。
3.14.3 变化3
将每个课程计划项的老师资源设为一个List列表,存储多个老师,当比较课程老师是否一致时,取List中的第一个教师(主要教师)进行比较。
3.15 Git仓库结构
请在完成全部实验要求之后,利用Git log指令或Git图形化客户端或GitHub上项目仓库的Insight页面,给出你的仓库到目前为止的Object Graph,尤其是区分清楚314change分支和master分支所指向的位置。
4 实验进度记录
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。
不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。
日期 时间段 计划任务 实际完成情况
2020-05-01 上午 阅读实验指导书 基本完成
2020-05-03 一整天 PlanningEntry和航班计划项 完成60%
2020-05-04 下午 未完成的航班计划项 基本完成
2020-05-06 上午,晚上 完成高铁计划项 基本完成
2020-05-10 上午,晚上 完成课程计划项 基本完成
2020-05-12 晚上 进行314change的完成 基本完成
2020-05-15 下午 编写实验报告 完成50%
2020-05-17 下午 编写实验报告 基本完成
5 实验过程中遇到的困难与解决途径
遇到的难点 解决途径
实验中各种设计模式不会运用
反复观看老师的教学视频,在网上寻找学习资源
基于语法的输入不太会
询问同学,寻求同学的帮助
实验的整体构架思路不清
参考了同学的思路,并且根据自己的想法加以改变
6 实验过程中收获的经验、教训、感想
6.1 实验过程中收获的经验和教训
6.2 针对以下方面的感受
(1) 重新思考Lab2中的问题:面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?本实验设计的ADT在五个不同的应用场景下使用,你是否体会到复用的好处?
面向ADT编程更加复杂,复用的确可以大量节省代码量!!
(2) 重新思考Lab2中的问题:为ADT撰写复杂的specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后的编程中坚持这么做?
减少输入带来的错误,使输入更加规范。也使自己更加了解各个ADT的具体应用。在今后的编程中要坚持这个好习惯。
(3) 之前你将别人提供的API用于自己的程序开发中,本次实验你尝试着开发给别人使用的API,是否能够体会到其中的难处和乐趣?
难度自我感觉很大,起初设计思路不明确,所以花费了大量时间,但是完成以后,在运用方面更加得心应手,运用更熟练。
(4) 在编程中使用设计模式,增加了很多类,但在复用和可维护性方面带来了收益。你如何看待设计模式?
虽然设计模式增加了很多类,但是对于今后代码的修改和维护起着十分巨大的作用,所以设计模式的应用必不可少。
(5) 你之前在使用其他软件时,应该体会过输入各种命令向系统发出指令。本次实验你开发了一个解析器,使用语法和正则表达式去解析输入文件并据此构造对象。你对语法驱动编程有何感受?
开始不太明白怎么做,后来询问同学之后有了进一步了解。自我感觉语法驱动编程比较抽象,并且麻烦。
(6) Lab1和Lab2的大部分工作都不是从0开始,而是基于他人给出的设计方案和初始代码。本次实验是你完全从0开始进行ADT的设计并用OOP实现,经过五周之后,你感觉“设计ADT”的难度主要体现在哪些地方?你是如何克服的?
该实验难度最大的地方我认为是整体思路的构建,其实思路出来以后,编程并不是特别难,但是我认为大部分人一开始就死在了思路上面,有可能我自己的思路也是不正确的,这是最令人恐慌的,没有正确的模板,一切从0开始,对于我是一个极大的挑战。
(7) “抽象”是计算机科学的核心概念之一,也是ADT和OOP的精髓所在。本实验的五个应用既不能完全抽象为同一个ADT,也不是完全个性化,如何利用“接口、抽象类、类”三层体系以及接口的组合、类的继承、设计模式等技术完成最大程度的抽象和复用,你有什么经验教训?
要灵活使用接口和抽象函数,可以复用的尽量要复用,处理好接口,抽象函数与具体函数之间的关系,最大程度上既减少代码量又实现代码的功能。
(8) 关于本实验的工作量、难度、deadline。
工作量巨大,难度比较难,ddl控制的很合理。
(9) 到目前为止你对《软件构造》课程的评价。
整体来说很好,但是个别方面需要反复观看老师的视频,希望老师以后可以讲清晰一些。
上一篇: [软件构造]实验回顾:Lab4
下一篇: 求某个范围内的所有素数