寒假作业2/2

这个作业属于哪个课程 课程
这个作业要求在哪里 作业
这个作业的目标 <阅读《构建之法》、学习使用git以及github、编写程序使用PSP进行时间管理和总结>
其他参考文献 ...

任务一

问题一

我看了1.1软件=程序+软件工程 里面的文字“我上班后,发现以前同事写的程序真是垃圾,根本看不懂,无法维护。我要推 翻重写!后来一个老员工笑嘻嘻地告诉我,我们现在看到的程序,就是去年的新员工愤怒地推翻重写之后的结果,大家反映还没有以前的版本好用呢。”,编写程序的语言是不断更新换代的,之前有遇到由于语言的不通而对程序有不同的影响,会产生一些莫名其妙的bug,程序随着时间变得庞大,系统会逐渐脆弱,对变化会越来越敏感,当接手到别人的项目代码中,有的时候不知道从哪里下手,也许别人的项目代码并不能支持当前的第三方库版本,我认为:后期程序需要大量的维护,重写的效率也许会更高,我的问题是“相比重写,后期程序的大量维护有其他更好的方法吗?”

问题二

我看了11.4。1把修改集集成到代码库中,里面“具体步骤如下:1. 根据场景和开发任务来决定集成的次序 2. 互相依赖的任务要一起集成 3. 在测试场景时,要保证端到端的测试 4. 场景的所有者必须保证场景完全通过测试,然后把场景的状态改为“解决” 这里有一个疑惑“多个修改集成到代码库中,当集成代码冲突是否更容易产生新的bug”,功能分配中有交集或功能区块分配大容易产生代码冲突,自己的思考是“功能分配中尽量不要有交集,功能区块分配尽量小“那么集成代码的过程中比如之后的团队合作的时候,并不能每个人都刚好分配到具体的功能。我的疑惑是“在集成代码的时候应该需要注意什么准备工作来避开代码冲突吗?”

问题三

我看了11.5.2每日构建,里面“阿超:我好像有几天没有收到每日构建的报告了。小飞:已经有一阵子没成功了。 阿超:哦?我们上课的时候不是说过“每日构建”的重要性么? 小飞:我同意在我们有时间的情况下,要做每日构建,但是工作一忙起来,我们的确没有时间去管构建的问题。”,有个疑惑“每日构建既然很重要,那对于我们学生平时应该注意强调每日构建吗?每日构建具体是什么?”每日构建意味着自动地,每天,完整地构建整个代码树,每天完整构建整个代码树会不会是一个巨大的工程?对于我们之后的项目,每日构建既然是基本功我们现在就应该养成每日构建的习惯吗?

问题四

我看了16.1创新的迷思,里面的文字“不但大众不喜欢创新,甚至连创新者自己都不例外,有些创新者甚至恨创新。”"在算法和数据库领域,创新的想法一开始往往不被接受,而那些建立 在前人基础上的“线性扩展”则往往有着更好的命运。而这些决定还是很有经验的 期刊审稿人做出来的",有了这个疑惑“创新一开始并不能被接受,那么相对的可能没有利益,创新也许不少但是能带来利益的很少”“没有利润的驱动,创新也会遭受过剩”,我的困惑是“除了利益因素以外,创新还应该坚持吗?这些‘过剩’的创新有价值吗?”

问题五

我看了16.1.1和16.1.5“它们没有提到这些科学巨人在顿悟之前已经在相关学科 打下了深厚的基础,同时他们也为这些问题进行了长时间的思考,那些看似神奇 的时刻才会光顾他们”“迷思之五:要成为领域的专家,才能创新 ”,有了疑惑“创新需要深厚的基础但是后文又讲并不是需要成为领域的专家才能创新”,科技创新高度既然依赖于深厚的基础科学积累,在我看来,其他人在拿手领域外得到的创新少之又少,我们主要注重自己专业方面的创新,平时不会注重其他领域的创新,那么在拿手领域外其他领域得到的创新跟该领域的基础又有什么关系呢?

任务二

Github项目地址

PSP表格如下:

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 15 10
• Estimate • 估计这个任务需要多少时间 5 5
Development 开发 360 400
• Analysis • 需求分析(包括学习新技术) 120 150
• Design Spec • 生成设计文档 30 35
• Design Review • 设计复审 30 25
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 30 40
• Design • 具体设计 60 40
• Coding • 具体编码 300 360
• Code Review • 代码复审 60 60
• Test • 测试(自我测试,修改代码,提交修改) 240 300
Reporting 报告 180 180
• Test Report • 测试报告 180 180
• Size Measurement • 计算工作量 5 10
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 10 20
合计 1725 1815

解题思路

刚开始拿到题目后,题目中命令行参数,统计文件中的字符数、单词总数、有效行数、单词出现次数、字典序、文件输入输出等。
使用的语言是java,命令行参数可以通过Main函数传入的参数args[]来获取,文件的输入输出通过InputStreamReader和OutputStreamWriter来读写,通过BufferedReader来一个个读取文件中的字符,最后统计的单词次数通过HashMap来存储,之后转化为ArrayList来排序获取前十单词。

