哈工大软件构造Lab2

2021年春季学期
计算学部《软件构造》课程

 

 

 

 

Lab 2实验报告

 

 

 

 

 

 

 

 

姓名

李金宣

学号

1181910201

班号

1903002

电子邮件

 

手机号码

 

 


 

目录

 

 

 

 

实验目标概述

  本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象编程(OOP)技术实现ADT。具体来说:

针对给定的应用问题,从问题描述中识别所需的ADT

设计ADT 规约(pre-conditionpost-condition)并评估规约的质量;

根据ADT 的规约设计测试用例;

ADT的泛型化;

根据规约设计ADT 的多种不同的实现;针对每种实现,设计其表示(representation)、表示不变性(rep invariant)、抽象过程(abstraction function

使用OOP 实现ADT,并判定表示不变性是否违反、各实现是否存在表示泄露(rep exposure);

测试ADT 的实现并评估测试的覆盖度;

使用ADT 及其实现,为应用问题开发程序;

在测试代码中,能够写出testing strategy 并据此设计测试用例。

 

实验环境配置

简要陈述你配置本次实验所需环境的过程,必要时可以给出屏幕截图。

特别是要记录配置过程中遇到的问题和困难,以及如何解决的。

Eclipse菜单 →“帮助” → 安装新软件;

安装对话框中,在“ 工作日期中输入http://update.eclemma.org/

根据指示正常安装即可

在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号)。

https://github.com/ComputerScienceHIT/HIT-Lab2-1181910201

 

实验过程

请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。

3.1 Poetic Walks

实现一个图graph的模块,基于此模块,根据语义库进行诗歌创作

1.     实现GraphString类型接口类,之后将String拓展为泛型L类;

2.     创建Graph类的addsetremoveverticessourcestargets等方法;

3.     基于创建好的Graph类,实现GraphPoet类,将语义库存入graph图中,然后利用GraphPoet类,根据graph中语义库的信息,对输入文本进行处理,若输入文本的两个单词之间存在桥接词,则插入桥接词;若存在多个单一桥接词,则选取边权重较大者。最终得到由输入文本创作的诗歌,

3.1.1 Get the code and prepare Git repository

创建本地仓库

git init

下载实验代码

git clone
https://github.com/rainywang/Spring2020_HITCS_SC_Lab2/tree/master/P1
连接远程仓库
git remote 

https://github.com/ComputerScienceHIT/HIT-Lab2-1181910201

添加到本地仓库
git add .
提交到本地仓库
git commit -m
初次上传到远程仓库
git push -u origin master
之后
git push origin master
 
 

3.1.2 Problem 1: Test Graph <String>

针对每个方法进行等价类划分的测试

 

覆盖率

3.1.3 Problem 2: Implement Graph <String>

以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。

3.1.3.1 Implement ConcreteEdgesGraph

1.     实现Edge

数据段-边的权值weight,边的起点source,终点target

 

 

Edge中的方法

 

Edge

构造方法,初始化边的权值weight,起点source,终点target

checkRep

检查不变性,边不为空且权值非负

getSource

get方法返回起点source

getTarget

get方法返回终点targe

getWeight

get方法返回权值weight

toString

" Source:" + this.source + ",Target:" + this.target + ",Weight:" +this.weight

2.     实现ConcreteEdgesGraph

数据段:顶点集vertices和动态链表edges

ConcreteEdgesGraph中的方法:

ConcreteEdgesGraph

构造方法

checkRep

检查不变性,edges中边的sourcetargetvertices中,权值weight大于0

add

参数为新顶点,点不在原图,添加成功-true 否则-false

set

参数为边的起点source边的终点target边的权重weight,列表edges中添加一条边,若起点终点相同或权值为负,添加失败返回;若是新边,权值为正,将两点添加至vertices,边添加到edges.若是已存在的边,权值为正,更新边的权值,返回上一条边的权值,权值为0,删除此边

remove

参数为需移除的顶点,删除顶点,与此点相连的边也一并删除,原图有此顶点返回true,若无则返回false

vertices

