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

221900239_张书旖 学生 2022-03-05 17:37:17
这个作业属于哪个课程2022年福大-软件工程、实践-W班
这个作业要求在哪里软件工程实践第二次作业——个人实战
这个作业的目标GitCode项目上传、代码编写并测试、博客撰写
其他参考文献参考文献见于文末

目录

  • 一、Gitcode项目地址
  • 二、PSP表格
  • 三、解题思路描述
  • 3.1 冬奥会数据的爬取
  • 3.2 数据的处理
  • 3.3 指令的处理
  • 3.4 json对象的解析
  • 3.5 文件的读写
  • 四、接口设计和实现过程
  • 4.1 程序中的类
  • 4.2 各类中的函数和变量展示
  • 4.3 函数之间的关系
  • 4.4 程序流程图
  • 五、关键代码展示
  • 六、性能优化
  • 6.1 性能优化的重要性
  • 6.2 优化的思路
  • 6.3 优化的思路
  • 6.4 优化的结果分析
  • 七、单元测试
  • 7.1 部分测试函数
  • 7.2 测试覆盖率情况
  • 八、异常处理
  • 九、心得体会
  • 参考文献


一、Gitcode项目地址


二、PSP表格

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

三、解题思路描述

之前有听说过17级的学长学姐的软工实践作业是疫情数据的收集和统计。因为是特别贴近我们生活的事情,当时觉得好厉害,原来到了大三可以完成这么有实际作用的项目。(我以为等到大三以后自己的编程能力能飞速成长,就可以像学长学姐一样。谁知道自己大三以后一看题目还是两眼一模黑,知道思路但是代码不会写)
我认为这次的题目和之前的疫情数据收集很相似,都是需要爬取网站的数据然后根据用户的需求将数据按照指定的格式输出。思路有了,不会那就学!对题目做了充分的分析之后,我觉得这次的题目主要有以下需求:

  • 爬取冬奥会的相关数据并进行适当的处理

  • 对获得的json对象进行解析

  • 读取用户输入的文件,分析用户输入的指令

  • 根据用户指令将相应的数据或是错误信息写入输出文件

3.1 冬奥会数据的爬取

注:本次数据的爬取行为仅用于课程教学
一开始以为要在程序中实现数据爬取,所以还急急忙忙地搜了好多数据爬取的教学视频 (之前只是听过爬虫,从来没有深入了解过T_T)
后来知道可以直接到网站上爬取数据然后存放在本地文件夹中,松了一口气~



根据作业的要求,我们需要得到2022年冬奥会的奖牌总榜数据以及每日赛程数据。下面演示爬取奖牌总榜数据的过程:

首先,需要打开央视的冬奥专栏,点击进入奖牌榜页面。然后按下F12打开开发者模式,选择网络一栏并重新载入页面,便可以查阅浏览器详细的网络活动信息。

在这里插入图片描述

依次查看浏览器请求的文件,可以发现有一个名为getbjOlyMedals的文件就是我们要找的奖牌榜的数据。

在这里插入图片描述

鼠标右键点击该文件在新的标签页中打开,就可以获得我们需要的源数据——奖牌榜api

在这里插入图片描述

由于每日赛程数据的获取过程与总榜相似,所以就不再进行演示了。在查找每日赛程的数据时,在冬奥专栏的每日赛程板块中获取数据,很容易发现参数startdatecn代表的就是是对应的赛程日期,通过修改startdatecn字段的值就可以得到相应日期的赛程信息。
这里给出一个2月14日的赛程api:2月14日赛程

3.2 数据的处理

原本打算用Java语言发送网络请求来获取网页数据,但因为冬奥会的赛事数据是固定的且题目没有要求在程序中爬取数据,所以我直接复制api中的数据进行处理。
由于从冬奥会专栏中复制下来的源数据只有一行,且其中的中文字符显示为Unicode编码,并非要求的UTF-8。为了便于后续程序的开发,要对数据进行适当的处理。
我先将获取的源数据放到vscode中,将json数组两端多余的括号删去。再使用vscode-json插件对所得数据进行格式化。这样就得到了与老师所给数据格式相同的数据。

在这里插入图片描述

因为没有在程序中爬取数据的需求,所以我将处理好的数据都保存在本地的文件夹中。这样每次查询时就不需要再在网页中爬取数据,可以减少因网络请求而消耗的时间。

3.3 指令的处理

