软工实践寒假作业(2/2)
软工实践寒假作业(2/2)
这个作业属于哪个课程 | 2020春S班 (福州大学) |
---|---|
这个作业要求在哪里 | 软工实践寒假作业(2/2) |
这个作业的目标 | 1.学习github使用 2.制定代码规范 3.学习PSP表格规划 4.对简单项目进行项目需求分析并编程实现 5.学习使用单元测试和性能测试工具 |
作业正文 | 软工实践寒假作业(2/2) |
其他参考文献 | 《码出高效_阿里巴巴Java开发手册》 |
1. Github仓库地址
https://github.com/CrowlLiu/InfectStatistic-main
2. PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 30 | 35 |
Estimate | 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 240 | 300 |
Analysis | 需求分析 (包括学习新技术) | 120 | 90 |
Design Spec | 生成设计文档 | 60 | 60 |
Design Review | 设计复审 | 20 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 60 | 45 |
Design | 具体设计 | 20 | 20 |
Coding | 具体编码 | 300 | 360 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 300 | 270 |
Reporting | 报告 | 120 | 100 |
Test Repor | 测试报告 | 20 | 30 |
Size Measurement | 计算工作量 | 15 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1385 | 1440 |
3. 解题思路描述
3.1 程序功能分析
此次程序需要以下功能:
1. 能够读取命令行中的命令并执行命令;
2.能够读取对应路径下的日志;
3.能够对日志内容进行统计、输出指定内容、进行排序等。
3.2 数据结构选择
程序要求对各省份共四类人员的数量进行列表输出,属于二维数据,故而采用List<Provience> allPrvns来处理数据。
3.3 命令行输入的处理
由于日志文件的数据格式是固定的,所以可以进行格式化输入输出的处理,在对Java的输入输出处理方法进行查找之后,得知了Java中Pattern类和Matcher类可以用于匹配字符,对格式化输入输出进行处理。
4. 设计实现过程
4.1 总体流程
4.2 类图
其中main方法为程序入口,Provience类用于处理四类感染人员,inputCommand方法负责处理命令行输入并执行命令,locatLog处理日志路径,locateOut处理输出文件路径,其他方法实现各命令行指令。
4.3 函数流程图
5. 代码说明
5.1 inputCommand方法
//处理命令行输入并执行命令
public static void inputCommand(String[] args)
{
if (args[0].equals(("list")))
{
for (int i = 1; i < args.length; i++)
{
switch (args[1])
{
case "-log":
order = "-log";
locateLog(args[++i]);
break;
case "-out":
order = "-out";
locateOut(args[++i]);
break;
case "-date":
order = "-date";
setDate(args[++i]);
break;
case "-type":
order = "-type";
while (i + 1 < args.length)
{
switch (args[++i])
{
case "IP":
selectType(TYPE_STR[0]);
case "SP":
selectType((TYPE_STR[1]));
case "cure":
selectType((TYPE_STR[2]));
case "dead":
selectType(TYPE_STR[3]);
}
}
break;
case "-provience":
order = "-provience";
while (i + 1 < args.length)
{
i++;
for (int k = 0; k < PRVNS_STR.length; k++)
{
if (args[i].equals(PRVNS_STR[k]))
{
selectProvience(PRVNS_STR[k]);
break;
}
}
}
break;
}
}
}
}
5.2 getData方法
//读取日志数据
public static ArrayList<File> getData()
{
ArrayList<File> beforeFile = new ArrayList<>();
Date thedate = new Date(1900 - 1900, 1 - 1, 1);
String fileName;
try
{
//查找指定日期日志文件
File file = new File(logPathStr);
if (file == null)
{
throw new IOException();
}
File[] fileList = file.listFiles();
for (int i = 0; i < fileList.length; i++)
{
if (fileList[i].getName().equals(theDateStr + ".txt"))
{
thedate = parseDate(theDateStr);
break;
}
}
//找出指定日期文件之前的文件
for (int i = 0; i < fileList.length; i++)
{
fileName = fileList[i].getName();
if (thedate.after(parseDate(fileName.substring(0, fileName.length() - 4))))
{
beforeFile.add(fileList[i]);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
return beforeFile;
}
5.3 countData方法
//统计数据
public static boolean countData(ArrayList<File> beforeFiles)
{
String pattern1 = "\\W+ 新增 感染患者 \\d+人";
String pattern2 = "\\W+ 新增 疑似患者 \\d+人";
String pattern3 = "\\W+ 感染患者 流入 \\W+ \\d+人";
String pattern4 = "\\W+ 疑似患者 流入 \\W+ \\d+人";
String pattern5 = "\\W+ 死亡 \\d+人";
String pattern6 = "\\W+ 治愈 \\d+人";
String pattern7 = "\\W+ 疑似患者 确诊感染 \\d+人";
String pattern8 = "\\W+ 排除 疑似患者 \\d+人";
BufferedReader br = null;
Date thedate = new Date(1900 - 1900, 1 - 1, 1);
String fileName;
String[] strs;
try
{
//对指定日期前的文件进行统计
for (int i = 0; i < beforeFiles.size(); i++)
{
fileName = beforeFiles.get(i).getName();
if (thedate.after(parseDate(fileName.substring(0, fileName.length() - 4))))
{
try
{
br = new BufferedReader(new FileReader(fileName));
String strLine = br.readLine();
while (strLine != null)
{
strs = strLine.split(" ");
for (int j = 0; j < PRVNS_STR.length; j++)
{
//匹配省份
if (PRVNS_STR[j].equals(strs[0]))
{
//统计人数 新增感染 新增疑似 流入感染 流入疑似 新增治愈 新增死亡 疑似确诊 排除疑似
if (Pattern.matches(pattern1, strLine))
{
Pattern p = Pattern.compile(pattern1);
Matcher m = p.matcher(strLine);
allPrvns.get(j).IP += Integer.parseInt(m.group(1));
}
else if (Pattern.matches(pattern2, strLine))
{
Pattern p = Pattern.compile(pattern2);
Matcher m = p.matcher(strLine);
allPrvns.get(j).SP += Integer.parseInt(m.group(1));
}
else if (Pattern.matches(pattern3, strLine))
{
}
else if (Pattern.matches(pattern4, strLine))
{
}
else if (Pattern.matches(pattern5, strLine))
{
Pattern p = Pattern.compile(pattern5);
Matcher m = p.matcher(strLine);
allPrvns.get(j).CURE += Integer.parseInt(m.group(1));
}
else if (Pattern.matches(pattern6, strLine))
{
Pattern p = Pattern.compile(pattern6);
Matcher m = p.matcher(strLine);
allPrvns.get(j).DEAD += Integer.parseInt(m.group(1));
}
else if (Pattern.matches(pattern7, strLine))
{
}
else if (Pattern.matches(pattern8, strLine))
{
}
}
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
throw new IOException();
}
catch (IOException e)
{
e.printStackTrace();
return false;
}
}
5.4 output方法
//格式化输出文件到指定目录下
public static void output(ArrayList<Provience> provienceArrayList, int[] proviences, int[] Type)
{
try
{
File file = new File(outPathStr + "\\"theDateStr + ".txt");
if (!file.exists())
{
file.createNewFile();
}
FileWriter fileWriter = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fileWriter);
for (int i = 0; i < proviences.length; i++)
{
bw.write(PRVNS_STR[proviences[0]]
+ " 感染患者" + provienceArrayList.get(proviences[0]).IP
+ "人 疑似患者" + provienceArrayList.get(proviences[0]).SP
+ "人 治愈" + provienceArrayList.get(proviences[0]).CURE
+ "人 死亡" + provienceArrayList.get(proviences[0]).DEAD
+ "人");
bw.write("// 该文档并非真实数据,仅供测试使用");
bw.write("// 命令:list -log " + logPathStr + " -out " + outPathStr + " -date "
+ theDateStr);
}
bw.close();
System.out.println("写入完成");
}
catch (IOException e)
{
e.printStackTrace();
}
}
6. 单元测试截图和描述
7. 单元测试覆盖率优化和性能优化
8. 代码规范链接
https://github.com/CrowlLiu/InfectStatistic-main/blob/master/example/codestyle.md
9. 本次项目的心路历程与收获
大一大二学习了C、C++、Java的时候,类似于这种对文件读入读取,进行统计、增删查改的系统已经写过两三次了,此次的项目在有之前的基础做铺垫的情况下还算顺利,程序本身不难,但是此次项目对需求的分析,对程序的用例测试,对性能的分析和优化等方面的工作是之前所从未做过的。通过此次项目对一个项目工程从立项分析到设计实践再到最后的测试优化的流程有了一个初步的了解,这在以前是从来没有过的。
通读过《工程师的能力评估与发展》后,我对优秀软件工程师的是如何开发代码、职业的规划、未来的发展等方面有了一个大体的了解,并对在一个项目开始之前对项目的需求分析,技术明确的重要性有了深刻的认识。
10. 技术路线图相关的仓库
1. vuejs/vue https://github.com/vuejs/vue
Vue.js的官方github库
2. bootstrap-vue / bootstrap-vue https://github.com/bootstrap-vue/bootstrap-vue
具有超过40个插件和超过75个自定义组件,为Vue.js提供了最全面的Bootstrap v4组件和网格系统实现。
3.SignalR / SignalR https://github.com/SignalR/SignalR
ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。
4. mono / mono https://github.com/mono/mono
第三方的跨平台的.NET运行环境,它包含了一个C#语言的编译器,一个CLR的运行时,和一组类库,并实现了 ADO NET和ASP NET。能够使得开发人员在Linux用C#开发程序。
5. abpframework / abp https://github.com/abpframework/abp
ABP是一个开源应用程序框架,专注于基于ASP.NET Core 的Web应用程序开发,但也支持开发其他类型的应用程序