返回得到图中所有顶点的HashSet

sources

参数为目标顶点,返回得到所有以该点为终点的边的起点及权值,储存到Map

targets

参数为目标顶点,返回得到所有以该点为起点的边的终点及权值,储存到Map

toString

返回字符串,包含顶点数,边数,各边及其权重

 

 

 

3.测试,增加testToString部分即可

 

覆盖率

3.1.3.2 Implement ConcreteVerticesGraph

1.     实现Vertex类:

数据段 -V表示顶点,Sources表示以该顶点为终点的边的起点表,Targets表示以该顶点为起点的边的终点表,MapString为顶点的对点,Integer为边的权值

 

 

 

 

 

 

 

Vertex中的方法

Vertex

初始化构造方法,参数为顶点

checkRep

检查不变性,顶点不空,权值为正

getV

返回顶点V

sources

返回所有以该点为终点的边,Map中为边的起点及权值

targets

返回所有以该点为终点的边,Map中为边的起点及权值

setSource

参数为待加入的起点与权值,该点为终点时,将边的起点和权值加入到 Map Sources中,若权值小于等于0,返回0,若权值为正,当起点已存在时,更新权值,返回原来的权值,起点不存在则添加新点

setTarget

参数为待加入的终点与权值,该点为起点时,将边的终点和权值加入到 Map Target中,若权值小于等于0,返回0,若权值为正,当终点已存在时,更新权值,返回原来的权值,终点不存在则添加新点

removeEdge

参数为对点,在SourcesTargets表中,删除与顶点相连某条边的对点,返回原来的边长

toString

this.V.toString()+"-Sources:"+this.Sources.toString()+" Targets:"+this.Targets.toString()+"\n"

 

2.     实现ConcreteVerticesGraph

数据段-Vertex构成的列表vertices

ConcreteVerticesGraph中的方法:

ConcreteVerticesGraph

构造方法

checkRep

检查不变性,权值为正,顶点非空,起点终点数相同

add

参数为顶点,在图中添加一个顶点,若图中存在该点,添加失败return false;若添加成功,return true

set

参数为边的起点,边的终点,边的权值,添加一条边(在起点终点各自的vertex类里添加各自的对点)若起点终点相同或权值为负,添加失败返回,若是新边,权值为正,将两点添加至vertices,各自类中添加边,权值为0,只将两点添加至vertices,若是已存在的边,权值为正,更新边的权值,返回上一条边的权值,权值为0,删除此边

remove

参数为需移除的顶点,删除顶点,与此点相连的边也一并删除,原图有此顶点返回true,若无则返回false

vertices

返回得到图中所有顶点的点集

sources

参数为目标顶点,返回得到所有以该点为终点的边的起点及权值,储存到Map

targets

参数为目标顶点,返回得到所有以该点为起点的边的终点及权值,储存到Map

toString

各顶点的边对点及其权重

3. 测试,增加testToString部分即可

覆盖率

 

 

 

 

 

 

3.1.4 Problem 3: Implement generic Graph<L>

3.1.4.1 Make the implementations generic

 

 

将类型更改为

publicclass ConcreteEdgesGraph<L> implements Graph<L>{ ... }class Edge<L>{ ... }

和:

publicclass ConcreteVerticesGraph<L> implements Graph<L>{ ... }class Vertex<L>{ ... }

已经声明了类型为Edge或 的变量List<Edge>成为Edge<L>List<Edge<L>>

只需按以上规则对Graph<String>进行重构即可,代码整体逻辑框架不变。

 

重构后测试结果

 

3.1.4.2 Implement Graph.empty()

public static Graph<String> empty() {
    return new ConcreteEdgesGraph();
}
返回空的实例

 

3.1.5 Problem 4: Poetic walks

基于创建好的Graph类,实现GraphPoet类,将语义库存入graph图中,然后利用GraphPoet类,根据graph中语义库的信息,对输入文本进行处理,若输入文本的两个单词之间存在桥接词,则插入桥接词;若存在多个单一桥接词,则选取边权重较大者。最终得到由输入文本创作的诗歌

