软件工程实践第二次作业

这个作业属于哪个课程软件工程实践2022年春-F班
这个作业要求在哪里软件工程实践第二次作业
这个作业的目标使用命令行 从网络上获取冬奥会奖牌榜和赛程的数据 并输出
其他参考文献CSDN、博客园


1、GitCode项目地址

m0_46536118 / PersonalProject-Java

2、PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划
• Estimate• 估计这个任务需要多少时间3030
Development开发
• Analysis• 需求分析 (包括学习新技术)6080
• Design Spec• 生成设计文档3050
• Design Review• 设计复审2030
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)1020
• Design• 具体设计3040
• Coding• 具体编码300400
• Code Review• 代码复审30120
• Test• 测试(自我测试,修改代码,提交修改)300500
Reporting报告
• Test Repor• 测试报告90120
• Size Measurement• 计算工作量3030
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划3060
合计9601480

3、解题思路描述

程序总体流程

在这里插入图片描述

数据获取

根据提供的冬奥会网站,审查元素找到对应的奖牌和赛程json文件
冬奥专栏
之后使用java自带的HTTP(java.net.HTTPURLConnection)构造并发送GET请求获取json字符串。

json解析

使用HTTP获取数据,处理字符串,创建对应类后使用gson解析库来解析

4、接口设计和实现过程

项目的类分为三种 工具类 实体类 业务类。
工具类有文件类用于输入输出文件、HTTP类用于获取需要的冬奥会数据。
实体类有奖牌类和赛程类,用于json解析。
业务类有getData和outPutData用于控制业务逻辑。
最终的项目结构如图
最终的项目结构
项目的流程为:获取数据、解析数据、输出数据
获取数据首先检查本地是否有数据文件,无则使用HTTP GET请求获取。
解析数据使用gson解析,解析部分抽象了totalJsonToString、scheduleJsonToString两个接口,获取json字符串的类需要继承对应的接口后实现处理json转为字符串的函数。
输出数据部分根据输入文件获取需要输出的编号,最后一次性输出。

5、关键代码展示

OlympicSearch.java

public class OlympicSearch {
    public static void main(String[] args) {
        if(args.length!=2) {
            System.out.println("运行格式异常,正确格式需要加上输入文件和输出文件");
            return;
        }
        ArrayList<String> requestType =new ArrayList<>();
        //按行读取input文件内容
        try {
            FileInputStream inputStream = new FileInputStream(args[0]);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String str;
            while((str = bufferedReader.readLine()) != null){
                requestType.add(str);
            }
            //close
            inputStream.close();
            bufferedReader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("未找到该文件");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常");
        }
        OutputData out=new OutputData(requestType);
        out.outPutToFile(args[1]);
    }
}

getSchedule

 public void getSchedule(String date)
    {
        int dateInt=Integer.parseInt(date);
		Gson gson = new Gson();
        String jsonString = file.readFile("data/schedule/"+date+".json");
        try{
            scheduleFile sf = gson.fromJson(jsonString, scheduleFile.class);
            fileString[dateInt-201]=sf.data.getSchedule();
        }catch (Exception e){
            //解析文件夹中的json文件失败后需要重新爬取json文件
            if(!getData.getFile(date)){
                System.out.println("json文件损坏,并且爬取数据失败");
            }
            else {
                System.out.println("json文件损坏,已经重新爬取文件");
                jsonString = file.readFile("data/schedule/"+date+".json");
                scheduleFile sf = gson.fromJson(jsonString, scheduleFile.class);
                fileString[dateInt-201]=sf.data.getSchedule();
            }
        }
    }

getTotal

public void getOutput()
    {
        Gson gson = new Gson();
        String jsonString = file.readFile("data/total.json");
        try{
            totalFile tf = gson.fromJson(jsonString, totalFile.class);
            fileString[0]=tf.data.getListByRank();
        }catch (Exception e){
            //解析文件夹中的json文件失败后需要重新爬取json文件
            if(!getData.getFile("total")){
                System.out.println("json文件损坏,并且爬取数据失败");
            }
            else {
                System.out.println("json文件损坏,已经重新爬取文件");
                jsonString = file.readFile("data/total.json");
                totalFile tf = gson.fromJson(jsonString, totalFile.class);
                fileString[0]=tf.data.getListByRank();
            }
        }
    }

6、性能改进

第一个版本的流程为每读入一行 根据该行的数据解析json字符串后输出到对应文件。
第一次改进: 每读入一行解析一次json字符串花销太大 所以让程序保存需要输出的数据
下次需要输出相同的数据可以使用已保存的而不用再次去解析json。
第二次改进:每读入一行输出一次到文件中反复打开文件的开销太大 所以让程序使用一个ArrayList保存需要输出的代码标号 最后根据ArrayList拼接所有需要输出的字符串后输出。

最终两万行输入耗时平均耗时900ms
内存平均占用237mb
在这里插入图片描述

7、单元测试

覆盖率测试

data文件夹存在对应文件不需要HTTP获取
data文件夹存在对应文件
data文件夹不存在对应文件需要HTTP获取
在这里插入图片描述

代码测试

总体测试

in.txt为输入文件 out.txt为输出文件 expected.txt为预期文件
测试代码使用输入文件输出到输出文件 之后读取输出文件和预期文件的内容进行对比

@Test
    public void outPutToFile(){
        ArrayList<String> requestType =new ArrayList<>();
        //按行读取input文件内容
        try {
            FileInputStream inputStream = new FileInputStream("in.txt");
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String str;
            while((str = bufferedReader.readLine()) != null){
                requestType.add(str);
            }
            //close
            inputStream.close();
            bufferedReader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("未找到该文件");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常");
        }

        OutputData out=new OutputData(requestType);
        out.outPutToFile("out.txt");
        
        String outFile=readFile("out.txt");
        String expected=readFile("expected.txt");
        Assert.assertEquals(expected,outFile);
    }

单元测试

 @Test
    public void getOutput() {
        ArrayList<String> requestType =new ArrayList<>();
        OutputData ou=new OutputData(requestType);
        ou.getOutput();
        String expected=readFile("1.txt");
        Assert.assertEquals(expected,ou.fileString[0]);
    }

    @Test
    public void getSchedule() {
        ArrayList<String> requestType =new ArrayList<>();
        OutputData ou=new OutputData(requestType);
        ou.getSchedule("0215");
        String expected=readFile("1.txt");
        Assert.assertEquals(expected,ou.fileString[14]);
    }

8、异常处理

命令行读取时参数个数异常 会提醒输入参数错误 并结束程序
数据文件不存在时会自动使用HTTP获取数据
数据文件损坏或者被修改 会使用HTTP重新获取数据

9、心得体会

开始编码前最重要的是先弄清楚需求。
之后要先设计程序的大体结构 再设计接口 使程序的代码可迁移。
最后开始具体的函数编码。
测试是繁琐的,但是十分重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值