项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2016级软件工程 |
这个作业的要求在哪里 | 第四次作业要求 |
课程学习目标 | 熟悉软件开发整体流程,提升自身能力 |
本次作业在哪个具体方面帮助我们实现目标 | 第一次体验一个完整的工程 |
任务一:
点评的博客:201671030103仇素龙实验二词频统计软件项目报告
点评博客的代码的github链接地址:实验二代码
点评内容:1.本篇博客写的很认真,排版也比较清晰,老师所要求的基本功能也都基本实现了。但是还是存在一些问题。首先是实验结果的截图result.txt文件不应该在Java界面直接给出,而是应该写在单独的文本文件中。再一个“结果发现这次程序设计包含的模块其实很清楚”,由此句话可以看出来博主在编写程序的时候没有做好充分的准备就写代码,这是不对的,而后面博主在进行了需求分析等一系列工作之后对自己要编写的代码也有了清楚的了解这点很好。最后,在PSP部分,博主在“估计这个任务需要多少时间,并规划大致工作步骤”的时候预估会花费20分钟,这显然是不合适的,还希望博主以后能够进行合理的PSP规划。2.在运行对方的代码的时候,学到了很多知识。我在第二个实验的时候没有实现柱状图的统计这一个功能,但是对方却用了一个简单的方法用“X”的多少来代表其柱的长短,这也是一种方法。这让我知道了有时候在我们遇到不会解决或者没办法解决的问题的时候我们可以试着去换一个思路,说不定效果就比我们预期的要好很多。
点评心得:通过阅读对方的博客和查看代码,可以学到很多自己没有注意到或欠缺的东西,比如进行一个项目之前如何很好的进行需求分析,需求分析和任务分配对后续的代码实现部分有多大的影响。在实现的时候遇到自己没有办法实现的功能要求的时候可以转换自己的想法,用简单易懂的方法来代替没有办法完整描述的功能。上一次的实验我们两个都没有实现人机交互界面,所以在这次的实验中我们两个在这一方面下了很大的功夫来进行学习和改善,进我们最大的努力实现了人机交互界面。
任务二:
一、项目要求
- 项目相关要求
(1)结对合作开发进度计划的要求:在项目正式开发之前,预估本次合作开发任务的PSP环节的消耗时间,并在PSP过程中统计实际耗时,填写PSP表格。
(2)尝试采用汉堡包法实施项目结对中两个人的沟通。
(3)理解领航员和驾驶员两种角色关系:两人都必须参与程序的编码工作,在结对编程中两个人轮流做对方的角色。
(4)github仓库中的代码提交要体现两人合作过程,不能只看到最终的代码,至少有三次以上的代码签入记录, 能显示代码从最初的基本框架, 基本功能,到全部功能实现的构建过程 。
(5)编撰两人合作开发遵守共同认可的编码规范,并提交编码规范文档到github项目仓库根目录下。
(6)将包含任务2的源码以增量方式提交到指定同学注册Github账号下的项目仓库中,要求项目仓库中要能看到项目多次commit的记录,同时必须有两个人各自的commit记录。
二、实现过程
需求分析:
- (1)实验2要求的功能;
(2)单词频数可视化柱状图要求是以下样式:
<img src="https://img2018.cnblogs.com/blog/1616082/201904/1616082-20190402141356938-694653612.png"width="300" hegiht="213" align=center />
(3)统计该文本行数及字符数;
(4)各种统计功能均提供计时功能,显示程序统计所消耗时间(单位:ms);
(5)可处理任意用户导入的任意英文文本;
(6)人机交互界面要求GUI界面(WEB页面、APP页面都可);
(7)附加分功能:统计文本中除冠词、代词、介词之外的高频词;
(8)附加分功能:统计前10个两个单词组成的词组频率。
软件设计:使用类图
- 类图的关系如下:
核心功能代码展示:展示核心功能代码
(1)单词频数利用可视化柱状图实现
public JFreeChart ShowCountHistogram(BufferedReader bufferedReader) throws IOException {
CategoryDataset dataset = getDataSet(bufferedReader);
JFreeChart chart = ChartFactory.createBarChart3D(
"英文文本词频统计图", // 图表标题
"单词名称", // 目录轴的显示标签
"次数", // 数值轴的显示标签
dataset, // 数据集
PlotOrientation.VERTICAL, // 图表方向:水平、垂直
true, // 是否显示图例(对于简单的柱状图必须是false)
false, // 是否生成工具
false // 是否生成URL链接
);
CategoryPlot plot=chart.getCategoryPlot(); //获取图表区域对象
CategoryAxis domainAxis=plot.getDomainAxis(); //水平底部列表
domainAxis.setLabelFont(new Font("黑体",Font.BOLD,14)); //水平底部标题
domainAxis.setTickLabelFont(new Font("宋体",Font.BOLD,12)); //垂直标题
ValueAxis rangeAxis=plot.getRangeAxis();//获取柱状
rangeAxis.setLabelFont(new Font("黑体",Font.BOLD,15));
chart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 15));
chart.getTitle().setFont(new Font("宋体",Font.BOLD,20)); //设置标题字体
return chart;
}
(2)统计文本中除冠词、代词、介词之外的高频词的实现
public Map<String, Integer> selectExceptFunctionWord(BufferedReader bufferedReader) throws IOException {
Map<String, Integer> map = this.selectWordCountByDOrder(bufferedReader);
Map<String, Integer> exceptFunction = new LinkedHashMap<String, Integer>();
for (Map.Entry<String, Integer> w :map.entrySet()) {
if(!w.getKey().equals("the")&&!w.getKey().equals("is")&&!w.getKey().equals("you")&&!w.getKey().equals("yourself")&&!w.getKey().equals("your")&&!w.getKey().equals("them")&&!w.getKey().equals("their")&&!w.getKey().equals("to")&&!w.getKey().equals("by")&&!w.getKey().equals("is")&&!w.getKey().equals("a")&&!w.getKey().equals("and")&&!w.getKey().equals("was")&&!w.getKey().equals("has")&&!w.getKey().equals("had")&&!w.getKey().equals("I")&&!w.getKey().equals("for")&&!w.getKey().equals("my")&&!w.getKey().equals("me")&&!w.getKey().equals("with")&&!w.getKey().equals("of")&&!w.getKey().equals("in")&&!w.getKey().equals("on")&&!w.getKey().equals("that")&&!w.getKey().equals("it")&&!w.getKey().equals("The")&&!w.getKey().equals("at")&&!w.getKey().equals("which")&&!w.getKey().equals("he")&&!w.getKey().equals("as")
&&!w.getKey().equals("but")&&!w.getKey().equals("his")&&!w.getKey().equals("from")&&!w.getKey().equals("some")&&!w.getKey().equals("be")&&!w.getKey().equals("were")&&!w.getKey().equals("not") &&!w.getKey().equals("they")&&!w.getKey().equals("this")&&!w.getKey().equals("an")&&!w.getKey().equals("no")&&!w.getKey().equals("into")&&!w.getKey().equals("It")&&!w.getKey().equals("there")&&!w.getKey().equals("But")&&!w.getKey().equals("him")&&!w.getKey().equals("could")&&!w.getKey().equals("been")&&!w.getKey().equals("would")&&!w.getKey().equals("she")&&!w.getKey().equals("then")&&!w.getKey().equals("Then")&&!w.getKey().equals("have"))
{
exceptFunction.put(w.getKey(), w.getValue());
}}
return exceptFunction;
}
(3)降序排列
public Map<String, Integer> selectWordCountByDOrder(BufferedReader bufferedReader) throws IOException {
Map<String, Integer> map = this.AllWordCount(bufferedReader);
List<Map.Entry<String, Integer>> nlist = new LinkedList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(nlist, new Comparator<Map.Entry<String, Integer>>()
{
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2)
{
int compare = (o1.getValue()).compareTo(o2.getValue());
return -compare;
}
});
Map<String, Integer> result = new LinkedHashMap<String, Integer>();
for (Map.Entry<String, Integer> entry : nlist) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
程序运行:程序运行时每个功能界面截图
-
主界面:
-
获取文本行数的结果:
-
获取文本字符数:
-
获取词频按照字典顺序排序:
-
读取文本词频获取柱状图:
-
读取指定单词出现次数:
- 读取文本获得前K个高频词
-
获取文本降序排列
-
读取冠词、介词、代词以外的高频词
描述结对的过程,提供两人在讨论、细化和编程时的结对照片(非摆拍)
1、我们两个在编程中的照片
<img src="https://img2018.cnblogs.com/blog/1616082/201904/1616082-20190402151202944-2013361638.jpg"width="300" hegiht="213" align=left />
<img src="https://img2018.cnblogs.com/blog/1616082/201904/1616082-20190402151315939-277331831.jpg"width="300" hegiht="213" align=right/>
2、对对方的评价
(1)是一个友善的人,愿意合作与交流,在与我的合作学习和探究活动中,能选择自己擅长的方式(语言、文字、图表等)表述研究过程和结果;主动提供自己的资料和想法,与我分享自己智慧,思路,体验合作的愉快。能倾听和尊重我提出的不同观点和评议,能对研究过程和结果进行评议,并与我交换意见,充分体现结对编程的价值。
(2)是个谦逊的人,在与我的合作交流中,我们做到相互尊重,相互信赖,认真倾听对方意见,勇于承认自己的不足,有虚心向对方学习请教的良好风尚,能在合作交流中正确地评价自己和他人,学会分享他人成功的喜悦。能够在合作交流中明确自己的责任,并履行自己承担的职责。具有与他人进行合作交流的态度与能力。
(3)有集体责任感,善于合作。在合作学习中充分发挥自己的特长,为实现集体目标作出了贡献。积极搜索资料,善于彼此分享交流,有无私的精神。尊重并理解他人,具有创新精神和动手操作能力,养成了合作交流的习惯。
(4)在结对合作学习过程中,能创造和谐的气氛,促进小组成员之间和谐的共同的完成各自任务,为养成健全人格奠定了基础。能为研究活动准备、计划,全面统筹的能力得到了锻炼;能总结“‘共同解决了什么问题、小组还有什么问题没有解决?”“我们小组做得最好的是哪些人?还有哪方面他们能够做得更好?”具有一定的领导才能。
3、对方编程习惯总结
我的搭档仇素龙同学编程非常规范,有着一定的编程水准,代码完整规范。而且具有一定的数据结构和算法功底,在这次项目的编写过程中数据库的基础都得到充分的体现。虽然编写代码速度不快,但是程序执行起来效率高,审核代码得时候也比较快,和她搭档非常舒服,是我学习的榜样。
提供此次结对作业的PSP
PSP2.1 | 任务内容 | 计划共完成需要的时间(h) | 实际完成需要的时间(h) |
---|---|---|---|
Planning | 计划 | 0.4 | 0.4 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 15 | 20 |
Development | 开发 | 2 | 3 |
Analysis | 需求分析 (包括学习新技术) | 5 | 6 |
Design Spec | 生成设计文档 | 2 | 1.5 |
Design Review | 设计复审 (和同事审核设计文档) | 1 | 1 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 0.5 | 0.5 |
Design | 具体设计 | 5 | 5 |
Coding | 具体编码 | 15 | 18 |
Code Review | 代码复审 | 0.5 | 0.5 |
Test | 测试(自我测试,修改代码,提交修改) | 0.5 | 0.5 |
Reporting | 报告 | 1 | 2 |
Test Report | 测试报告 | 0.5 | 0.5 |
Size Measurement | 计算工作量 | 0 | 0 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 0.5 | 0.5 |
- 本次项目总结和反思:
首先通过这篇博文我们对结对编程有了进一步的认识,实际操作的时候,分工跟预想的并不完全一样,我们首先讨论出了具体的编程想法,由于我们两个的编程能力都不太好,其中一些代码的实现花费了很多时间,但是两个人学习总比一个人的学习效率高。最后还是完整的写出了这次项目。谈下结对编程的优缺点吧,首先说优点。第一、可以发散思维,两个人一个小时能讨论出来的东西,或许一个人一个星期都没法想出来。第二、可以减少代码复审率,当一个人写出一段代码的时候,另一个人作为旁观者往往更容易发现其中的问题。第三、在技术互补的情况下,可以很大程度的提高效率。其次是缺点,最大的问题就是数据结构的问题,虽然在面向对象的框架下,都可以写各自的类和方法,但是核心代码对其他函数的调用还是很多的,由于互相不熟悉变量名称和效果,传值时还需要自己来写,这个很麻烦。比如仇素龙设计核心代码时,用到我写的外部函数,就得询问我,或者直接让我来写调用了。另一个问题就是效率问题,有时候由于工作的重复性以及讨论的不恰当性,会导致达不到1+1>2的效果。总的说来,我从软件工程这门课程里得到的收获是非常大的,虽然需要很多的时间,但是通过完成项目,不仅可以学到技术知识,而且更获得了许多宝贵的合作经验,更收获了深厚的友谊。 - 本次项目源码在此处查看