3.1.5.1 Test GraphPoet

添加一段测试,生成诗歌是否与预期相同即可

覆盖率

 

 

3.1.5.2 Implement GraphPoet

数据段-新的空表

GraphPoet,按行读入文本文件,String.split()分割为数组String.toLowerCase()小写。构建图,相邻的单词加边。首先要在加边前通过Graph.add()加点,加边时要判断是否存在:由于Graph.set()能返回之前加的边的值,以此来判断是否存在,存在则在之前的值加一(之前的边的值保存为temp_weight)。

poem当相邻两个单词任意一个不在之前创建的图里,则将后者单词加入,当存在时,Bridge长度只能为2,分别求两个单词的sourcestargets,将该Map转换为Set求交集;若交集为空,则无桥,若交集不空,则在交集中找最短的桥(可以在Mapvalue中查询weight)。

3.1.5.3 Graph poetry slam

测试

3.1.6 使用Eclemma检查测试的代码覆盖度

3.1.7 Before you’re done

请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。

如何通过Git提交当前版本到GitHub上你的Lab2仓库。

 

在这里给出你的项目的目录结构树状示意图。

3.2 Re-implement the Social Network in Lab1

Lab1类似,用PersonFriendshipGraph两个类模拟社交网络图,Person模拟图的顶点,FriendshipGraph模拟关系,getDistance能够计算出每两个Person之间的最短路径,但要用3.1中的Graph ADT中的方法来实现

3.2.1 FriendshipGraph

数据段:

一个由Person类组成的Graph类型图,初始为空

方法:

addVertex():调用graph.add()添加点。

addEdge():调用graph.set()两次,添加双向边,权值为1,返回旧边的权值。

int getDistance():判断起止点是否相等。再新建Map<Person, Integer> disance存储从起始点开始到该Person的距离,Map<Person, Boolean> visited表示该Person是否访问过。将两个Map初始化后,把起点标记为已经访问。然后开始BFS搜索,找到终点为止,返回最短距离。

 

 

 

 

 

3.2.2 Person

数据段name,构造方法Person赋值,get方法getName返回数据段name

 

 

 

 

 

3.2.3 客户端main()

 

Lab1中的main复制过来即可

3.2.4 测试用例

覆盖率

3.2.5 提交至Git仓库

在这里给出你的项目的目录结构树状示意图。

实验进度记录

请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。

每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。

不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。

日期

时间段

计划任务

实际完成情况

2021.6.10

18.00-22.00

完成Graph<String>部分

对实验要求有了初步认识,细节未完成

2021.6.11

18.00-23.00

完成poet之前的部分

完成

2021.6.12

12.00-15.00

完成poet部分

完成

2021.6.13

12.00-15.00

完成Person部分

完成

实验过程中遇到的困难与解决途径

遇到的难点

解决途径

 

MIT的实验要求不明确,英文难懂

 

翻译软件初步翻译后,仍有许多细节模糊,每一句再具体翻译

 

javadoc要求的完善方法具体实现需要的数据结构不清楚

 

上网,翻阅教材查阅相关数据结构

 

 

 

 

实验过程中收获的经验、教训、感想

6.1 实验过程中收获的经验和教训

1.java编程经验少,对相关数据结构不熟悉,javadoc格式的注释不规范

2.ADTOOP有了更深刻的理解

3.对相关数据结构,有了更深的理解。

 

6.2 针对以下方面的感受

(1)   面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?

面向对象以抽象,类,继承,对象等方法为基础,就像制造汽车时,先将汽车分成多个部分,然后具体生产每一部分的零件再组装,而面向过程像是从零件直接组装。

(2)   使用泛型和不使用泛型的编程,对你来说有何差异?

泛型能适应更多的情况,更加灵活多变。

(3)   在给出ADT的规约后就开始编写测试用例,优势是什么?你是否能够适应这种测试方式?

可以及时修改,保证代码正确性与规范性,能

(4)   P1设计的ADT在多个应用场景下使用,这种复用带来什么好处?

增加代码利用率,避免重复造轮子

