我的第四次做業——結對編程

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流來進行文件操做。html

    2)根據要求以及難易程度,咱們首先解決文本的行數以及字符數的統計。這裏使用正則表達式進行處理。git

    3)對於單詞的統計咱們在完成行數和字符數統計以後,決定使用集合來處理單詞,可是發現單詞是可以處理了,可是得不到單詞出現的次數,因此咱們轉而使用字典集(Dictionary)來進行處理,字典集爲咱們提供了不少方便的功能。程序員

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

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

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

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

    對於指定長度的詞組,實現方式和單詞的存儲大體相同。
    總體程序流程圖以下圖所示
緩存

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、代碼複審

    我在審查隊友代碼的時候,發現「統計單詞」這一模塊的排序實現有問題,不知足給定的要求。排序功能只實現了詞頻的排序,可是有相同詞頻的不一樣單詞沒有按照字典序排序。

最第一版本運行截圖:

    能夠看到,在第一個版本這裏,"child"和"little"的詞頻都是出現一次,可是按照字典序,"child"應該排在"little"前面輸出。
改進後版本運行截圖:

    改進後,"again"和"made"詞頻都是出現兩次,實現了字典序輸出相同詞頻的單詞排序。

4、模塊接口性能改進

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

  • 對效能分析結果發現characSum函數佔用較多CPU,修改先後效能分析對好比下

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

    內存溢出問題

    在進行小文本測試時,代碼能夠正常實現預約功能,並輸出;當咱們使用一個大小爲28MB的txt文本時,通過進2分鐘的運行,拋出內存溢出錯誤。

    在多方查找資料以及嚴密分析以後,發現了咱們代碼中存在的問題。在characSum函數中,對大量數據進行處理時,須要接二連三的實例化很是多個對象,而且它們一直會在緩存區,直到函數執行完畢纔會被釋放,這樣就會致使內存一直被擠壓,最後就會致使內存不夠用,進而拋出內存溢出的錯誤。

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

5、單元測試

  • 測試規則

    測試三個基本功能。

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

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

    1)大小寫同時出現。

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

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

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

6、模塊異常處理

  • 命令行輸入異常

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

  • 內存溢出異常

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

7、結對過程

    在結對以後,選定了兩方都有空的時間進行討論,根據PSP表格預估時間,討論出項目需求,代碼設計,根據各自水平進行分工,完成代碼先進性自省,而後交換代碼進行復審,最後彙總生成.exe文件進行單元測試並不斷提交進度,最後撰寫博客。

    這是咱們在一塊兒進行代碼測試分析

8、附加功能

用戶交互界面繪製

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

  • 直接輸入單詞

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

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

  • 導出統計結果

總結

一、 兩人在合做過程當中彼此交流,能更敏銳地發現代碼中出現的漏洞,及時改正錯誤,提升工做效率;

二、 兩人合做相較於多人團隊合做而言,更能促進彼此的交流,由於兩人合做過程當中,有什麼問題能夠直接提出,並在兩人商討以後獲得滿意的結論,若參與者數量太多,反而很差調配;

三、 雖然咱們兩我的的水平有必定差距,可是咱們彼此信任,共同努力,最終仍是實現了一個比較理想的算法,這是咱們共同的勞動結果;

四、能和同伴一塊兒交流,一同解決問題是一件挺好的事,兩我的一塊兒寫代碼思路也會更開闊。我以爲若是當一我的沒有思路了,或者實現一個比較複雜的邏輯部分代碼的時候,能夠採用結對編程的方式。

相關文章
相關標籤/搜索