《構建之法》——第四次我的做業

GitHub項目地址 這裏
合做同窗做業地址 這裏

1、PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 30 30
Estimate 估計這個任務須要多少時間 1510 1925
Development 開發 990 1325
Analysis 需求分析 (包括學習新技術) 90 100
Design Spec 生成設計文檔 60 60
Design Review 設計複審 (和同事審覈設計文檔) 20 30
Coding Standard 代碼規範 (爲目前的開發制定合適的規範) 10 20
Design 具體設計 30 25
Coding 具體編碼 900 1200
Code Review 代碼複審 60 100
Test 測試(自我測試,修改代碼,提交修改) 240 300
Reporting 報告 30 25
Test Report 測試報告 10 5
Size Measurement 計算工做量 30 20
Postmortem & Process Improvement Plan 過後總結, 並提出過程改進計劃 30 40
合計 1510 1925

2、計算模塊接口的設計與實現過程

1.項目實現的基本思路

    1)首先咱們須要讀取指定的文件,而且將文本文件中的內容提出出來,進行操做。這裏使用C#的IO流來進行文件操做。
在這裏插入圖片描述
    2)根據要求以及難易程度,咱們首先解決文本的行數以及字符數的統計。這裏使用正則表達式進行處理。
在這裏插入圖片描述
在這裏插入圖片描述
    3)對於單詞的統計咱們在完成行數和字符數統計以後,決定使用集合來處理單詞,可是發現單詞是可以處理了,可是得不到單詞出現的次數,因此咱們轉而使用字典集(Dictionary)來進行處理,字典集爲咱們提供了不少方便的功能。html

    先用ArrayList集合存儲全部單詞,包括重複的單詞,都存進去,可是是按照要求存儲單詞,也就是說必須四個英文字母開頭的單詞咱們才存儲,這裏就用到正則表達式來解決。git

    將存儲好的單詞通過遍歷放進字典集,這樣咱們就獲得了符合要求的全部單詞的一個字典集,而且也獲得了它們出現的次數,而後在對它們進行排序,就能夠獲得最終符合要求的前10個單詞了。程序員

    4)基礎功能實現後,又開始實現新添加的功能,命令行操做以及輸出指定長度的詞組。github

    因爲使用條件判斷語句不可以很好的知足命令行操做的要求,咱們通過查找資料,發現了可使用一個第三方的工具包來幫助咱們。這裏@命令行解析,經過這個工具包,咱們實現了命令行操做。正則表達式

    對於指定長度的詞組,實現方式和單詞的存儲大體相同。編程

    類圖
在這裏插入圖片描述
    總體程序流程圖以下圖所示

在這裏插入圖片描述數組

2.部分代碼以及代碼規範

  • 經過正則表達式存儲符合要求單詞緩存

    /*
       * 按要求存儲可用單詞
       */
      public ArrayList Splitwords(string text)
      {
          ArrayList al = new ArrayList();
          MatchCollection matchs = Regex.Matches(text, @"\b[a-zA-Z]{4,}\w*");
          foreach (Match match in matchs)
          {
              al.Add(match.Value);
          }
          return al;
      }
      public ArrayList Splitlenth(int lenth, string text)
      {
          string b = lenth.ToString();
          string pattern = "\\b\\w{"+b+"}\\s";
          ArrayList al = new ArrayList();
          MatchCollection matchs = Regex.Matches(text, pattern);
          foreach (Match match in matchs)
          {
              al.Add(match.Value);
          }
          return al;
      }
  • 統計每一個單詞出現的次數函數

    /*
       * 統計每一個單詞出現的次數
       */
      public Dictionary<string, int> countWords(ArrayList arrayList)
      {
          Dictionary<string, int> nary = new Dictionary<string, int>();
          foreach (string word in arrayList)
          {
              if (nary.ContainsKey(word))
              {
                  nary[word]++;
              }
              else
              {
                  nary.Add(word, 1);
              }
          }
          return nary;
      }
  • 按值排序工具

    /*
       * 按值排序 
       */
      public Dictionary<string, int> sort(Dictionary<string, int> nary)
      {
          var result = from pair in nary orderby pair.Value descending, pair.Key ascending select pair;
          Dictionary<string, int> bronary = new Dictionary<string, int>();
          foreach (KeyValuePair<string, int> pair in result)
          {
              bronary.Add(pair.Key, pair.Value);
          }
          return bronary;
      }
  • 指定輸出詞組長度

    /*
       * 指定詞組長度 
       */
      public Dictionary<string,int> msort(ArrayList al,int size)
      {
          Dictionary<string, int> nary = new Dictionary<string, int>();
          ArrayList bl = new ArrayList();
          int i = 0;
          while(i<=al.Count-size)
          {
              string str = null;
              var result = al.GetRange(i, size);
              foreach (var n in result)
              {
                  str += n.ToString()+" ";
              }
              bl.Add(str);
              i++;
          }
          foreach (string word in bl)
          {
              if (nary.ContainsKey(word))
              {
                  nary[word]++;
              }
              else
              {
                  nary.Add(word, 1);
              }
          }
          return nary;
      }
  • 代碼規範
        代碼規範是程序員的一種編程習慣,良好的編程習慣,不只能天然地產生幾乎沒有bug的代碼,並且在代碼交接時,也方便繼任者的閱讀.這是咱們的代碼規範

