Github
地址html
見文末git
看教科書和其它資料中關於Information Hiding, Interface Design, Loose Coupling的章節,說明大家在結對編程中是如何利用這些方法對接口進行設計的github
在本次做業中,是須要將
gui
與計算模塊耦合在一塊兒。爲了下降耦合,咱們實現了標準接口,gui
直接將信息傳給計算模塊的函數,而後獲取結果。爲了與更好的與gui
庫耦合,咱們在接口上儘量使用基本類型。計算模塊部分,將信息處理與邏輯處理分開設計,將信息處理與邏輯處理自身的信息隱藏起來,只須要互相調用接口就能夠實現完整的邏輯。算法
extern "C" CoreAPI int build_map(char* words[], char* text); \\對單詞進行拆分 extern "C" CoreAPI int gen_chain_word(char* words[], int len, char* result[], char head, char tail, bool enable_loop);\\計算最長單詞單詞鏈 extern "C" CoreAPI int gen_chain_char(char* words[], int len, char* result[], char head, char tail, bool enable_loop);\\計算最長字母單詞鏈
計算模塊接口的設計與實現過程。 設計包括代碼如何組織,好比會有幾個類,幾個函數,他們之間關係如何,關鍵函數是否須要畫出流程圖?說明你的算法的關鍵(沒必要列出源代碼),以及獨到之處編程
有3個類:
Core
,FindChain
,Init
。18個函數。Init
處理原始數據,命令行參數處理、單詞切分等任務。FindChain
對Init
的數據進行深加工,抽象出邊和圖,進行相關的計算。Core
將兩個類結合在一塊兒,進行必要的調度。判斷是否有環是經過是否存在拓撲序進行判斷的,無環的最長路是用一個簡單的spfa
,在處理有環的最長路是,爲了提升效率使用鄰接鏈表,並使用了一個剪枝:若是當前最長路已經將一個點的全部出邊都覆蓋到,那麼這個點的最長路必定不會更優。函數
閱讀有關UML的內容:https://en.wikipedia.org/wiki/Unified_Modeling_Language。畫出UML圖顯示計算模塊部分各個實體之間的關係(畫一個圖便可)。工具
在計算部分進行性能改進時,咱們基本上就在對有環的狀況進行優化,咱們爲了提升效率使用鄰接鏈表,使用了一個剪枝:若是當前最長路已經將一個點的全部出邊都覆蓋到,那麼這個點的最長路必定不會更優。oop
咱們性能分析後發現主要性能仍是消耗在dfs的遞歸上,所以主要優化目標仍是對dfs進行剪枝。性能
看Design by Contract, Code Contract的內容:
http://en.wikipedia.org/wiki/Design_by_contract
http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx
描述這些作法的優缺點, 說明你是如何把它們融入結對做業中的單元測試
這些作法會增長代碼編寫的工做量可是卻能夠保證代碼的正確性,在代碼的開發階段加入
assert
可以提前發現bug
,測試階段須要assert
來進行正確性的測試
計算模塊部分單元測試展現。 展現出項目部分單元測試代碼,並說明測試的函數,構造測試數據的思路。並將單元測試獲得的測試覆蓋率截圖,發表在博客中。要求整體覆蓋率到90%以上,不然單元測試部分視做無效。
TEST_METHOD(TestMethod8) { char* words[10] = { "abb","bc", "cd", "de", "drrrrr","rrrrr" }; char* result[105]; FindChain findchain; findchain.BuildMap(words, 6, 1, 0, 0); int len = findchain.GetWordChain_NoRing(result); Assert::AreEqual(len, 5); for (int i = 0; i < 3; i++) { int slen = strlen(result[i]); Assert::IsTrue(result[i][slen - 1] == result[i + 1][0]); } }
以上爲當自環在這個鏈的最後時的測試,用來檢查自環是否被計算上。
TEST_METHOD(TestMethod7) { char* words[10] = { "aa","cc","bb", "dd", "ee", "rr" }; char* result[105]; FindChain findchain; findchain.BuildMap(words, 6, 1, 'c', 0); int len = findchain.GetWordChain_NoRing(result); Assert::AreEqual(len, 1); }
以上爲對每一個字母都是自環的狀況進行考慮,雖然沒有造成鏈可是一個單詞也要輸出鏈。
TEST_METHOD(TestMethod1) { char* words[10] = { "ab","bc","ca", "cd", "de", "dee" }; char* result[105]; FindChain findchain; findchain.BuildMap(words, 6, 1, 0, 0); int len = findchain.GetWordChain_Ring(result); Assert::AreEqual(len, 5); for (int i = 0; i < 4; i++) { int slen = strlen(result[i]); Assert::IsTrue(result[i][slen - 1] == result[i + 1][0]); } }
計算模塊部分異常處理說明。 在博客中詳細介紹每種異常的設計目標。每種異常都要選擇一個單元測試樣例發佈在博客中,並指明錯誤對應的場景。
- 不能識別的參數
TEST_METHOD(InitError5) { Core core; char* argv[10] = { "program", "w" }; try { Init* init = core.init_word(2, argv); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("Incorrect command line parameters!", msg); } }對應可能忘記加上
-
等等場景。測試時保證必定會拋出異常,不然會fail
,而且異常信息正確。
- 同時輸入了
-w
和-c
指令TEST_METHOD(InitError2) { Core core; char* argv[10] = { "program", "-w","a.txt","-c","a.txt" }; try { Init* init = core.init_word(5, argv); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("Command line arguments include both -w and -c", msg); } }測試時同時輸入w和c參數,保證必定會拋出異常,且異常信息正確。
- 沒有輸入
-w
和-c
指令TEST_METHOD(InitError3) { Core core; char* argv[10] = { "program" }; try { Init* init = core.init_word(1, argv); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("Command line parameters do not contain - w or -c", msg); } }測試時沒有輸入w和c參數,保證必定會拋出異常,且異常信息正確。
-h
或-t
指令後參數格式錯誤TEST_METHOD(InitError4) { Core core; char* argv[10] = { "program", "-w", "a.txt", "-h", "0" }; try { Init* init = core.init_word(5, argv); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("The parameter should be a letter", msg); } }測試時
-h
後面的格式錯誤,保證必定會拋出異常,且異常信息正確。
- 存在環路且沒有
-r
指令TEST_METHOD(LoopError1) { HINSTANCE CoreDLL = LoadLibrary("Core.dll"); p_gen_chain_word gen_chain_word = (p_gen_chain_word)GetProcAddress(CoreDLL, "gen_chain_word"); Core core; char* words[10] = { "ab","bc","cd", "da", "abb", "bcc" }; char* result[105]; try { int len = gen_chain_word(words, 6, result, 0, 0, 0); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("There is a ring in the word list", msg); } }測試時不輸入
-r
,且單詞中存在環路,保證必定會拋出異常,且異常信息正確。
- 缺失參數
TEST_METHOD(InitError1) { Core core; char* argv[10] = { "program", "-w" }; try { Init* init = core.init_word(2, argv); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("Missing parameters", msg); } }測試時
-w
後未接文件路徑,致使缺失參數,保證必定會拋出異常,且異常信息正確。
- 找不到文件
TEST_METHOD(BuildError1) { Core core; char text[1000]; char* argv[10] = { "program","-w","../WordlistProject/zzy.txt" }; Init* init = core.init_word(3, argv); try { core.read_file(init, text); Assert::Fail(); } catch (const char* msg) { Assert::AreEqual("File not found", msg); } }構造一個不存在的文件,保證必定會拋出異常,且異常信息正確。
界面模塊(若是沒有實現GUI,則能夠描述命令行模塊)的詳細設計過程。 在博客中詳細介紹界面模塊是如何設計的,並寫一些必要的代碼說明解釋實現過程。
界面模塊的第一步是選擇一個溫馨的
gui
庫,咱們去github
上選擇star
數最高的imgui
。簡單的練習後能夠上手了,可是發現缺乏文件操做的函數,因而去issues
找到了須要的函數。ShowMainMenuBar(core, init); OpenButtonMonitor(core, init, inputText); SaveButtonMonitor(core, init, outputText); ImGui::Columns(3, "mixed"); ImGui::Text("Input"); ImGuiInputTextFlags inputFlags = ImGuiInputTextFlags_AllowTabInput; ImGui::InputTextMultiline("##Input", inputText, IM_ARRAYSIZE(inputText), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 32), inputFlags); //ImGui::Separator(); ImGui::NextColumn(); ImGui::Text("Output"); ImGuiInputTextFlags outputFlags = ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_ReadOnly; ImGui::InputTextMultiline("##output", outputText, IM_ARRAYSIZE(outputText), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 32), outputFlags); ImGui::NextColumn(); FlagCheckBox(core, init, inputText, outputText);主界面將劃分爲3列,分別爲輸入、輸出和相關功能的按鈕
static ImGuiFs::Dialog openDlg; const char* myPath = openDlg.chooseFileDialog(OpenButtonPressed); OpenButtonPressed = false; if (strlen(openDlg.getChosenPath()) > 0) { ImGui::Text("Open file: \"%s\"", openDlg.getChosenPath()); } else { ImGui::Text("Open file: \"%s\"", ""); } if (strlen(myPath) > 0) { FILE* fp = fopen(myPath, "r"); int i = 0; while ((text[i] = fgetc(fp)) != EOF && i < MAX_BYTES - 1) i++; text[i] = '\0'; fclose(fp); }在菜單按鈕上實現文件打開與導出,根據打開的文件路徑,將文件內容讀入到輸入框中。導出功能相似,將輸出框中的內容處處到所選的文件。
界面模塊(GUI或命令行模塊)與計算模塊的對接。 詳細地描述UI模塊的設計與兩個模塊的對接,並在博客中截圖實現的功能。
對接時
gui
只須要將輸入框數據傳給計算模塊建圖而且進行最長路的計算。並將計算的內容導出到輸出框中。
- 計算功能
- 文件功能
咱們與王冰小組進行了gui的耦合。
王冰學號:16061155 謝靜芬學號:16061093
描述結對的過程,提供非擺拍的兩人在討論的結對照片。
咱們坐到一個電腦前,坐在一個凳子上擠在一塊兒,一個看一個寫。
看教科書和其它參考書,網站中關於結對編程的章節,例如:
http://www.cnblogs.com/xinz/archive/2011/08/07/2130332.html
說明結對編程的優勢和缺點。
結對的每個人的優勢和缺點在哪裏 (要列出至少三個優勢和一個缺點)。
在作題的時候就習慣先討論後編碼。結對編程能夠更好地將討論過程融入到編碼中。並且能夠提早發現對方的
bug
,減小測試的壓力。缺點:結對編程會同時佔用兩我的的時間,可是隻有一臺電腦,當一我的編碼時,另外一我的會很着急。並且在宿舍中結對編程很是擁擠,致使結對編程的環境不夠溫馨。
優勢 缺點 餘宸狄 (1)思惟嚴謹,謀定後動(2)熟悉多種算法,更好地提出思路(3)喜歡使用基本類型,迴歸c本質 不夠細心,是個瞎子 張朝陽 (1)對搜索算法提出了不少改進,思惟活躍。(2)代碼能力強。(3) 熟悉STL庫 喜歡摸魚
在你實現完程序以後,在附錄提供的PSP表格記錄下你在程序的各個模塊上實際花費的時間。
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 20 | |
· Estimate | · 估計這個任務須要多少時間 | 0 | 5 |
Development | 開發 | 1500 | |
· Analysis | · 需求分析 (包括學習新技術) | 120 | 300 |
· Design Spec | · 生成設計文檔 | 60 | 0 |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 30 | 0 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 120 | 30 |
· Design | · 具體設計 | 120 | 180 |
· Coding | · 具體編碼 | 120 | 600 |
· Code Review | · 代碼複審 | 90 | 40 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 60 | 450 |
Reporting | 報告 | 180 | |
· Test Report | · 測試報告 | 60 | 30 |
· Size Measurement | · 計算工做量 | 20 | 10 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 20 | 140 |
合計 | 820 | 1700 |