# 第四周做業之wcPro核心模塊的實現java
## 1、基本任務:代碼編寫+單元測試git
### 小組github地址github
https://github.com/SkateCloud/wcPro編程
### PSP表格數組
<div style="text-align: left" align="center">
<table>
<thead>
<tr class="header"><th align="center">PSP2.1</th><th align="center">PSP階段</th><th align="center">預估耗時(分鐘)</th><th align="center">實際耗時(分鐘)</th></tr>
</thead>
<tbody>
<tr class="odd">
<td align="center"><strong>Planning</strong></td>
<td align="center">計劃</td>
<td align="center">30</td>
<td align="center">60</td>
</tr>
<tr class="even">
<td align="center">Estimate</td>
<td align="center">估計任務須要多少時間</td>
<td align="center">30</td>
<td align="center">60</td>
</tr>
<tr class="odd">
<td align="center"><strong>Development</strong></td>
<td align="center">開發</td>
<td align="center">120</td>
<td align="center">180</td>
</tr>
<tr class="even">
<td align="center">Analysis</td>
<td align="center">需求分析</td>
<td align="center">20</td>
<td align="center">30</td>
</tr>
<tr class="odd">
<td align="center">Design Spec</td>
<td align="center">生成設計文檔</td>
<td align="center">20</td>
<td align="center">30</td>
</tr>
<tr class="even">
<td align="center">Design Review</td>
<td align="center">設計複審</td>
<td align="center">20</td>
<td align="center">30</td>
</tr>
<tr class="odd">
<td align="center">Coding Standard</td>
<td align="center">代碼規範</td>
<td align="center">30</td>
<td align="center">10</td>
</tr>
<tr class="even">
<td align="center">Design</td>
<td align="center">具體設計</td>
<td align="center">30</td>
<td align="center">50</td>
</tr>
<tr class="odd">
<td align="center">Coding</td>
<td align="center">具體編碼</td>
<td align="center">30</td>
<td align="center">40</td>
</tr>
<tr class="even">
<td align="center">Code Review</td>
<td align="center">代碼複審</td>
<td align="center">30</td>
<td align="center">40</td>
</tr>
<tr class="odd">
<td align="center">Test</td>
<td align="center">測試</td>
<td align="center">50</td>
<td align="center">10</td>
</tr>
<tr class="even">
<td align="center"><strong>Reporting</strong></td>
<td align="center">報告</td>
<td align="center">70</td>
<td align="center">240</td>
</tr>
<tr class="odd">
<td align="center">Test Report</td>
<td align="center">測試報告</td>
<td align="center">30</td>
<td align="center">100</td>
</tr>
<tr class="even">
<td align="center">Size Measurement</td>
<td align="center">計算工做量</td>
<td align="center">20</td>
<td align="center">60</td>
</tr>
<tr class="odd">
<td align="center">Postmortem</td>
<td align="center">總結</td>
<td align="center">20</td>
<td align="center">80</td>
</tr>
<tr class="even">
<td align="center"> </td>
<td align="center">合計</td>
<td align="center">280</td>
<td align="center">480</td>
</tr>
</tbody>
</table>
</div>多線程
### 接口設計模塊化
- 接口描述函數
本人負責的是核心模塊,即對輸入的文件讀取後的結果進行單詞排序並存入`List`結構中準備輸出工具
- 設計思路性能
對從輸入模塊獲取的數據存入`hashMap`中,再將`Map`結構轉變成`List`結構進行單詞排序,爲輸出模塊準備接口
- 實現過程
先使用`Map<String, Integer>`結構對輸入模塊傳來的數據進行存儲.
```java
HashMap<String,Integer> words = new HashMap<>();
String str = readFile(args[0]);
{
int state = 0;
int beginIndex = -1;
for (int i = 0; i <= str.length(); ++i) {
char ch = i == str.length() ? ' ' : str.charAt(i);
boolean isWordChar = ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '-';
if (state == 0 && isWordChar && ch != '-') {
beginIndex = i;
state = 1;
} else if (state == 1 && !isWordChar) {
String word = str.substring(beginIndex, i).toLowerCase();
words.put(word, words.getOrDefault(word, 0) + 1);
state = 0;
}
}
}
```
因爲外部存儲機構使用的是`Map.Entry<String, Integer>`,不便於排序等操做,因此將map轉化爲List結構,進行排序
```java
List<Map.Entry<String, Integer>> list = new ArrayList<>();
list.addAll(words.entrySet());
list.sort((lhs, rhs) -> {
int cmp = -lhs.getValue().compareTo(rhs.getValue());
if (cmp != 0) return cmp;
else return lhs.getKey().compareTo(rhs.getKey());
});
```
### 測試設計
保證設計的測試用例應至少覆蓋函數中全部的可執行語句,同時主要空數組、最差狀況、詞頻排序、字母排序、二者混合等各類狀況設計測試用例。
![附件2截圖]()
### 單元測試
使用測試腳本進行單元測試,過程以下
![測試腳本運行截圖](http://r.photo.store.qq.com/psb?/V10RioZu2yUxV6/n1er*KNZRifOkCNiXWZBFPjPZzYkWW89C36Q0e27Yfk!/r/dA4AAAAAAAAA)
單元測試效果良好,沒有報錯
### 小組貢獻
咱們小組齊心合力, 攻克難關,積極討論,指出問題,我認爲個人小組貢獻分是0.4
## 二.擴展任務:靜態測試
### 1. 代碼規範
我選擇了代碼風格規範中:斷行與空白的{}行、分行、命名、下劃線、大小寫;
代碼設計規範中:函數、錯誤處理、new和delete、類型繼承,模塊化
個人編程習慣與以上附錄中所述規範大體相同。而在其餘如代碼審查等重要規範上有待提升。
### 2. 同組分析
我分析了本身的代碼,縮進、斷行風格整潔,命名簡單明瞭,邏輯清晰易讀,但在代碼設計規範上,模塊化不足,不易於進行團隊的coding工做,常常在git操做上發生衝突.
最後決定將團隊代碼進行整合重構,重構任務由我完成,故最終貼出組長的重構代碼
```java
public class wordcount {
public static void main(String[] args) {
long t1 = System.currentTimeMillis();
new wordcount().start(args);
long t2 = System.currentTimeMillis();
long dt = t2 - t1;
System.out.println(("Elapsed " + dt + "ms"));
}
private void start(String[] args) {
HashMap<String,Integer> words = new HashMap<>();
String str = readFile(args[0]);
{
int state = 0;
int beginIndex = -1;
for (int i = 0; i <= str.length(); ++i) {
char ch = i == str.length() ? ' ' : str.charAt(i);
boolean isWordChar = ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '-';
if (state == 0 && isWordChar && ch != '-') {
beginIndex = i;
state = 1;
} else if (state == 1 && !isWordChar) {
String word = str.substring(beginIndex, i).toLowerCase();
words.put(word, words.getOrDefault(word, 0) + 1);
state = 0;
}
}
}
List<Map.Entry<String, Integer>> list = new ArrayList<>();
list.addAll(words.entrySet());
list.sort((lhs, rhs) -> {
int cmp = -lhs.getValue().compareTo(rhs.getValue());
if (cmp != 0) return cmp;
else return lhs.getKey().compareTo(rhs.getKey());
});
try (FileWriter fout = new FileWriter("result.txt")) {
int maxsz = Math.min(list.size(), 100);
for (int i = 0 ; i < maxsz; ++ i) {
Map.Entry<String, Integer> item = list.get(i);
fout.write(item.getKey());
fout.write(' ');
fout.write(item.getValue().toString());
if (i != maxsz - 1)
fout.write('\n');
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private String readFile(String path) { // 讀文件
try {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, "UTF-8");
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
```
### 3. 靜態代碼檢查工具
使用的是IDEA的插件Ant Build中的檢錯功能
Ant Build是一個Java自動化生成工具,其檢錯功能用來檢查類或者jar文件,用來發現可能的問題。檢測完成以後會生成一份詳細的報告,藉助這份報告能夠找到潛在的bug.
檢測範圍
- 常見代碼錯誤,序列化錯誤
- 可能致使錯誤的代碼,如空指針引用
- 國際化相關問題:如錯誤的字符串轉換
- 可能受到的惡意攻擊,如訪問權限修飾符的定義等
- 多線程的正確性:如多線程編程時常見的同步,線程調度問題。
- 運行時性能問題:如由變量定義,方法調用致使的代碼低效問題
### 4. 掃描結果
![掃描結果](http://r.photo.store.qq.com/psb?/V10RioZu2yUxV6/rDxJRHigmYxocOiCk0dbyIFU79kW7pc7KV8Xg8yQeP8!/r/dN0AAAAAAAAA)
檢測結果在右上角,能夠看出僅有少許警告,根據IDEA紅線標註可發現大可能是聲明方式不是按照目前使用的java標準,沒有發生內存泄露等問題.
### 5. 小組代碼問題說明
- 因爲進行了整合重構,因此模塊化程度下降,不易維護,但程序執行效率上升
- 異常處理的不夠全面,應該覆蓋大部分的一場狀況,以便於檢查與調試
## 三. 高級任務:性能測試和優化
設計,評審,優化
選擇10kb,50kb,182kb大小的txt文件進行測試,程序處理時長以下:
輸入輸出:1ms,1ms,2ms
單詞統計:20ms,150ms,540ms
詞頻排序:6ms,8ms,10ms
單詞統計時間與文件大小呈線性相關,其餘兩個模塊佔比較小,故程序性能主要受到文件大小影響。組內共同對代碼結構和細節進行詳細審查並與其餘組程序對比,整理獲得以下觀點:
1.整合重構是正確的,不只增長了代碼的可讀性和規範性,還大幅增長了程序的性能
2.將大部分功能模塊彙集在一個類方法中,雖然會致使代碼耦合度增高,不易於團隊維護和再開發,可是減小了模塊間相互調用的開銷和隨之產生的內存開銷
## 小結
經過基本任務、擴展任務、到高級任務的完成以及中間遇到的許多困難,體現出了軟件測試對於軟件開發的重要性。在開發過程當中,使用靜態測試工具實時地檢測本身的代碼,能夠改正本身不良的編程習慣,更能防患於未然,減小出現bug的可能;對本身的模塊進行單元測試,能夠保障本身代碼的正確性,更是對其餘開發成員和整個任務的負責,使軟件開發可以一步一個腳印地穩定開展;對性能的分析與測試,能使軟件的質量進一步提升,同事能總結開發經驗,使本身設計的模塊更加高效。