代码规范

计算模块接口的设计与实现过程,关键代码,解释思路,独到之处

lib();
void fileCount(String inputFile);//读取文件,通过BufferedReader读取字符,通过读取的字符来判断计数
void CountChar(int x );//charCount++
void CountLine(int x);//遇到换行符如果该行包括非空白字符则+1
void CountWord(int x);//分隔符后若无4个英文字母则不计入单词数中,反之调用addWordMap(word)且wordCount+1
void addWordMap(String word);//将单词转化为小写,已存在value+1,不存在word为key,value=1;
void getWordTopTen();//转化为list,重写排序顺序
void writeFile(String outputFile);

判断单词部分由于单词必须以4个英文字母开头,非字母数字符号做分隔符

void CountWord(int x){
        if(((x<='Z'&&x>='A')||(x<='z'&&x>='a'))&&letterCount!=-1){
            word += (char)x;
            letterCount++;;
        }
        //前4个包含数字
        else if (((x<='Z'&&x>='A')||(x<='z'&&x>='a'))&&letterCount==-1){
            letterCount=-1;
        }
        else if(x<='9'&&x>='0'&&letterCount<4){
            letterCount=-1;
            word = "";
        }
        //前4个全是英文
        else if (x<='9'&&x>='0'&&letterCount>=4){
            word += (char)x;
        }
        //遇到分隔符
        else{
            if(letterCount>=4){
                wordCount++;
                addWordMap(word);
            }
            letterCount = 0;
            word = "";
        }
    }

排序代码

        list = new ArrayList<Map.Entry<String, Integer>>(wordMap.entrySet());
        list.sort(new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                if(o1.getValue().equals(o2.getValue())) {return o1.getKey().compareTo(o2.getKey());}
                else {return o2.getValue().compareTo(o1.getValue());}
            }
        });

写入文件代码

            out = new OutputStreamWriter(new FileOutputStream(outputFile),"UTF-8");
            StringBuilder str = new StringBuilder();
            str.append("characters: "+charCount+"\n"
                    + "words: "+wordCount+"\n"
                    +"lines: "+lineCount+"\n");
            for(int i = 0;i<(list.size()<10 ? list.size():10);i++){
                str.append(list.get(i).getKey()+": "+list.get(i).getValue()+"\n");
            }
            out.write(str.toString());

计算模块接口部分的性能改进

刚开始的时候使用String来连接字符串,但是查阅资料得String使用+=连接字符串要重新初始化一个String对象来赋值,这就浪费了时间和空间,改进用了StringBuilder
使用BufferedReader缓存流来读取字符,查阅资料对文件io的速度有所提升
排序的算法将HashMap转化为List,重新定义List的排序比较规则,对较多数据的排序时间有所缩短

计算模块部分单元测试展示,单元测试得到的测试覆盖率截图

计算模块正确性部分

  1. 测试统计字符功能

测试数据是ASCII码0-127
ASCII字符都能被统计出来,汉字不在测试文档中不做测试

  1. 测试统计行数用例

测试数据是" "+"\n"+"\t"+"\n"+"\r"+"\n"
仅存在空白字符的行数不会被统计

  1. 测试单词数

测试用例 file123 1file fil1e
以上都不为单词

  1. 测试单词前10

测试用例
测试数据"aaaa2,aaaa20,aaaa30,aaaa19\n"*循环次数5次,末尾append("aaaa9\n")

    for(int i=0;i<str.length();i++){
        lib.CountWord(str.charAt(i));
    }
    lib.getWordTopTen();
    String str1 = "";
    String str2 = "aaaa19:5\naaaa2:5\naaaa20:5\naaaa30:5\naaaa9:1\n";
    for(int i=0;i<lib.list.size();i++){
        str1+= lib.list.get(i).getKey()+":"+lib.list.get(i).getValue()+"\n";
    }
    Assert.assertEquals(str2,str1);

测试结果:

覆盖率截图

如何提高覆盖率

一个函数中尽量不写过长的代码,少些条件分支,避免多次读写文件

计算模块部分异常处理说明

计算模块异常为文件io处理异常和命令行参数少于两个会导致数据越界,代码本身没有设置其他的异常

心路历程与收获

加深了对Java语言的认识,对于命令行参数,文件io,同时也熟悉了使用Github来存放和更新自己的代码,为今后的项目开发积累了经验。在完成作业的同时也通过查阅资料发现了之前很多自己疏忽的知识点。同时也接触了单元测试,在测试过程中能注意到自己在开发过程中疏忽的点,但是测试数据需要多加思考,才能确保原来代码的正确性。在与同学们的交流中也收获了许多,认识到了自己的不足,为之后的项目需要自己掌握更多的知识点,对每个项目都要努力进行测试和优化,尽量做到更好。

posted @ 2021-03-04 21:26  Poisson7  阅读(130)  评论(4编辑  收藏  举报