結對項目-最長單詞鏈總結

項目 內容
這個做業屬於哪一個課程 https://edu.cnblogs.com/campus/buaa/BUAA_SE_2019_LJ
這個做業的要求在哪裏 https://edu.cnblogs.com/campus/buaa/BUAA_SE_2019_LJ/homework/2638
我在這個課程的目標是 熟悉結對編程流程,進行一次結對開發
這個做業在哪一個具體方面幫助我實現目標 進行結對編程實踐,瞭解告終對編程的優缺點

GitHub項目地址

最長單詞鏈項目html

開始實現前的PSP表

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

接口設計方法

看教科書和其它資料中關於Information Hiding, Interface Design, Loose Coupling的章節,說明大家在結對編程中是如何利用這些方法對接口進行設計的

Information Hiding(信息隱藏)原則,是David Parnas在1972年最先提出信息隱藏的觀點。他在其論文中指出:代碼模塊應該採用定義良好的接口來封裝,這些模塊的內部結構應該是程序員的私有財產,外部是不可見的。是指程序的具體實如今外部是不可見的,只暴露出一些接口。
Interface Design,良好的接口設計須要遵循單一職責原則,開放-封閉原則,里氏替換原則等,在本次做業中,Core類只暴露出2個接口。
Loose Coupling,鬆耦合,一個模塊對另外一個模塊的調用較少。
在本次做業設計中,Core模塊僅暴露出2個接口gen_chain_word()和gen_chain_char(),用戶對於內部的具體實現是不知道的。node

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

設計包括代碼如何組織,好比會有幾個類,幾個函數,他們之間關係如何,關鍵函數是否須要畫出流程圖?說明你的算法的關鍵(沒必要列出源代碼),以及獨到之處

計算模塊包含一個Core類,其中僅有兩個可供外部調用的接口:git

int gen_chain_word(char* words[], int len, char* result[], char head, char tail, bool enable_loop);

int gen_chain_char(char* words[], int len, char* result[], char head, char tail, bool enable_loop);

Core類中的其餘函數:程序員

void newnode(string word);

    void addtomap(node newword);

    void toforest();

    void next1(vector<int> forward, int root);

    void next2(vector<int> forward, int root);

    int findmostwords(char head, char tail);

    int findlongest(char head, char tail);

    int listlength(int index);

各函數之間的調用流程圖以下:
github

算法大體思路:
根據單詞鏈的定義,一個單詞的最後一個字母等於另外一個單詞的第一個字母,故想到用有向圖來實現。算法

UML圖

閱讀有關UML的內容:https://en.wikipedia.org/wiki/Unified_Modeling_Language。 畫出UML圖顯示計算模塊部分各個實體之間的關係(畫一個圖便可)。

計算模塊接口部分的性能改進

記錄在改進計算模塊性能上所花費的時間,描述你改進的思路,並展現一張性能分析圖(由VS 2015/2017的性能分析工具自動生成),並展現你程序中消耗最大的函數

花費時間:
改進計算模塊性能所花費的時間:2小時。編程

改進思路:
第一個版本的程序中,不管面對什麼狀況,都會把有向圖中的大大小小的全部鏈路都分出來,花費了大量的時間。在不約束首位字母和只約束首字母的狀況下,只按照各個根節點來生成最長的單詞鏈。在約束尾字母的狀況下,再加入對尾字母的判斷,生成更多的鏈。app

性能分析圖以下:

ide

從性能分析圖來看,消耗最大的函數是listlength(),該函數用來計算單詞鏈的長度,具體代碼以下:函數

int Core::listlength(int index)

{

    int sum = 0;

    int i = 0;

    for (i = 0; i < forest[index].size(); i++)

    {

        sum += map[forest[index][i]].wordlen;

    }

    return sum;

}

看Design by Contract, Code Contract的內容

看Design by Contract, Code Contract的內容:
http://en.wikipedia.org/wiki/Design_by_contract
http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx
描述這些作法的優缺點, 說明你是如何把它們融入結對做業中的

Design by Contract(契約編程),Design by Contract使用了三類斷言:後繼條件(post-conditions),前提條件(pre-conditions),以及不變量(invariants)。
契約編程好處在於程序員只需按照以前制定好的契約來對本身的代碼負責,可是契約式編程很是的繁瑣,這也就是缺點。
在咱們本次的做業中,並無嚴格知足契約式編程。

計算模塊部分單元測試展現

展現出項目部分單元測試代碼,並說明測試的函數,構造測試數據的思路。並將單元測試獲得的測試覆蓋率截圖,發表在博客中。要求整體覆蓋率到90%以上,不然單元測試部分視做無效。

對Core模塊進行了多個測試,如下舉出2例

測試示例一代碼以下:

TEST_METHOD(TestMethod5)//-h a -t t -w

