這個作業屬于哪個課程 | |
這個作業要求在哪裡 | j |
這個作業的目的 | 熟悉一個項目的完整開發流程,鍛煉個人程式設計能力 學習使用代碼品質分析工具和性能分析工具,學會進行單元測試 |
作業GitHub連結:https://github.com/blip00/blip00
1. PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
Planning | 計劃 | 30 | |
· Estimate | · 估計這個任務需要多少時間 | ||
Development | 開發 | 890 | 940 |
· Analysis | · 需求分析 (包括學習新技術) | 180 | |
· Design Spec | · 生成設計文檔 | 60 | 40 |
· Design Review | · 設計複審 | 20 | |
· Coding Standard | · 代碼規範 (為目前的開發制定合适的規範) | ||
· Design | · 具體設計 | ||
· Coding | · 具體編碼 | 360 | 330 |
· Code Review | · 代碼複審 | ||
· Test | · 測試(自我測試,修改代碼,送出修改) | 120 | 240 |
Reporting | 報告 | 200 | |
· Test Report | · 測試報告 | 150 | |
· Size Measurement | · 計算工作量 | ||
· Postmortem & Process Improvement Plan | · 事後總結, 并提出過程改進計劃 | ||
· 合計 |
2. 計算子產品接口的設計與實作過程
-
子產品接口設計
考慮到整個程式的運作過程并降低功能子產品之間的耦合性,我設計将程式分為三個子產品,分别是負責讀寫檔案的檔案IO操作子產品、負責計算文本相似度的核心算法子產品、負責調用前兩者的主子產品。
個人項目作業 -
算法關鍵及獨到之處
經過資料搜集(參考連結:javascript:void(0) ),發現 SimHash 局部敏感雜湊演算法相比其他常見算法對長文本的相似度檢測更加理想,故最終确定采用它作為核心算法。
個人項目作業 算法的獨到之處還在于采用了當下比較成熟的 HanLP 漢語言處理包(HanLP官網)用于文本分詞,在面對混雜在 html 标簽中的文本時,也能有效排除噪聲詞提取出詞語。除此以外,還采用了 MD5 加密算法生成數字簽名,以及通過計算 Hamming 距離作為衡量文本相似度的名額。
本程式的“權重”操作比較簡單粗暴,僅僅隻是周遊出各個詞語并按順序賦權,個人認為更進階的一步是根據詞頻(周遊統計,詞頻越高則權重越高)或者根據詞性(借助HanLP包的分析詞性功能并自己定義規則,讓名詞、動詞等實義詞賦予更高的權重)進行更合理的賦權,奈何時間不允許,隻好作罷。
以下為實作該算法的關鍵函數的流程圖。
個人項目作業
3. 計算子產品接口部分的性能
-
性能分析圖(由性能分析工具 JProfiler 自動生成)
從分析結果可以看出,浮點運算、分詞和處理字元串占用了最多資源。對于分詞操作我能做出的改變很少,隻能盡量選用最新、最先進的分詞工具。而針對浮點運算和字元串處理,我觀察到程式當中有很多需要循環的地方,是以我的改進思路是盡可能簡化或者拆分浮點運算和字元串處理,将公共運算提到循環體之外,進而減少運算次數。
個人項目作業 個人項目作業
4. 計算子產品部分單元測試展示
-
部分單元測試代碼展示
構造資料的思路主要是從正常情況和異常情況兩方面來考慮的,正常情況是指論文原文與各抄襲版論文逐一比較,異常情況主要是指傳入參數不合理的情況。
test 檔案夾除了增加了 UnitTest 單元測試類,其餘結構與 main 檔案夾中的正式代碼結構完全相同,UnitTest 類中的各個測試方法通過調用同檔案夾下 Main 包的 main() 方法進行測試。
個人項目作業 package com.similarity.main; import org.junit.Test; public class UnitTest { //擷取目前項目路徑 public static final String PATH = System.getProperty("user.dir")+"/src/test/resources/"; /** 傳入參數個數不正确 */ @Test public void test0_1(){ String[] args = { // PATH + "test/orig.txt", PATH + "test/orig_0.8_add.txt", PATH + "out/ans.txt" }; Main.main(args); } /** 傳入的檔案路徑不存在 */ @Test public void test0_2(){ String[] args = new String[3]; args[0] = PATH + "test/abc.txt"; args[1] = PATH + "test/orig_0.8_add.txt"; args[2] = PATH + "out/ans.txt"; Main.main(args); } /** test包内檔案檢測 */ @Test public void test1_1(){ String[] args = new String[3]; args[0] = PATH + "test/orig.txt"; args[1] = PATH + "test/orig_0.8_add.txt"; args[2] = PATH + "out/ans1_1.txt"; Main.main(args); } /** test2包内檔案檢測 */ @Test public void test2_1(){ String[] args = new String[3]; args[0] = PATH + "test2/orig.txt"; args[1] = PATH + "test2/orig_0.8_add.txt"; args[2] = PATH + "out/ans2_1.txt"; Main.main(args); }
-
測試覆寫率
沒有覆寫到的代碼行主要是捕獲異常的部分。
個人項目作業
5. 計算子產品部分異常處理說明
- FileUtil.readFile()該方法集中捕獲了 IOException,其中包括了 UnsupportedEncodingException、FileNotFoundException。
- FileNotFoundException 的主要出現場景:使用者輸入了不存在的檔案輸入路徑。(見測試用例 test0_2)
個人項目作業 - IOException 的主要出現場景:reader 讀取字元輸入流時出現異常情況,如流為空時。
- UnsupportedEncodingException:經過測試,字元集名“ UTF-8 ”确認無誤,一般情況下不會抛出該異常。
個人項目作業
- FileUtil.writeFile()該方法集中捕獲了 IOException,其中包括了 FileNotFoundException。
- FileNotFoundException 的主要出現場景:使用者輸入了不存在的檔案輸出路徑。(同見測試用例 test0_2,此處不再附圖)
- IOException 的主要出現場景:建立檔案方法 createNewFile() 失敗時;檔案輸出流寫入、重新整理、關閉操作出現異常時。
個人項目作業
-
SimHashUtil.hash()
該方法直接捕獲了Exception,其中包括了 java.security.NoSuchAlgorithmException 和 java.io.UnsupportedEncodingException。經過測試,算法名“ MD5 ”和字元集名“ UTF-8 ”确認無誤,一般情況下不會抛出以上異常。
個人項目作業