第四次软工作业——结对编程

GIT地址 GITHUB克隆地址
结对伙伴 余睿哲
伙伴学号 201831061417
伙伴博客地址 地址

一、PSP表格


二、接口的设计与实现过程

设计:

共五大类,其中计算方法类和命令行翻译类两个类需要设计对应的接口。

详细内容见下面思维导图(如果图片看不清可以适当放大网页观看

各类之间的关系

CountMethodImpl类 为Main类提供各种算法

TranslateCommandImpl类 则翻译Main类传过去的命令行指令,并返回需要的参数

WriteFile类 主要用于文件读写

Test类 用于测试各种类中的方法能否正确实现

Main类 中执行主函数,集成所有功能。

关键函数及实现方法(见思维导图)

程序运行结果

注:有效行数与看到的行数不同的原因:文档窗口的大小不同,会导致显示的行数不同,如果文档窗口足够长,则该文章(测试文章)可显示为一行

用到的几种设计理念

Interface Design

为两个比较重要,且内部函数较多的类设计了接口

Loose Coupling

设计了五大类,将各个部分分开,想要加减功能可以在对应的类中进行更新,对整体影响较小

Information Hiding

使用一些常量将ASCII码、条件语句以及循环的参数保存起来,即隐藏了数据也提高了代码的可读性。


三、代码复审

编码规范

参考《阿里巴巴JAVA开发手册》

开始阅读

IDEA编译器可以下载审查插件

插件扫描结果,即还存在的问题:

改正后:

还存在一定的问题是因为:

1、有一个类为最早写的测试类,里面有较多直接使用的数字(以后会多加注意)。

2、有变量定义为numberM和numberN,是符合小写驼峰命名法的,是插件扫描判断错误。


四、性能改进

性能改进

接口实现的函数中,大多数都需要用到循环,循环的时间复杂度不算多,但也不算少。所以在循环中减少不必要的循环,不如在需要跳出循环时跳出循环,减少循环次数等等,即可减少一定的时间消耗,从而提高性能。

性能工具:JProfiler(IDEA的性能测试插件)

安装方法

性能分析图

主函数因为集成了所有工具类的方法,所以消耗最大

主函数代码如下

public static void main(String[] args) {
	//输入命令行
	Scanner scanner = new Scanner(System.in);
	String cmd = scanner.nextLine();
	//创建需要的对象
	TranslateCommandImpl translate = new TranslateCommandImpl();
	CountMethodImpl method = new CountMethodImpl();
	WriteFile writeFile = new WriteFile();
	//得到需要的参数
	String inFile = translate.returnInFile(cmd);
	String outFile = translate.returnOutFile(cmd);
	int numberM = translate.returnNumberM(cmd);
	int numberN = translate.returnNumberN(cmd);
	//能否读到文件,不能则停止
	try {
		InputStream in = new FileInputStream(inFile);
	}catch (IOException e) {
		System.out.println("文件位置有误!");
		return;
	}
	//用于保存各种数据
	int characters, words, lines;
	//词频Map中的长度
	int length;
	//判断有无-i, -o指令
	String noFile = "null";
	if(noFile.equals(inFile) || noFile.equals(outFile)) {
		System.out.println("输入或者输出不能为空!");
		return;
	}
	//用于保存单词集
	List<String> strings;
	//定长单词集
	List<String> lengthWords;
	characters = method.countCharacterNumber(inFile);
	strings = method.countWordNumber(inFile);
	words = strings.size();
	lines = method.countLine(inFile);
	lengthWords = method.statisticsWord(strings, numberM);
	//得到词频的Map
	List<Map.Entry<String, Integer>> frequency = method.countWordsFrequency(strings);
	//保存定长词频
	List<Map.Entry<String, Integer>> neededFrequency = new ArrayList<>();
	//得到其长度,方便遍历
	int maxLength = 10;
	length = frequency.size();
	//如果长度大于10,则把长度变成10
	if(length > maxLength) {
		length = 10;
	}
	//打印结果
	System.out.println("字符总数是:"+characters);
	System.out.println("有效单词数是:"+words);
	System.out.println("有效行数是:"+lines);
	System.out.println("单词的出现频率从高到低依次是:");
	for(int i=0; i<length; i++) {
		System.out.println(frequency.get(i));
	}
	if(numberM > 0) {
		System.out.println("定长为 "+numberM+" 的单词是:"+lengthWords);
	}
	//如果参数n大于Map中的大小,则打印有效个。
	if(numberN > length) {
		numberN = length;
	}
	if(numberN > 0) {
		System.out.println("出现评率最高的前"+numberN+"个单词依次是:");
		for(int i=0; i<numberN; i++) {
			System.out.println(frequency.get(i));
			neededFrequency.add(frequency.get(i));
		}
	}
	//写入文件
	writeFile.writeFile(outFile, characters, words, lines, lengthWords, neededFrequency);
}

五、单元测试及其覆盖率展示

测试有效行的计算

函数构造思路:得到数据后,打印文章行数

数据构造思路:文章中有空行,看程序能否正确判断

测试有效单词的读取

函数构造思路:得到数据后,统计有效单词数后打印

数据构造思路:文章中有部分非有效单词,看程序能否成功判断并存入单词集合中。

测试命令行参数的获取

函数构造思路:给定一条命令行指令,看能否正确地获得参数

数据构造思路:给定各种形式的命令行进行测试,看能否正确获得参数;以及命令行有问题时能否正确报错。


六、异常处理说明

注:异常处理都在主函数中直接进行测试

异常一:命令行没有 -i 或 -o指令

异常二:无法读取到文件


七、结对过程

描述:

这次很幸运能够找到也同样是写JAVA的同学余睿哲。分工明确,因为我在一开始就对这个程序的编写有比较明确的思路,所有完成了大部分代码的编写;相应的他完成了很多代码的审计工作。结对编程让我感到一个复杂程序的编写,因为两个人的合作与努力变得简单了。结对期间没有发生任何矛盾,每个人都把自己的做的那部分任务做到了最好。代码的编写期间也有过阻碍,通过两个人的共同思考解决了问题。让我真切的感受到1+1>2。

照片如下:

posted @ 2019-10-09 22:25  NyimaC  阅读(449)  评论(5编辑  收藏  举报