{

    Core* core = new Core();

    char* result[100];

    char* words[] = { "abbbb","bcccc","cdddd","deee","ct" };

    char* answer[] = { "abbbb","bcccc","ct"};

    int answerlen = 3;

    int resultlen = core->gen_chain_word(words, 5, result, 'a', 't', false);

    Assert::AreEqual(resultlen, answerlen);

    int i = 0;

    for (i = 0; i < answerlen; i++)

    {

    string stranswer = answer[i];

    string strresult = result[i];

    Assert::AreEqual(stranswer, strresult);

    }

}

這是一個約束單詞鏈首字母爲a,末尾字母爲t,單詞數量最多的測試,調用Core模塊中的gen_chain_word接口。這是一個測試程序可否正確跑對的測試。

測試示例二代碼以下:

TEST_METHOD(TestMethod8)//-h b -t t -c

{

    Core* core = new Core();

    char* result[100];

    char* words[] = { "abb","bccccccccccccccccccccc","cccccccccccccccccccccf","ctttt","cbt" };

    char* answer[] = { "bccccccccccccccccccccc","ctttt" };

    int answerlen = 2;

    int resultlen = core->gen_chain_char(words, 5, result, 'b', 't', false);

    Assert::AreEqual(resultlen, answerlen);

    int i = 0;

    for (i = 0; i < answerlen; i++)

    {

        string stranswer = answer[i];

    string strresult = result[i];

    Assert::AreEqual(stranswer, strresult);

    }

}

這個測試一樣也是約束首尾字母分別爲b,t的測試,但不一樣的是,要求輸出字母最多的單詞鏈,在所給的輸入數字中存在一個干擾項,即「bccccccccccccccccccccc」,"cbt"。來檢驗程序是否可以正確執行。

在Core模塊的單元測試中,總共構造了12個測試。獲得的測試覆蓋率以下:

計算模塊部分異常處理說明

在博客中詳細介紹每種異常的設計目標。每種異常都要選擇一個單元測試樣例發佈在博客中,並指明錯誤對應的場景。

(1)「單詞文本隱含單詞環」異常

此異常應對當輸入的單詞可以構成單詞環可是並無輸入-r參數的狀況。
單元測試樣例以下

TEST_METHOD(ErrorTest1)//包含單詞環可是沒有-r參數

        {

            Core* core = new Core();

            char* result[100];

            char* words[] = { "apple","elephant","tea","alex","box","xob","cccccff","football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc" };

            char* answer[] = { "football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc","cccccff" };

            int answerlen = 3;

            try {

                int resultlen = core->gen_chain_char(words, 9, result, '\0', 'f', false);

            }

            catch (exception e) {

                Assert::AreEqual("單詞文本隱含單詞環", e.what());

            }

        }

其中 football -- llllllllllllllc --- cccccff 能造成單詞環,可是 enable_loop 傳入 false,應該拋出「單詞文本隱含單詞環」異常。

(2)」單詞包含非法字符「異常

計算模塊接口經過char* words[] 來傳入所有單詞,若是單詞字符串中出現不是字母的狀況,就應該拋出此異常。
單元測試樣例以下

TEST_METHOD(ErrorTest2)//輸入的單詞中有非法字符,elephant 的字母l被空格代替

        {

            Core* core = new Core();

            char* result[100];

            char* words[] = { "apple","e ephant","tea","alex","box","xob","cccccff","football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc" };

            char* answer[] = { "football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc","cccccff" };

            int answerlen = 3;

            try {

                int resultlen = core->gen_chain_char(words, 9, result, '\0', 'f', false);

            }

            catch (exception e) {

                Assert::AreEqual("單詞包含非法字符", e.what());

            }

        }

輸入的單詞中的第二個單詞"e ephant"的第二個字符不是字母,應該拋出」單詞包含非法字符「異常。

(3)「首尾字母約束不合法」異常

當傳入的head 和 tail 參數既不是合法字母,也不是'\0'字符時拋出異常。
單元測試樣例以下

TEST_METHOD(ErrorTest3)//首尾字母約束不合法,用 -h *

        {

            Core* core = new Core();

            char* result[100];

            char* words[] = { "apple","elephant","tea","alex","box","xob","cccccff","football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc" };

            char* answer[] = { "football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc","cccccff" };

            int answerlen = 3;

            try {

                int resultlen = core->gen_chain_char(words, 9, result, '*', '\0', false);

            }

            catch (exception e) {

                Assert::AreEqual("首尾字母約束不合法", e.what());

            }

        }

在調用gen_chain_char()時,head參數輸入爲'*',既不是字母也不是'\0',不合法,應當拋出「首尾字母約束不合法」異常。

(4)「有單詞爲空字符串」異常

當傳入的words[]中有空字符串的時候,拋出此異常。
單元測試樣例以下

