这个作业属于哪个课程 | 福州大学-202302软件工程 |
---|---|
这个作业要求在哪里 | 软件工程第二次作业–文件读取 |
这个作业的目标 | 完成对世界游泳锦标赛跳水项目相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序 |
其他参考文献 | 构建之法、单元测试和回归测试 |
文章目录
Gitcode项目地址
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 35 |
• Estimate | • 估计这个任务需要多少时间 | 30 | 35 |
Development | 开发 | 1390 | 1435 |
• Analysis | • 需求分析 (包括学习新技术) | 300 | 400 |
• Design Spec | • 生成设计文档 | 40 | 30 |
• Design Review | • 设计复审 | 40 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 25 |
• Design | • 具体设计 | 40 | 40 |
• Coding | • 具体编码 | 600 | 500 |
• Code Review | • 代码复审 | 50 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 300 | 350 |
Reporting | 报告 | 120 | 115 |
• Test Repor | • 测试报告 | 50 | 45 |
• Size Measurement | • 计算工作量 | 30 | 25 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 40 | 35 |
合计 | 1540 | 1585 |
一、解题思路描述
1.1 数据解析
本次项目需要我们对世界游泳锦标赛跳水项目相关数据进行提取,这部分的数据我是直接使用助教提供的数据,故重点放在JSON数据的解析上。
通过导入fastjson包,调用里面的方法对数据进行处理。
具体过程:
先对JSON文件进行处理,将其转换为字符串,方便后续调用方法提取json对象和json数组。
以输出所有选手信息这个函数为例子:
输出赛事选手排名也是同理,如此一来便完成了对json数据的解析。
二、接口设计和实现过程
2.1 类的设计
编写了一个运动员类,用于存放从json文件中提取到的相关数据。
2.2 函数设计
- 指令提取和启动函数:readCommand和activeCommand函数,前者负责从input中读取所有指令,后者负责将指令和功能绑定在一起。
- 功能函数:writeEventsRank和writePlayers,二者负责完成项目的两个功能。
- 辅助函数:JSONToString和commandsCheck,前者用于将json文件转换为字符串类型,辅助后续处理数据,后者用于检查输入指令是否合法。
2.3 设计的独到之处
1.用到了许多集合来存储数据,方便函数调用
2.建立了一个实体类用于记录数据,实现了模块化
3.使用了map来模拟缓存,不用多次提取数据
三、关键代码展示
3.1 指令提取
public static ArrayList<String> readCommand(String filePath){
ArrayList<String> commandList = new ArrayList<String>();
String command = "";
try{
BufferedReader br = new BufferedReader(new FileReader(filePath));
while((command = br.readLine())!=null){
commandList.add(command);
}
}
catch (FileNotFoundException e){
System.out.println(filePath + "文件不存在!");
}
catch(IOException e){
System.out.println("文件为空文件!");
}
return commandList;
}
3.2 指令分析及模拟缓存建立
public static void activeCommand(ArrayList<String> commands, String filePath ){
Map<String,String> dataCached = new HashMap<>();
String data = "";
for(String command : commands){
int statusCode = commandsCheck(command);
try{
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
if(statusCode == 1){
bufferedWriter.write("Error"+'\n');
bufferedWriter.write("-----\n");
}
else if(statusCode == 2){
bufferedWriter.write("N/A"+'\n');
bufferedWriter.write("-----\n");
}
else{
if(dataCached.containsKey(command)){
bufferedWriter.write(dataCached.get(command) + '\n');
}
else{
if(command.equals("players")){
data = writePlayers(filePath);
}
else{
String temp[] = command.split(" ");
if(!temp[temp.length-1].equals("detail")){
data = writeEventsRank(command,filePath);
}
}
dataCached.put(command,data);
}
}
bufferedWriter.close();
}
catch (IOException e) {
System.out.println("文件不存在!");
}
}
}
3.3 选手类
public class Athlete {
private String fullName;
private String gender;
private String country;
private ArrayList<String> finalScores;//决赛每次得分
private ArrayList<String> preliminaryScores;//初赛每次得分
private ArrayList<String> semifinalScores;//半决赛每次得分】
private String finalAllScore;//决赛总分
private String preliminaytAllScore;//初赛总分
private String semifinalAllScore;//半决赛总分
private String finalRank;//决赛排名
private String preliminaryRank;//初赛排名
private String semifinalRank;//半决赛排名
public Athlete() {
finalScores = new ArrayList<>();
preliminaryScores = new ArrayList<>();
semifinalScores = new ArrayList<>();
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public ArrayList<String> getFinalScores() {
return finalScores;
}
public void setFinalScores(ArrayList<String> finalScores) {
this.finalScores = finalScores;
}
public String getFinalRank() {
return finalRank;
}
public void setFinalRank(String finalRank) {
this.finalRank = finalRank;
}
public String getFinalAllScore() {
return finalAllScore;
}
public void setFinalAllScore(String finalAllScore) {
this.finalAllScore = finalAllScore;
}
}
四、性能改进
本次项目中,如若碰上相同指令,若没有保存数据,则需频繁的解析数据,导致运行效率降低。故优化的关键点就在于将第一次执行的指令提取到的数据保存下来,后续如果有相同指令,直接输出即可,无需再次提取数据。
我的想法是用一个map来模拟cache,通过键值对将指令和数据结合起来,再在指令执行前判断其是否存在于这个map容器中,如若存在,直接取出对应value值,输出即可;如不存在,读取json数据,将其存入map中。
五、单元测试
5.1 对main函数的测试
分为以下几种情况:
- 参数名、参数个数均正确
- 参数名正确,参数个数错误
- 多个参数
结果显示为test1测试不通过,其余都通过。
5.1 对Lib接口的测试
结果显示Test2不通过测试,其余均通过。
六、异常处理
6.1 I/O流异常处理
6.2 文件提取异常处理
七、心得体会
通过本次作业,我体会到了完成一个项目不是一蹴而就的,不是一上来就编写代码,在之前要对需求进行分析,规划时间,合理地安排每个阶段所要完成的任务。在完成本次作业的过程中,JSON数据处理、单元测试、git的使用是我以前很少接触过的,在完成作业的同时,我也通过上网查阅资料,学习了相关知识,掌握了相应方法。通过完成本次作业,不仅提升了我的编程能力,也让我更深入的了解了软件工程实际开发过程。