说来惭愧,因为自己开始的比较晚,大家在群里已经列举了很多有关输入指令的问题。所以我把所有可能出现的指令以及对应的输出都列举出来:

  • 正确的指令: total和schedule 赛程日期(赛程日期需在冬奥会比赛期间且格式为例如0203的四位数字)

  • 日期不符合要求的指令: schedule 不符合要求的字符串(如shcedule 1312、shcedule sss、shcedule 212、shcedule 0228等)

  • 不正确的指令: 指令的第一个词不是total或schedule的字符串(如schedule0202、Total、sss等)

根据以上分类,我使用split函数按照空白字符对每行指令包含的词进行划分,由此来对指令分类处理。
对于正确的指令,我根据题目给的示范输出样例进行了分析。将json文件中将会用到的属性都提前罗列下来,保证数据的正确性。为后续json对象的解析提供一定便利。(事实证明,这样做是有好处的。把数据分析清楚能够让编程思路更清晰,不至于手忙脚乱忽略了细节)

3.4 json对象的解析

需求更新说可以使用第三方库之后,我一开始打算使用Gson来解析json对象。但是因为自己不太理解Gson的使用并且没有看到非常适合的教程,中途想过不使用第三方库,直接用字符串函数来解析json对象。
然后在DDL即将到来之际,我看到了一篇博客:就是这篇就是这篇! 这篇博客非常详细地讲解了使用jsonObject对象解析json文件的过程。因为上学期Android课上老师讲的json解析就是采用的jsonObject对象。我看完之后茅塞顿开,仿佛找到了救命稻草,火速转成使用Fastjson来解析json文件。
以下是json解析部分的代码:

//获取奖牌总榜列表
public static ArrayList<CountryRank> getMedalsList() throws IOException{
    ArrayList<CountryRank> medalsList =new ArrayList<>(); //存放奖牌总榜列表
    //运用JSONObject对象实现json字符串到JavaBean对象之间的转换
    JSONObject object= JSONObject.parseObject(jsonToString("./src/data/total.json")); //获得json字符串对应的对象
    JSONObject data=object.getJSONObject("data"); //获得data对应的json对象
    JSONArray list=data.getJSONArray("medalsList"); //获得data对象中的medalsList对象数组
    for (int i=0;i<list.size();i++){
         JSONObject o=list.getJSONObject(i); //通过数组下标获取json对象
         //将json字符串转换为JavaBean对象
         CountryRank country=JSON.parseObject(o.toJSONString(),CountryRank.class);
         medalsList.add(country);
    }
    return medalsList; //返回赛程总榜列表
}

3.5 文件的读写

  • 对于文件的读写,我选择了性能较好的BufferedReaderBufferedWriter对象。
  • 同时为了减少频繁打开关闭输出文件消耗的时间,我将所有的输出结果都存在一个静态的ArrayList中,等所有指令都处理完后再将结果输出到文件中。这样只需要打开一次输出文件就可以完成结果的写入。

四、接口设计和实现过程

4.1 程序中的类

//主类,负责文件中指令的读取、分类指令并调用其他类中指令处理函数、调用输出函数
public class OlympicSearch {...}
//工具类,负责完成程序的主要功能
public class Lib {...}
//存放国家奖牌榜信息的类
class CountryRank{...}
//存放赛程信息的类
class Match{...}

4.2 各类中的函数和变量展示

  • OlympicSearch类
//指令的输出列表
ArrayList<String> resultList=new ArrayList<String>();

//程序的入口函数,负责读取输入文件中的指令并调用Lib中的函数分类处理,最后输出至文件中
public static void main(String[] args){...}
  • Lib类
//使用HashMap存放已经查找过的数据,每次输出时就只需要查表获来获取数据
static HashMap<String,ArrayList<String>> presentData=new HashMap<>();

//判断输入的指令类型(-1:整行空格;0:赛程信息;1:日期非法指令;2:奖牌总榜;3:错误指令
public static int judgeInstruction(String instruction){...}
    
//读取json文件内容并转换为json格式字符串
public static  String jsonToString(String filename) throws IOException{...}

//实现json字符串到JavaBean对象数组的转换,返回奖牌总榜对象数组
public static ArrayList<CountryRank> getMedalsList() throws IOException{...}

//实现json字符串到JavaBean对象数组的转换,获取对应日期的赛程信息
public static ArrayList<Match> getMatchList(String date) throws IOException{...}

