第一次個人編程作業


倉庫地址

PSP

PSP2.1 Personal Software
Process Stages
預估耗時(min) 實際耗時(min)
Planning 計划 54 54
Estimate 估計這個任務需要多少時間 54 54
Development 開發 792 880
Analysis 需求分析
(包括學習新技術)
90 90
Design Spec 生成設計文檔 54 40
Design Review 設計復審 54 20
Coding Standard 代碼規范
(為開發制定合適的規范)
27 10
Design 具體設計 108 100
Coding 具體編碼 189 360
Code Review 代碼復審 60 60
Test 測試
(自我測試,修改,提交修改)
189 200
Reporting 報告 54 54
Test Report 測試報告 18 18
Size Measurement 計算工作量 9 9
Postmortem & Process
Improvement Plan
事后總結
並提出過程改進計划
27 27
合計 900 988

解題思路

**step 1. **利用正則表達式提取姓名和手機號碼, 並將其從原字符串中去除

**step 2. ** (Level 1) 利用中國省市區街道四級聯動json數據逐級匹配地址,對於缺字的情況,取前兩個字當作關鍵詞匹配。對於缺級的情況,遍歷上一級所有子級的子級匹配。雖然總數據量較大,但是實際上每次分級之后可以少檢索很多數據。

**step 3. ** (Level 2) 利用正則表達式分割剩余的詳細地址

**step 4. ** (Level 3) 調用高德Api

**step 5. ** 使用Moshi庫將結果對象轉換成Json輸出

設計實現過程

數據類

類名 說明 屬性
Data 數據 provinces
Result 結果 name, phone, address
Province 省級 name, cities
City 地級 name, areas
Area 縣級 name, streets
Street 街道 name

工具類

類名 作用
FileUtil 讀取和寫入文件
JsonUtil 轉換對象和Json字符串
Trimmer 處理輸入樣例

主要函數

函數名 說明
void Data.build() 用json數據生成所需對象
void trimName() 切去姓名
void trimPhone() 切去手機號
void trimProvince() 切去省級
void trimCity(List<City>) 切去地級
void trimArea(List<Area>) 切去縣級
void trimStreet(List<Street>) 切去街道
void trimDetail() 切分詳細地址

單元測試 (with JUnit 5)

設計

這個題輸入比較穩定,只是有可能缺失某幾級地址,可以考慮為每個缺失設計一個caseN()測試函數,手動輸入樣例和答案,例如:

@Test
public void case15() {
    String testCase = "2!甘鞋,甘肅蘭州西固區西柳溝街道18629411660什么花園.";
       String name = "甘鞋";
          String phone = "18629411660";
          String[] address = new String[]{
                  "甘肅省",
                  "蘭州市",
                  "西固區",
                  "西柳溝街道",
                  "",
                  "",
                  "什么花園"
          };
          resultTest(testCase, name, phone, address);
      }

用resultTest函數驗證正確性:

private void resultTest(String testCase, String expectedName, String expectedPhone, String[] expectedAddress) {
    Result result = new Trimmer(testCase).trim().toResult();
    String message = testCase + System.lineSeparator() + result.toString();
    Assert.assertEquals(message, expectedName, result.getName());
    Assert.assertEquals(message, expectedPhone, result.getPhone());
    Assert.assertArrayEquals(message, expectedAddress, result.getAddress().toArray());
}

如果結果與預期有誤,則調用assertEquals輸出錯誤信息,方便調試:

測試結果

一共設計了15個不同情況的case,經過瘋狂調試,終於全部通過。

完整單元測試代碼

測試覆蓋率

分割地址用的主要是Trimmer類,除了getter和setter都覆蓋到了。其余沒覆蓋到的也主要是getter和setter。

異常處理

異常主要發生在Trimmer類的方法里,主要是由於輸入錯誤導致的,這樣的異常不好正確處理,這里簡單地將trim方法包裹在try代碼塊里,執行時判斷輸入是否符合要求,如果不符合,中斷執行,並直接返回一個空的結果,避免了程序直接退出。

 @Test
    public void exceptionCase1() {
        String testCase = "甘鞋,甘肅蘭州西固區西柳溝街道18629411660什么花園.";
        resultTest(testCase,"","",new String[]{});
    }

代碼分析 (with Codacy)

根據提示消除了了所有Issue.

性能測試 (with JProfiler)

程序中最占內存的是解析json數據構造出來的String對象,最耗時的操作是解析Json數據。為了提高效率,可以考慮把Json解析器換成FastJson。

收獲

這一次還是收獲滿滿的,學會了很多東西:

  • 用JUnit做單元測試;
  • 用JProfiler做性能分析;
  • 用Codacy做代碼分析;
  • 用Gradle構建項目,並把所需依賴打包到Jar文件里;

其中最有用的要數單元測試了,可以很方便的測試出Bug來,並修改完代碼之后可以反復運行,效率很高,相比以前手動測試,節省了不少時間。代碼分析工具可以檢測出代碼中不合理的地方,並給出修改提示,按照提示修改代碼,可以提高代碼的可讀性和健壯性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM