软工实践寒假作业(2/2)
这个作业属于哪个课程 | 2021春软件工程实践S班 |
---|---|
这个作业要求在哪里 | 软工实践寒假作业(2/2) |
这个作业的目标 | 阅读《构建之法》,学习github的使用,完成WordCount项目 |
其他参考文献 | 《构建之法》、关于单元测试和回归测试、github简单教程、github fork 与pull request |
任务一:阅读《构建之法》并提问
问题1:该怎么样保护自己的创新?
“有创新当然很好,但是怎么保护创新呢?就像你的城堡一样,有护城河来保护么?果冻是学校里的第一个学会魔方口诀的,在学校这个小范围里姑且算一种创新,但是你的竞争力有护城河么——你能否保持只有你会背这个口诀》如果没有,那有可能大家都来学,然后人手一个魔方,很快就有人超过你了。” (P373)
在现实中,也有很多人借用了别人的创新做出了更加热门的产品,或者直接使用盗版软件,比如windows系统,很多人使用的都是盗版windows。所以我们应该怎样保护自己的创新呢,我查阅了资料,有几种方法,比如说申请专利,掌握先手优势,不要将创意告知他人等。
问题2:业绩和价值间应该如何取舍,如何判断员工价值观的好坏?
“如果业绩很好,但价值观不太对路(不太听话?),则是一条野狗。要坚决清除,不然功高震主......”
“如果业绩和价值观都取得双丰收,那就是明星员工了,可以用藏獒来命名。”。 (P407-408)
我上网查询得知,一个不好的价值观会给团队带来很多负面影响,影响业绩。但我认为价值观不像业绩一样可以直观的分出好坏,很多时候一个人的业绩能做的好,则说明这个人的价值观也是有好的地方的高。所以我们应该如何正确判断一个业绩好的人是“野狗”还是“藏獒”呢?
问题3:如何选择合适的团队模式
《构建之法》第5章 团队和流程 5.2软件团队的模式 (P92-101)
在《构建之法》的第5章团队和流程的5.2软件团队的模式(P97)中,作者列举了很多团队模式,比如“主治医师模式”、“明星模式”、“社区模式”等。在我以往的团队作业中,经常发展成为书中的“主治医师模式”,只由团队中的一两个人干活,其他同学都在打酱油。我认为这是由于没有进行好的任务分配造成的,这导致每个人都不清楚自己在团队中的位置以及自己应该干什么。所以我觉得在任务开始之前团队应该讨论每个人应该干什么,以及每个人什么时候能完成任务,让每个人都参与进团队中。
问题4:什么是敏捷
《构建之法》第6章 敏捷流程 (P115)
看了《构建之法》第六章后我还是不能很好地理解“敏捷”这个概念。我认为“敏捷”应该是要以用户的需求为核心、设定优先级、积极交流、提高效率的意思,可能不够准确。
问题5:惊喜功能会影响用户体验吗
“还有一种是让用户惊喜(delighter)功能,这些功能一旦出现(尽管质量不是太好),就能给用户满意度带来正面的帮助,随着此类功能质量的提高,用户会非常满意这个产品。用户可能会因为这样的功能而给这个APP打高分。 (P176)”
现实生活中的QQ与微信,两者都是社交聊天软件,QQ不仅“基本功能”和“核心功能”没比微信差,还有很多微信没有的“惊喜功能”,比如“皮肤装饰”、“QQ空间”、“扩列”等。但是微信的用户数量和用户的活跃度都领先QQ,我认为可能是这类“惊喜功能”太多,增加了APP的使用难度,让年龄较大的用户觉得不好用导致的。
二、附加题
以前电脑储存成本很高,压缩软件相比来说就非常重要。然而一家独大的压缩软件ARC却要收费,Phil Katz看不惯就自己写了个免费的压缩软件兼容了ARC,结果被ARC打压。他一气之下索性自己写了个zip出来,算法比ARC更加优秀并且直接免费发放,最后zip把ARC搞垮了。随后基于zip的7-zip的推出让我们现在能够理所应当得用着高质量的免费压缩工具,这都多亏了Phil Katz的开源精神,然而他自己却染上了酗酒的恶习,穷困潦倒早早在37岁时孤独的死在了汽车旅馆里。现在流行的Winrar,因为zip格式免费就毫无压力地兼容zip,而靠着自己rar的授权费让很多免费zip软件无法亏血本反向兼容rar而成就了其压缩软件的霸主地位。
Phil Katz自己呕心沥血付出生命为之奋斗的开源精神却被其他人用来反制于自己,觉得挺悲哀的,看了这个故事,让我对以后软件究竟是要收费还是免费有了新的见解。
任务二:WordCount编程
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 20 |
•Estimate | •估计这个任务需要多少时间 | 30 | 20 |
Development | 开发 | 1450 | 1460 |
•Analysis | •需求分析 (包括学习新技术) | 600 | 630 |
•Design Spec | •生成设计文档 | 30 | 30 |
•Design Review | •设计复审 | 20 | 30 |
•Coding Standard | •代码规范 (为目前的开发制定合适的规范) | 50 | 30 |
•Design | •具体设计 | 90 | 80 |
•Coding | •具体编码 | 600 | 580 |
•Code Review | •代码复审 | 30 | 30 |
•Test | •测试(自我测试,修改代码,提交修改) | 30 | 50 |
Reporting | 报告 | 120 | 120 |
•Test Repor | •测试报告 | 40 | 30 |
•Size Measurement | •计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | •事后总结, 并提出过程改进计划 | 60 | 70 |
合计 | 1600 | 1500 |
解题思路
看了一下题目的要求,发现要求用到挺多新知识,比如github、代码规范、单元测试等,于是我先通过老师分享的链接和网上的一些视频、博客等资料进行自学,顺便复习了一下JAVA。对整个题目有了大致的思路后,根据题目的要求,对功能进行划分。
- 统计字符数
- 统计单词数
- 统计行数
- 统计最多的10个单词及其词频
解决相应的功能时,我会通过自己思考并上网查阅资料等方式找到合适的解决方法,功能完成后,再进行相应的单元测试,测试成功后就对这次作业进行总结和编写博客。
设计与实现过程
- 读取文件,每个功能运行时都要先读取文件。
public static Reader InputFile(String fileName) {
File file = new File(fileName);
Reader reader = null;
try {
reader = new InputStreamReader(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("找不到输入文件!");
}
return reader;
}
- 统计字符数:对文件进行读取,每读取一个字符CharactersNum加1,当读取到-1时,说明文件读取完成,停止while循环,并输出字符数。
public static int CountCharacters(String InputFile, String OutputFile) throws IOException {
Reader reader = InputFile(InputFile);
Writer writer = new FileWriter(OutputFile);
int CharactersNum = 0; //文件字符数
while (reader.read() != -1) //读取到-1时停止。
{
CharactersNum++;
}
writer.write("characters:" + CharactersNum + '\n');
writer.close();
reader.close();
return CharactersNum;
} // 统计字符数。
- 统计单词数,用了正则表达式"[a-zA-Z]{4}[^ ,.]+"判断是否为四个英文开头
public static int CountWords(String inputFile, String outputFile) throws IOException {
Reader reader = InputFile(inputFile);
Writer writer = OutputFile(outputFile);
int length; //表示单词的长度,大于等于4合法
int temp;
int WordsNum = 0;
String word = "";
String regex = "[a-zA-Z]{4}[^ ,.]+"; //正则表达式判断是否为四个英文开头
Pattern p = Pattern.compile(regex);
while ((temp = reader.read()) != -1)
{
while ((temp >= 97 && temp <= 122) || (temp >= 65 && temp <= 90) || (temp >= 48 && temp <= 57)) {
word += (char) temp;
temp = reader.read();
}
while ((!(temp >= 97 && temp <= 122) || (temp >= 65 && temp <= 90) || (temp >= 48 && temp <= 57)) && temp != -1) //去除空白字符和分隔符
{
temp = reader.read();
}
Matcher m = p.matcher(word);
length = word.length();
if (length >= 4 && m.matches()) //使用正则表达式
{
WordsNum++;
}
word = "" + (char)temp;
}
writer.append("words: " + WordsNum + '\n');
writer.close();
reader.close();
return WordsNum;
} //统计单词数
- 在统计单词频率功能中,通过对Map进行排序得出单词频率的排序。
Map<String, Integer> WordsSort = words.entrySet().stream().sorted(new Comparator<Map.Entry<String, Integer>>()
{
public int compare(Map.Entry<String, Integer> w1, Map.Entry<String, Integer> w2)
{
if (w1.getValue().equals(w2.getValue()))
{
return w1.getKey().compareTo(w2.getKey());
}
else
{
return w2.getValue().compareTo(w1.getValue());
}
}
}
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(oldValue, newValue) -> oldValue, LinkedHashMap::new)); //对单词频率进行排序
单元测试
- 测试能否正确读取文件
@Test
public void InputFile() throws IOException {
String inputFile3 = "D:\\test\\test3.txt";
assertEquals(null,Lib.InputFile(inputFile3));
} //测试读取文件失败时的运行结果
- 测试字符数统计功能,通过比较函数返回值是否与实际值相等来判断是否成功,用两个输入文件,提高测试案例。
@Test
public void testCountCharacters() throws IOException {
String inputFile1 = "D:\\test\\test1.txt";
String inputFile2 = "D:\\test\\test2.txt";
String outputFile = "D:\\test\\out.txt" ;
if(Lib.CountCharacters(inputFile1, outputFile) == 521)
{
System.out.println("字符数统计功能测试成功");
}
if(Lib.CountCharacters(inputFile2, outputFile) == 15)
{
System.out.println("字符数统计功能测试成功");
}
} //测试字符数统计功能
-
单词数统计、行数统计、单词频率统计的单元测试和字符数统计差不多,我就不放代码了。
-
单元测试覆盖率
异常处理说明
- 当命令行没有输入两个文件名时,会输出"需要输入两个文件名!"。
public static void main(String[] args) throws IOException {
if (args.length != 2)
{
System.out.println("需要输入两个文件名!");
System.exit(0);
}
- 当文件不存在时抛出IO异常,并输出"找不到输入文件!"。
public static Reader InputFile(String fileName) {
File file = new File(fileName);
Reader reader = null;
try {
reader = new InputStreamReader(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("找不到输入文件!");
}
return reader;
}
});
心路历程与收获
刚开始看到这个作业时,我觉得挺难的,因为这涉及了很多我从来没学过的新知识,同时我也在想要用C++还是Java来完成这次作业,虽然我更熟悉C++一些,但是这学期不少课要用到Java的,比如JavaEE、设计模式与软件体系结构等课程,于是我就想提高一下Java水平,选择用Java来完成作业,所以这次作业花了我很多时间在学习知识和编写代码上。虽然很累,但是觉得收获很大,通过上网查找资料、看视频学习,我不仅学会了很多新知识,对整个作业也渐渐有了思路,但是由于时间比较紧迫,有一些知识还没有完全理解,运用的不是很好,比如单元测试、性能测试等,完成作业以后有时间还要进一步学习,同时以后也要对时间做出更好的安排。