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。