//返回奖牌总榜对应的字符串数组,用于主函数中输出结果的拼接
public static ArrayList<String> showTotal() throws IOException{...}

//返回对应日期赛程的字符串数组,用于主函数中输出结果的拼接
public static ArrayList<String> showMatchList(String instruction) throws IOException{...}

//返回输入错误的提示信息,用于主函数中输出结果的拼接
public static String showError(){...}

//返回N/A信息的提示信息,用于主函数中输出结果的拼接
public static String showNA(){...}

//判断日期是否合法,日期应该为合法日期且是冬奥会的比赛时间
public static boolean isRightDate(String date){...}

//将数据写入输出文件中
public static void writeFile(String filename,ArrayList<String> resultList) throws IOException{...}

//去除文件末尾的换行符
public static void deleteEndLine(String filename) throws IOException{...}
  • CountryRank类
private String rank;        //国家奖牌数排名
private String countryid;   //国家名称缩写
private String gold;        //金牌数
private String silver;      //银牌数
private String bronze;      //铜牌数
private String count;       //奖牌总数

//生成符合输出格式的国家奖牌榜信息的字符串
public String toString() {...}

//以及所有字段对应的get和set函数
...
  • Match类
private String startdatecn;  //比赛时间
private String itemcodename; //运动类别
private String title;        //赛事名称
private String homename;     //对抗方一国家名
private String awayname;     //对抗方二国家名
private String venuename;    //比赛场地

//生成符合输出格式的赛程信息的字符串
public String toString() {...}

//以及所有字段对应的get和set函数
...

4.3 函数之间的关系

1. main函数:

  • 调用Lib.judgeInstruction函数进行指令类型的判断;

  • 调用Lib.showMatchList函数获得指定日期的赛程信息对应的字符串列表

  • 调用Lib.showTotal函数获得奖牌总榜对应的字符串列表。

  • 调用Lib.showError函数获得错误信息对应的字符串

  • 调用Lib.showNA函数获得格式错误信息的字符串

  • 调用Lib.writeFile函数将结果列表输出到输出文件中

2. Lib.judgeInstruction函数:

  • 调用isRightDate函数来判断日期是否符合要求

3. Lib.showMatchList函数:

  • 调用Lib.getMatchList函数获得指定日期赛程信息的Match对象列表

  • 调用Match.toString函数获得指定格式的输出字符串

4. Lib.showTotalList函数:

  • 调用Lib.getMatchList函数获得指定日期赛程信息的Match对象列表

  • 调用CountryRank.toString函数获得指定格式的输出字符串

5. Lib.getMatchList函数和getMedalsList函数:

  • 调用Lib.jsonToString函数输入对应的json文件路径来获取相应json文件对应的json格式的字符串。

6. Lib.writeFile函数:

  • 调用Lib.deleteEndLine函数来删除文件末尾多余的换行符

4.4 程序流程图

img


五、关键代码展示

  • judgeInstruction函数: 使用split函数对每一行指令按照空白字符切割。根据切割而来的数组判断指令的类型:
    • 返回值为-1:表示指令整行都为空白字符,跳过不处理
    • 返回值为0:表示指令符合输出赛程信息的指令规范,主函数中将添加赛程信息
    • 返回值为1:表示指令对应的赛程日期不符合要求,主函数中将添加N/A信息
    • 返回值为2:表示指令符合输出奖牌榜的规范,主函数中将添加奖牌榜信息
    • 返回值为3:表示指令为无法识别的指令,主函数中将添加Error信息
//-1:整行空格;0:赛程信息;1:日期非法指令;2:奖牌总榜;3:错误指令
public static int judgeInstruction(String instruction){
//因为指令前后多余的空格忽略,所以使用split(“\\s+”)来删去所有的空白字符,包括空格、制表符、换页符
    String regex="\\s+"; 
    String ins[]=instruction.trim().split(regex); //将每一行指令按照空白字符切割
    if (ins[0].equals(""))
        return -1;  //读到整行都为空格,则跳过
    //用户输入指令为输出赛程信息
    if (ins[0].equals("schedule")){
        if (ins.length==2&& Lib.isRightDate(ins[1]))
            return 0;  //日期格式符合要求
        else //用户输入的赛程日期不合法
            return 1;
     }
     //用户输入指令为输出奖牌榜
     else if (ins[0].equals("total")){
        if (ins.length==1)
            return 2;
        else //该行除了total指令外还有其他语句,属于无法识别的指令
            return 3;
     }
     else //其余输入均为错误输入
        return 3;
}
  • jsonToString函数: 使用BufferReader对象读取json文件中的内容,然后利用stringBuffer对象进行字符串的拼接,最后返回json格式的字符串
