软件工程实践第二次作业——个人实战

222000305陈宇焜 学生 2023-03-02 19:00:09

软件工程实践第二次作业——个人实战

这个作业属于哪个课程2023年福大软件工程实践课程W班
这个作业要求在哪里软件工程实践第二次作业
这个作业的目标代码编写、撰写单元测试、撰写博客
其他参考文献单元测试与回归测试-邹欣

目录

  • 一、项目git目录
  • 二、项目PSP
  • 三、项目解题思路
  • 四、设计与实现过程
  • 类与函数设计
  • json数据解析类
  • 每日赛事、选手信息输出类
  • 五、程序性能改进
  • 六、单元测试展示
  • 整体测试用例及输出结果
  • 1.程序入口测试:
  • 2.最终覆盖率:
  • 3.优化
  • 七、异常处理
  • 八、心得体会

一、项目git目录

项目代码Gitcode目录

二、项目PSP

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

三、项目解题思路

在已有json数据的情况下,项目主体需要三个主要部分:
1.解析json数据的解析类,作为工具解析所需要的Json数据,参数为Json文件名
2.两个功能各一个类,作为分开的两个功能,调用Json解析类获取根对象,并进行解析。
3.测试类,每写一个功能就可以对其方法进行测试。
并且,由于实现过程需要用到json解析,则需要寻找相应的解析包,项目最终使用阿里巴巴的fastJson,性能较好。单元测试也需要引入Junit,项目使用Junit4

四、设计与实现过程

类与函数设计

首先数据解析类作为工具,可设计为一个静态的工具方法。两个功能类结构应该大体类似,可设计一个抽象类,便于维护两个类的方法和数据;功能内动态使用来自文件的指令,故没有创建文件路径的常量类;没有将数据和逻辑分离。

img

json数据解析类

解析类使用fastJson来实现具体的解析,传入参数为文件路径,主要方法为JSONObject.parseObject(String text),使用它将json数据字符串解析为根对象并输出,所用文件使用Java的文件流InputStreamReader类读取json文件。

        public  static JSONObject readJsonObject(String fileName) {
        String str="";
        try {
            int c;

            InputStream inputStream=JsonParserUtil.class.getClassLoader().getResourceAsStream(fileName);
            InputStreamReader reader=new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            StringBuilder stringBuilder=new StringBuilder();
            while((c= reader.read())!=-1) {
                stringBuilder.append((char)c);
            }
            str= stringBuilder.toString();
            reader.close();
        }
        catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return JSONObject.parseObject(str);
    }

每日赛事、选手信息输出类

1、主要方法的参数为指令及所输出的目标文件,将输出部分按要求分为四个方法:验证和获取时间、获胜者、分数。验证使用正则表达式验证,并返回对应验证结果。原数据中获取分数时由于数据嵌套复杂,需要一层一层循环读取,新数据只有一层嵌套,可直接获取数组或对象再获得属性。获胜者即获取到队伍id后到teams中找到players数组,再到players中寻找。

    private void CreateWinner(StringBuilder builder, String teamId) {
        JSONArray winners = null;
        // 获得player的uuid
        for (int m = 0; m < allTeams.size(); m++) {
            String uuid = (String) JSONPath.eval(allTeams, "$[" + m + "].uuid");
            if (uuid.equals(teamId)) {
                winners = (JSONArray) JSONPath.eval(allTeams, "$[" + m + "].players");
                break;
            }
        }

        builder.append("winner:");
        if (winners.size() == 1) {
            builder.append(uuid2Name.get(winners.getString(0)));
        } else {
            builder.append(uuid2Name.get(winners.getString(0)));
            for (int m = 1; m < winners.size(); m++) {
                String winner = winners.getString(m);
                builder.append(" & ").append(uuid2Name.get(winner));
            }
        }
        builder.append("\n");
    }
    private void CreateScores(StringBuilder builder, JSONObject teamA, JSONObject teamB) {
        JSONArray scoresA = teamA.getJSONArray("score");
        JSONArray scoresB = teamB.getJSONArray("score");
        builder.append("score:");
        String first = JSONPath.eval(scoresA, "$[0].game") + ":"
                + JSONPath.eval(scoresB, "$[0].game");
        builder.append(first);
        for (int m = 1; m < scoresA.size(); m++) {
            String once = JSONPath.eval(scoresA, "$[" + m + "].game") + ":"
                    + JSONPath.eval(scoresB, "$[" + m + "].game");
            builder.append(" | ").append(once);
        }
        builder.append("\n-----\n");
    }