(5)   P3要求你从0开始设计ADT并使用它们完成一个具体应用,你是否已适应从具体应用场景到ADT的“抽象映射”?相比起P1给出了ADT非常明确的rep和方法、ADT之间的逻辑关系,P3要求你自主设计这些内容,你的感受如何?

体会到了面向对象编程的优点,有轮子时很容易实现,造轮子很困难。

(6)   ADT撰写specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后编程中坚持这么做?

防止内部数据被外部修改,愿意

(7)   关于本实验的工作量、难度、deadline

   大,难,紧

(8)   《软件构造》课程进展到目前,你对该课程有何体会和建议?

上课内容太过宽泛,课后辅导较少,难度较大,实验和课堂结合不好。

 

工大标志

2021年春季学期
计算学部《软件构造》课程

 

 

 

 

Lab 1实验报告

 

 

 

 

 

 

 

 

姓名

李金宣

学号

1181910201

班号

1903002

电子邮件

 

手机号码

 

 


 

目录

 

1 实验目标概述................................................................................................................................................. 1

2 实验环境配置................................................................................................................................................. 1

3 实验过程........................................................................................................................................................... 1

3.1 Magic Squares......................................................................................................................................... 1

3.1.1 isLegalMagicSquare()........................................................................................................ 1

3.1.2 generateMagicSquare()..................................................................................................... 1

3.2 Turtle Graphics....................................................................................................................................... 1

3.2.1 Problem 1: Clone and import.................................................................................................. 2

3.2.2 Problem 3: Turtle graphics and drawSquare................................................................... 2

3.2.3 Problem 5: Drawing polygons................................................................................................. 2

3.2.4 Problem 6: Calculating Bearings............................................................................................ 2

3.2.5 Problem 7: Convex Hulls.......................................................................................................... 2

3.2.6 Problem 8: Personal art.............................................................................................................. 2

3.2.7 Submitting........................................................................................................................................ 2

3.3 Social Network....................................................................................................................................... 2

3.3.1 设计/实现FriendshipGraph......................................................................................... 2

3.3.2 设计/实现Person................................................................................................................. 2

3.3.3 设计/实现客户端代码main().............................................................................................. 2

3.3.4 设计/实现测试用例.................................................................................................................... 3

4 实验进度记录................................................................................................................................................. 3

5 实验过程中遇到的困难与解决途径.................................................................................................... 3

6 实验过程中收获的经验、教训、感想............................................................................................... 3

6.1 实验过程中收获的经验和教训..................................................................................................... 3

6.2 针对以下方面的感受......................................................................................................................... 3

 


1 实验目标概述

本次实验通过求解三个问题,训练基本Java编程技能,能够利用Java OO开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。另一方面,利用Git作为代码配置管理的工具,学会Git的基本使用方法。

l 基本的Java OO编程

l 基于Eclipse IDE进行Java编程

l 基于JUnit的测试

l 基于Git的代码配置管理

2 实验环境配置

JDK环境,大一学习Javaee课程时配置的jdk8环境,环境变量等配置时遇到一些问题,通过网络搜索自学解决。

配置Eclipse环境时,一开始按照指导手册的教程一步步安装,中间导入URL等环节出现许多问题,于是直接放弃指导手册,自己一路点击nextfinish进行安装,所幸成功安装eclipse。由于对全英文开发环境不太熟悉,网上搜索了eclipse简体中文环境的配置方法,具体参考

https://blog.csdn.net/qq_43015730/article/details/89225747

下载的eclipse自带Junit环境,但需要在eclipse设置中自行调用,一开始并不太懂应该怎么调用Junit,在运行P2turtletest文件时,因未配置Junit环境导致出错,在报错的行ctrl+1进行修改,成功配置Junit4环境。

在使用git的过程中遇到了非常多的问题,前后花了很长时间才将git环境配置好,一开始按照实验指导手册的Git指导书学习,但指导书内容过于繁杂,重点不突出,很多细节问题都没有解答,于是直接放弃指导书,同学间交流和网络上自行搜索成功配置好Git环境。

参考过非常多网站,如