//读取json文件内容并转换为json字符串
public static  String jsonToString(String filename) throws IOException{
    String jsonLine;  //存放json文件的每一行
    StringBuffer stringBuffer=new StringBuffer(); //用来进行字符串的拼接
    BufferedReader reader = new BufferedReader(new 
        InputStreamReader(new FileInputStream(filename), StandardCharsets.UTF_8));
    while ((jsonLine=reader.readLine())!=null)
        stringBuffer.append(jsonLine);  //将json文件的每一行拼接成一个字符串
    reader.close(); //关闭输入流
    return  stringBuffer.toString();
}
  • getMatchList函数: 首先利用JSONObject对象的parseObject方法将json格式的字符串转换为json对象。再通过getJSONObject方法通过键值获取赛程信息的json对象数组matchList。最后利用parseObject方法将json对象转换为Match对象,并返回Match对象的列表。获取奖牌总榜的getMedalsList函数同理。
//获取对应日期的赛程信息并返回
public static ArrayList<Match> getMatchList(String date) throws IOException{
    ArrayList<Match> matchList =new ArrayList<>(); //存放赛程列表
    //运用JSONObject对象实现json字符串到JavaBean对象之间的转换
    //获得json字符串对应的对象
    JSONObject object= JSONObject.parseObject(jsonToString("./src/data/schedule/"+date+".json")); 
    JSONObject data=object.getJSONObject("data"); //获得data对应的json对象
    JSONArray list=data.getJSONArray("matchList"); //获得data对象中的matchList对象数组
    for (int i=0;i<list.size();i++){
        JSONObject o=list.getJSONObject(i); //通过数组下标获取json对象
        //将json字符串转换为JavaBean对象
        Match match=JSON.parseObject(o.toJSONString(),Match.class);
        matchList.add(match);
}
    return matchList;  //返回赛程列表
}
  • showMatchList函数: 首先分解输入的指令,通过split函数切割指令获得用户指定的赛程日期。再将日期作为键值,判断presentData表中是否存在该日期对应赛程信息。
    • 若赛程信息已存在,则直接返回其对应的输出;
    • 若赛程信息不存在,则通过getMatchList函数获取赛程信息对象列表,将列表中每一个比赛对应的信息添加到输出列表中并返回。最后将获取到的数据保存在presentData表中方便下次查找。
    • 返回奖牌总榜的showTotal函数同理。
//返回对应日期的赛程信息
public static ArrayList<String> showMatchList(String instruction) throws IOException{
    String regex="\\s+"; //筛选所有空白字符
    String ins[]=instruction.trim().split(regex); //将每一行指令按照空白字符切割
    String date=ins[1]; //获得指定的日期
    //若当前表中已有对应日期的赛程数据则直接返回
    if (presentData.containsKey(date))
        return presentData.get(date);
    //若当前没有对应日期的赛程数据则获取数据并添加到已有数据表中
    ArrayList<Match> list=getMatchList(date); //获得赛程信息列表
    ArrayList<String> matchList=new ArrayList<>(); //存放输出的字符串列表
    for (Match country:list)
        matchList.add(country.toString());
    presentData.put(date,matchList); //将数据添加到presentData表中方便下次查找
    return matchList;
}
  • toString函数: 使用StringBuffer对象进行字符串的拼接。对于对抗赛事的输出,我观察了以下原本的json文件,发现非对抗赛事的homename数据为空。所以我从homename字段入手,通过判断该字段是否为空来选择是否加上对抗信息。
//生成赛程信息的字符串
public String toString() {
    StringBuffer stringBuffer=new StringBuffer(); //用来进行字符串的拼接
    stringBuffer.append("time:");
    stringBuffer.append(startdatecn.substring(11,16)); //将时间的时和分切割出来
    stringBuffer.append("\nsport:");
    stringBuffer.append(itemcodename);
    stringBuffer.append("\nname:");
    stringBuffer.append(title);
    if (!homename.equals("")){ //出战国家名非空,说明为对抗赛事
        stringBuffer.append(" ");
        stringBuffer.append(homename);
        stringBuffer.append("VS");
        stringBuffer.append(awayname);
    }
    stringBuffer.append("\nvenue:");
    stringBuffer.append(venuename);
    stringBuffer.append("\n-----\n");
    return stringBuffer.toString();
}
  • writeFile函数: 使用BufferedWriter对象将输出列表的数据写入输出文件中,最后去掉末尾的换行符。