2、选手信息嵌套简单,只需要直接读取对应的数据即可。

    private String CreateOutput() {
        StringBuilder builder=new StringBuilder();
        JSONArray players = playerJsonObject.getJSONArray("players");
        for (int i = 0; i < players.size(); i++) {
            JSONObject player = players.getJSONObject(i);
            String name = player.getString("full_name");
            String gender = player.getString("gender");
            if (gender.equals("M")) {
                gender = "male";
            } else {
                gender = "female";
            }
            String nationality = (String) JSONPath.eval(player, "$.nationality.name");
            builder.append("full_name:").append(name).append("\n");
            builder.append("gender:").append(gender).append("\n");
            builder.append("nationality:").append(nationality).append("\n-----\n");
        }
        return builder.toString();
    }

五、程序性能改进

1.程序优化大概花费20min,主要在实现阶段完成。
2.此程序大部分优化可以通过在方法前进行空判断以跳过某次循环或不需要创建对象直接输出。
3.不同对象中的跳转查找可以进行结构优化封装,在解析类中实现类似数据库的联合查找。(未实现)
4.由于功能类只支持单条指令,故在循环使用功能时若有连续相同的指令可在内部缓存读取出的对象,避免反复解析。

六、单元测试展示

整体测试用例及输出结果

输出过长故只显示部分输出

1.程序入口测试:

测试函数创建input.txt文件并创建上图的指令,类型包括前后空格、多分隔、错误指令、错误文件名等。输出后将数据从output.txt读取至控制台并删除文件。


    private void InitInputText() {
        File file = new File("input.txt");
        if (file.exists()) {
            file.delete();
        }

        try {
            file.createNewFile();
            FileWriter writer = null;
            writer = new FileWriter(file, true);
            writer.write("player\n");
            writer.write("result.\n");
            writer.write(" player\n");
            writer.write("\n");
            writer.write("result 1\n");
            writer.write("result 01 16\n");
            writer.write("players 1\n");
            writer.write("result 01161\n");
            writer.write("result 0116\n");
            writer.write("result 0116\n");
            writer.write("players\n");

            writer.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

工具类JsonParseUtil测试,主要测试是否找到文件。


    @Test
    public void Test() {
        assertNull(JsonParserUtil.readJsonObject("6"));
        JSONObject obj= JsonParserUtil.readJsonObject("src/data/players.json");
        assert obj != null;
    }

2.最终覆盖率:

img

3.优化

经判断部分的IOException(文件是否存在)没有测试到,即文件是否存在的问题。

七、异常处理

计算部分的异常分为文件异常和指令的异常,文件名不存在或其他错误因方法固定需要而生成try-catch语句块,指令异常判断为null(非法指令),N/A(Json文件不存在)

八、心得体会

此次项目完成时间上与预期相差很大,分析后原因有:1.旧数据的结构复杂,同时需要分析属性作用。2.没有单元测试经验,误判了单元测试的时间。3.以为Json数据结构简单。4.中途变更了数据 5.需求分析阶段时间不充分,导致花费大量时间创建了无用数据。
不过由于在其他项目中解析过Json数据,故时间可以整体缩减。对项目整体分析后,认为整体结构还可以更好,如减少一些嵌套等。

...全文
225 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
张书旖 助教 2023-03-14
  • 打赏
  • 举报
回复

项目的解题思路可以写的再详细一点哈,继续加油!

688

社区成员

发帖
与我相关
我的任务
社区描述
2023年福州大学软件工程实践课程W班的教学社区
软件工程团队开发软件构建 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • 张书旖
  • 郭渊伟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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