TEST_METHOD(ErrorTest5)//有單詞爲空字符串 "

        {

            Core* core = new Core();

            char* result[100];

            char* words[] = { "apple","","tea","alex","box","xob","cccccff","football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc" };

            char* answer[] = { "football","lllllllllllllllllllllllllllllllllllllllllllllllllllllllllc","cccccff" };

            int answerlen = 3;

            try {

                int resultlen = core->gen_chain_char(words, 9, result, '\0', '\0', false);

            }

            catch (exception e) {

                Assert::AreEqual("有單詞爲空字符串", e.what());

            }

        }

傳入的words[]中的第二個是 「」 , 爲空字符串,應當拋出「有單詞爲空字符串」異常。

Core模塊拋出異常單元測試狀況

界面模塊(若是沒有實現GUI,則能夠描述命令行模塊)的詳細設計過程

在博客中詳細介紹界面模塊是如何設計的,並寫一些必要的代碼說明解釋實現過程。

(1)首先經過main函數從命令行中獲取參數的個數和具體的參數

int main(int argc, char* argv[])

從第二個參數開始依次讀取argv[]中的參數,與"-h","-t","-r","-w","-c"這五個參數進行比較,進行具體處理。
若是是"-h"或者"-t"這兩個約束首尾字母的參數,則直接讀取argv[]中的下一個參數,根據規則,緊跟着的下一個參數應該是字母,若是不是則報錯。
若是是「-w"或者「-c」這兩個參數,則直接讀取argv[]中的下一個參數,根據規則,緊跟着的下一個參數應該是單詞文本的路徑,若是不是則報錯。
其中,「-w","-c"參數不能同時存在,"-h",」-t「參數能夠同時存在,同一個參數不能出現兩次,所以增長了五個布爾類型的變量進行是否重複的判斷。
以判斷」-h「參數爲例,部分代碼以下

for (i = 1; i < argc; i++)

{

    parameter = argv[i];

    if (strcmp(parameter, "-h") == 0)

    {

        if (if_head)

        {

            cout << "錯誤:-h參數重複" << endl;

        exit(0);

        }

        if_head = true;

        i++;

        parameter = argv[i];

        if (strlen(parameter) == 1 && isalpha(parameter[0]))

        {

            head_alpha = parameter[0];

        }

        else

        {

            cout << "錯誤:-h後沒有字母" << endl;

        exit(0);

        }

}

界面模塊(GUI或命令行模塊)與計算模塊的對接

詳細地描述UI模塊的設計與兩個模塊的對接,並在博客中截圖實現的功能。

在main函數讀入參數以後,直接進行命令行參數的處理,判斷參數都正確以後,根據"-w" 和 "-c" 參數來分別調用Core模塊中的兩個接口進行計算

if (if_word)

{

    resultlen = core->gen_chain_word(words, wordslen, result, head_alpha, tail_alpha, if_roun);

}

else if (if_char)

{

    resultlen = core->gen_chain_char(words, wordslen, result, head_alpha, tail_alpha, if_roun);

}

描述結對的過程

看教科書和其它參考書,網站中關於結對編程的章節

例如:
http://www.cnblogs.com/xinz/archive/2011/08/07/2130332.html
說明結對編程的優勢和缺點。
結對的每個人的優勢和缺點在哪裏 (要列出至少三個優勢和一個缺點)。

  • 結對編程的優勢和缺點
    • 優勢:
      • 兩個程序員互相幫助,獲得能力上的互補。
      • 能有效的加強代碼質量,BUG也隨之減小。
      • 遇到難題時能相互討論,快速的解決問題。
    • 缺點:
      • 每一個人的習慣都不一樣。若是結對的兩我的編程習慣上有較大差別,會產生不可預料的麻煩。
      • 當兩我的的能力有較大差別時,能力強者可能會對能力較弱者產生矛盾。
  • 我的優缺點
    • 優勢:
      • 我的完成項目的壓力會大大減小。
      • 能夠學習對方的長處。
      • 項目進展推進較快。
    • 缺點:
      • 可能剛開始時會有點難以適應這種模式。

完成程序後的PSP表

PSP 2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃
· Estimate · 估計這個任務須要多少時間 1830 1430
Development 開發
· Analysis · 需求分析 (包括學習新技術) 200 180
· Design Spec · 生成設計文檔 60 20
· Design Review · 設計複審 (和同事審覈設計文檔) 30 10
· Coding Standard · 代碼規範 (爲目前的開發制定合適的規範) 30 10
· Design · 具體設計 200 30
· Coding · 具體編碼 600 600
· Code Review · 代碼複審 200 180
· Test · 測試(自我測試,修改代碼,提交修改) 300 220
Reporting 報告
· Test Report · 測試報告 150 200
· Size Measurement · 計算工做量 30 10
· Postmortem & Process Improvement Plan · 過後總結, 並提出過程改進計劃 30 10
合計 1830 1430
相關文章
相關標籤/搜索