https://www.cnblogs.com/dfsxh/articles/10959383.html

 

在这里给出你的GitHub Lab1仓库的URL地址。

https://github.com/ComputerScienceHIT/HIT-Lab1-1181910201

 

3 实验过程

请仔细对照实验手册,针对四个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但无需把你的源代码全部粘贴过来!)。

为了条理清晰,可根据需要在各节增加三级标题。

3.1  Magic Squares

要求1:在 main()函数中调用五次 isLegalMagicSquare()函数,将 5 个文本文件名作为参数输入,读入文本数据,判断输入的数据能否构成一个MagicSquare,若是则返回true,若不是或格式错误,则返回false且说明原因。

要求2:对给出的generateMagicSquare函数扩展,根据参数n生成一个MagicSquare并写入文本6.txt中,然后判断其是否为MagicSquare。输入为奇数能生成MagicSquare返回true,输入偶数或者负数会返回false

 

3.1.1 isLegalMagicSquare()

设计思路:首先读入txt文本文件,然后进行判断题目要求的三个条件:

1.   行列数不相等,并非矩阵:每读入一行row++,计算总行数,将每一行按照\t分隔存入数组,判断每一行的列数是否与行数相等,若存在不相等,返回false

2.   矩阵中的某些数字并非正整数:每一行按照\t分隔存入数组后,判断数组元素有无”-””.”,有则说明有负数或小数,返回false

3.   数字之间并非使用\t分割:对Integer.valueOf使用try catch方法,若不是以     \t作为分隔符则抛出异常信息,返回false

对错误类型进行判断输出错误类型并返回false,当判断完毕没  格式错误时,将读入的数据存入到矩阵中,判断每一行,每一列,对角线的和是否相等,满足MagicSquare 则返回true,若有不相等则返回false

测试结果:

 

3.1.2 generatelMagicSquare()

流程图

未命名文件

合法输入判断

测试样例

3.2  Turtle Graphics

完善并使用绘图工具Trurtle Graphics

要求:1.完善drawSquare函数,画出一个正方形

2.完善calculateRegularPolygonAngle函数计算正多边形内角

3.完善calculatePolygonSidesFromAngle函数,由正多边形内角        得到边数

4.完善drawRegularPolygon函数,画正多边形

5.完善calculateBearingToPoint计算从一个点到另一个点所转过的角度,

6.完善calculateBearings函数,给定一组点,计算每次转过的角度并返回集合,

7.完善convexHull函数计算一系列点中的凸包,使用junit进行单元测试。

8.调用函数绘制自己的图形

3.2.1  Problem 1: Clone and import

从实验手册的网站git clone下载P2的包,解压导入eclipse项目中。

1.获取秘钥:

2.找到秘钥并复制添加到github上;

本地Git提交,pushGitHub

1. git add ;

2. git commit -m "   " ;

3. git push

参考https://www.cnblogs.com/dfsxh/articles/10959383.html

3.2.2 Problem 3: Turtle graphics and drawSquare

行进四次,每次转90

 

测试结果

3.2.3 Problem 5: Drawing polygons