//将数据写入输出文件中
public static void writeFile(String filename,ArrayList<String> resultList) throws IOException{
    File file=new File(filename);
    if (!file.exists())  //输出文件不存在则创建一个新的文件
        file.createNewFile();
    BufferedWriter writer = new BufferedWriter(new 
        OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8));
    for (String result:resultList)  //依次向文件中输出结果
        writer.write(result);
    writer.close(); //关闭输出流
    deleteEndLine(filename);  //去除文件末尾的换行符
}

六、性能优化

6.1 性能优化的重要性

我最开始尝试跑了一万条左右的数据,发现性能优化前后的运行时间相差并不太大。我还暗暗担忧是不是自己性能优化的效果不好。
结果在我尝试用优化前的程序跑了一百五十万条数据(input1.txt)后,我看着我的命令行缓慢地输出,风扇呼呼地响,电脑烫的起飞。最后的最后,我等到的不是结果,是静止的电脑。因为程序占用的内存太大了,抛出了异常!(太久没清内存了T_T) 这时我才意识到,性能优化有多重要!

在这里插入图片描述

6.2 优化的思路

分析了一下代码发现,其实影响本次程序运行效率的主要因素有以下两点:

  • 文件的频繁读取: 优化之前,每次需要输出赛程以及奖牌榜数据时,都要到本地文件夹中去读取相应的json数据,文件的频繁读取会消耗很多时间。
  • 字符串的拼接: 因为String的值是不可变的,这就导致每次对String对象进行拼接操作时操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间。

6.3 优化的思路

  • 既然文件读取需要消耗很多时间,那就减少读取的次数。我将已经输出过的奖牌总榜和赛事数据,都存放在HashMap中。
    这样在查询结果时,先查表判断数据是否已经存在:数据存在则直接输出,不存在才读取文件中的数据。这样牺牲内存,以空间换时间,可以大大减少因文件读取而消耗的时间。
  • 采用StringBuffer对象进行字符串的拼接。 StringBuffer是可变类和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。这样可以缩短因频繁创建对象而消耗的时间。

6.4 优化的结果分析

为了进行性能测试,我构建了一个约有十七万条有效指令(只包含total和schedule 正确日期的指令)的数据文件input2.txt。使用该文件作为输入文件,观察改进前后程序的运行时间。
未改进前,程序的运行时长为:286718ms(jar包运行)。

在这里插入图片描述

改进后,程序的运行时长为:17391ms(jar包运行)。

在这里插入图片描述

可以看到,才十万级的数据,性能就提高了大概十六倍!多么可怕的数字哇~

我再使用之前一百五十万行左右的有效指令文件input1.txt进行测试,运行时长为26169ms(源码运行),此时输出文件大小为3.2G(没有异常了,电脑不卡了,好起来了!)

在这里插入图片描述

JProfiler分析如下:

在这里插入图片描述

由此可以见得性能优化在项目开发过程中真的很重要!
(在性能的调试过程中我还发现了一个很神奇的现象:一开始我直接在命令行运行jar包得到的程序的运行时间。但是因为要使用JProfiler插件来监控运行情况,所以我在IDEA中又运行了一遍原来的数据。对比二者运行时间后我发现:对于相同的指令文件,控制台程序的运行速度居然比命令行的jar包要快十倍以上!但是很遗憾没有找到解释这种现象的博客,所以不太明白其中的缘由)


七、单元测试

因为IDEA可以很方便地安装JUnit的单元测试插件,所以我在IDEA中使用JUnit4进行单元测试。设计并计算好好要输入的指令和预期所得的结果,编写测试的代码并运行,对比实际的结果和预期结果是否相符,获得测试的结果,并观察代码的覆盖率。

7.1 部分测试函数

  • 判断指令类型函数的测试函数