3.接口設計以及封裝

    1)接口設計:將三個基本功能,分爲三個類,下降耦合度,便於進行單元測試,以及代碼的修改,這樣就能夠在修改其中一個功能的時候,不影響其餘功能。可是也並無把全部的功能都分離開,統計單詞裏面就有不少個功能,類多了會增長整個程序的繁瑣程度,也會下降代碼的可讀性。

    2)功能封裝:按照要求將三個基本功能進行封裝,封裝成一個ClassLibrary,而且讓它生成dll文件,這樣程序就能夠直接引用封裝好的功能,更能減小代碼量,下降耦合度。

    在咱們的Winform程序當中,咱們引用了封裝好的統計功能,減小了重複代碼量。

    接口的封裝讓咱們的功能的實現更加的隱蔽,用戶在引用咱們的dll時,不會看見咱們的代碼。

3、代碼複審

    代碼複審過程是一個相互學習的過程,此次複審了項目的每一個模塊,對代碼的寫法進行優化,這裏只舉了一個比較嚴重的問題。

    索引超界問題

    在實現輸出指定長度的詞組功能時,發生了「偏移量和長度超出數組界限」的問題。
在這裏插入圖片描述
    在查看ArrayList相關資料時,發現了Capacity與count的區別,咱們所使用的的capacity是ArrayList能夠包含的元素個數,而count是ArrayList實際包含的元素個數,這就致使了越界問題。

    將capacity換爲count

在這裏插入圖片描述

4、模塊接口性能改進

    在完成全部要求以後,對代碼進行效能分析以下。

在這裏插入圖片描述

  • 對效能分析結果發現characSum函數佔用較多CPU,修改先後效能分析對好比下
    在這裏插入圖片描述
    在這裏插入圖片描述

  • 發現的問題以及解決措施

    內存溢出問題

    在進行小文本測試時,代碼能夠正常實現預約功能,並輸出;當咱們使用一個大小爲28MB的txt文本時,通過進2分鐘的運行,拋出內存溢出錯誤。
在這裏插入圖片描述
    在多方查找資料以及嚴密分析以後,發現了咱們代碼中存在的問題。在characSum函數中,對大量數據進行處理時,須要接二連三的實例化很是多個對象,而且它們一直會在緩存區,直到函數執行完畢纔會被釋放,這樣就會致使內存一直被擠壓,最後就會致使內存不夠用,進而拋出內存溢出的錯誤。

    在瞭解了問題觸發的機制後,在處理數據時,咱們不在使用實例化對象的方式,而是經過統計字符串的整個長度來獲得字符數的大小,而且通過實驗,達到了預期目的。

在這裏插入圖片描述

5、單元測試

  • 測試規則

    測試三個基本功能。

    對於行數以及字符數測試,咱們進行簡單的數據構造,測試數據要可以靠人工數出來。

    對於單詞統計測試,咱們一樣進行簡單的數據構造。

    1)大小寫同時出現。

    2)數據中要有file123和123file這類詞。

    3)數據中心要有小於4個字符的詞。

  • 測試截圖以下(本次測試共進行10組測試,因爲本機安裝社區版VS2017,不能查看測試代碼覆蓋率)

在這裏插入圖片描述

6、模塊異常處理

  • 命令行輸入異常

    命令行輸入不符合要求的話,會提示出錯,須要從新輸入命令行。

  • 內存溢出異常

    根據代碼效能分析的結果,設置內存溢出異常處理。

7、結對過程

這是結對過程,共同完成了代碼的編寫以及博客共同部分的編寫。

結對照片:
在這裏插入圖片描述

8、附加功能

用戶交互界面繪製

  • 導入單詞文本(-i命令行)

在這裏插入圖片描述

  • 直接輸入單詞

在這裏插入圖片描述

  • 自定義詞組長度(-m)

在這裏插入圖片描述

  • 自定義輸出高頻單詞數量(-n)

在這裏插入圖片描述

  • 導出統計結果

在這裏插入圖片描述

總結

    結對感覺:第一次進行結對編程,只能說感覺良多,同時也用親身的體驗回答了本身對第一篇我的博客裏面提出的疑問在這裏插入圖片描述
    如今個人回答是兩我的坐在一塊兒,確實會有人力資源浪費的狀況,也會存在着偷閒的藉口。再說效率問題,對於此次做業,若是一我的會比兩我的快嗎,我以爲會快,由於一我的寫的話效率會高不少,兩我的的話,有適應過程,有協商的過程,這個過程會存在什麼,偷閒的藉口。那麼結對編程的優點體如今哪裏呢?那就是互相學習,從對方身上看到優勢,見賢思齊焉,見不賢而內自省也,還有就是兩我的看一個東西,實現的方式會更多一些,思路更多一些。1+1等於多少?1+1等於1,兩我的融爲一體,步調一致,纔可以完美髮揮結對編程的目的。

隊友辛苦了。

相關文章
相關標籤/搜索