正多边形内角=(边数-2*180/边数

画多边形时每次前进偏转外角度数即可

 

3.2.4 Problem 6: Calculating Bearings

调用atan2函数得到两点间偏转弧度,toDegree转换成角度,减去当前偏角即为偏转角度,计算一组点,反复调用两点的函数即可

 

 

 

3.2.5 Problem 7: Convex Hulls

利用Gift wrapping算法计算凸包,先找到最左下角的点作为初始点加入集合,然后比较剩余点到此点的偏转角,找到偏转角最小的加入集合,当偏转角相同时,找到最长的一条边的点加入集合,直到返回初始点最后得到凸包的点集。

//这部分源代码过长贴不下,请看源文件

3.2.6 Problem 8: Personal art 

3.2.7 Submitting

Junit测试

3.3Social Network

PersonFriendshipGraph两个类模拟社交网络图,Person模拟图的顶点,FriendshipGraph模拟关系,getDistance能够计算出每两个Person之间的最短路径。

3.3.1设计/实现FriendshipGraph

定义Person数组来储存所有的顶点,构造方法

addVertex添加对象,若新对象名字与已有名字重复,打印错误,退出

addEdge添加边(顶点间的关系),在Person a对象数组friend的里添加b,单向

因为边权重为1,可以使用广度优先搜索求两点间最短路径,调用类HashMap,用temp临时存储a1到各个点的最短距离,调用队列,将a1入队后按广度优先搜索的方法不断入队出队,更新temp中各顶点当前最短路径,直到有到a2的路径为止,返回最短距离

3.3.2设计/实现Person

 

 

 

3.3.3设计/实现客户端代码main()

直接复制实验手册的代码,对界面稍加修改即可

3.3.4设计/实现测试用例

给出你的设计和实现思路/过程/结果。

对于addVertex,设计用例,建立四个Person对象,执行addVertex,判断vertex里面这些对象。

对于addEdge,设计test用例,建立四个Person对象,执行addVertex后,执行addEdge然后判断每个对象的friend中是否包含即可。

对于getDistance,设计test用例t,建立四个Person对象,执行addVertex后,执行addEdge后,最短距离正确即可。

4 实验进度记录

请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。

每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。

不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。

日期

时间段

任务

实际完成情况

2021-05-19

配置环境

Git配置未完成

2021-05-20

18.00-

配置环境

完成

2021-05-21

1000-1300

编写P1isLegalMagicSquare函数

完成

2021-05-21

1500-1600

编写P1generateMagicSquare函数

完成

2021-05-22

1000-1400

完成P2

完成

2021-05-22

1700-2100

完成P3

完成

 

 

 

 

5 实验过程中遇到的困难与解决途径

遇到的困难

解决途径

Git配置出现问题

 

 

网上自己搜,与同学交流学习

P2测试类时出现问题

 

 

Eclipsejunit环境未设置,在报错的行ctrl+1进行修改,成功配置Junit4环境。

 

P2对礼物包装算法不熟悉

 

网络上搜索算法详细介绍,参考算法的相关代码编写

P3Java的广度优先算法编写不太熟悉

查阅Java中队列,哈希表等相关类的介绍和用法,成功使用并优化了代码

6 实验过程中收获的经验、教训、感想

6.1 实验过程中收获的经验和教训

1.使用java次数少,对java语法不熟悉,许多地方代码优化不好

2.Git配置不熟悉,出现许多问题

3.java语言有了更深的理解。

 

6.2 针对以下方面的感受

(1)   Java编程语言是否对你的口味?还好,有一定java基础但不熟练,Java可使用的类与库非常多,相比c语言可以使代码的编写更加容易,代码更加简洁。

(2)   关于Eclipse IDE;以前用过,用户界面也比较良好,上手也容易,暂时未遇到太多问题

(3)   关于GitGitHub;环境配置非常麻烦,实验手册的指导完全没有重点,不知道从哪学起,全依靠自己上网搜索和同学交流,希望这门课以后能把Git环境的配置详细地指导给大家,而不是直接照搬MIT的指导手册。

(4)   关于CMUMIT的作业;虽然有一定难度,但层层递进,锻炼编程能力,Java编程的收获很大。

(5)   关于本实验的工作量、难度、deadline;有一定难度,工作量大,虽然两周时间实验其实还算充裕,但课程时间与其他课程ddl冲突,开课第一周恰逢自动机期末考试和csapp实验ddl,导致实际上的实验时间被大大缩短,希望教务处能平衡好这几门课ddl的冲突.

(6)   关于初接触“软件构造”课程;

实验收获还是很大的,但个人觉得平时上课讲的东西太抽象宽泛,缺乏实际联系,很难理解什么意思,很多同学也听得不知所云,应对考试也就是背知识点做题,很难有实际收获,然而这些部分却占了成绩的大头,希望课程考核和教学方式能有所改革,能更多侧重于实验部分或者提升平日课程内容的质量。

 

 

posted @ 2021-06-29 22:13  YukiYuki123  阅读(188)  评论(0)    收藏  举报