@Test
   void judgeInstruction() {
       assertEquals(-1,Lib.judgeInstruction("    ")); //空格,跳过
       assertEquals(0,Lib.judgeInstruction("schedule 0212")); //输出赛程的指令
       assertEquals(1,Lib.judgeInstruction("schedule 1312")); //日期不合法的指令
       assertEquals(1,Lib.judgeInstruction("schedule sss")); //日期不合法的指令
       assertEquals(1,Lib.judgeInstruction("schedule 212"));  //日期不合法的指令
       assertEquals(1,Lib.judgeInstruction("schedule 0228"));  //日期不合法的指令
       assertEquals(2,Lib.judgeInstruction("total"));  //输出赛程总榜的指令
       assertEquals(3,Lib.judgeInstruction("Total"));  \\错误的指令
       assertEquals(3,Lib.judgeInstruction("schdule0202")); \\错误的指令
       assertEquals(3,Lib.judgeInstruction("-sss"));                   \\错误的指令
   }
  • json格式字符串转换函数的测试函数
 @Test
    void jsonToString() {
        String content,result=new String();
        String inputPath="test/jsonToStringIn.txt"; //输入的json文件的文件路径
        String correctPath="test/jsonToStringCo.txt"; //预期结果的文件路径
        StringBuffer buffer=new StringBuffer();
        try { //读取预期结果文件中的数据并存在buffer中
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(correctPath), StandardCharsets.UTF_8));
            while ((content=reader.readLine())!=null)
                buffer.append(content);
            result=Lib.jsonToString(inputPath); //获取jsonToString函数得到的实际结果
        } catch (IOException e) {
            e.printStackTrace();
        }
        assertEquals(buffer.toString(),result); //对比预期结果和实际结果
    }

7.2 测试覆盖率情况

在这里插入图片描述

最终的覆盖率为98%,除了一些异常处理没有办法自行抛出,其他部分代码都得到了覆盖。


八、异常处理

本次作业的异常主要有以下几种:

  • RuntimeException: 主要是用户参数输入错误的异常

    在这里插入图片描述

  • FileNotFoundException: 文件不存在的异常

    在这里插入图片描述

  • IOException: 主要是与文件读写有关的异常

    在这里插入图片描述


    所有的异常都在主函数中进行捕获并处理

    在这里插入图片描述


九、心得体会

  • 虽然之前做项目的时候有用过Git、GitHub,但是并没有真正掌握git作为版本控制工具的要义。通过这次作业我更加深入地了解了Git的相关知识,明白了版本控制的重要性,体会到了Git的便捷。

  • 自己的知识面还是不够广,很多项目相关的知识还是不了解 (之前从来没听说过单元测试) 以前看到过一句话感觉说的很有道理:“不要停下前进的脚步,否则世界就会忘了你”

    接下来的学习过程中还是要拓宽自己的知识面多接触新的知识,跳出舒适区,不断学习,这样才能提升自己的编程水平!希望自己能通过接下来的实践学到更多的项目开发的知识。 (认真脸)

  • 一定要边编程边写博客,这样能及时将自己的解题思路记录下来。博客也能作为编写代码时的参考,可以不断完善内容。最后才写博客容易忘东忘西,思路不清晰。拒绝拖延症!!!早点开始写真的会从容很多! (自己的经验教训T_T)

  • 性能的优化对于软件的开发来说真的很重要!虽然输出的结果是相同的,都能满足客户的需求,但是好的程序能给用户最好的体验。这一定是未来的软件开发生涯中必须要时刻注意的。


参考文献


...全文
652 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
SoftwareTeacher 2022-03-07
  • 打赏
  • 举报
回复

控制台程序的运行速度居然比命令行的jar包要快十倍以上!但是很遗憾没有找到解释这种现象的博客,所以不太明白其中的缘由


控制台是指你的 IDE么?

221900239_张书旖 学生 2022-03-07
  • 举报
回复
@SoftwareTeacher 是的老师,控制台是我在IDEA上运行的结果。测试的时候偶然发现了这种情况,但是不太理解原因
Jingbin-Wang 教师 2022-03-07
  • 打赏
  • 举报
回复
设计和优化思路清晰,赞👍🏻希望这次作业能让你体会优化的意义,在将来项目开发中保持这个理念。加油!
221900239_张书旖 学生 2022-03-07
  • 举报
回复
@Jingbin-Wang 谢谢老师,我会继续努力的!

142

社区成员

发帖
与我相关
我的任务
社区描述
2022年福大-软件工程;软件工程实践-W班
软件工程 高校
社区管理员
  • FZU_SE_teacherW
  • 丝雨_xrc
  • Lyu-
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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