項目 | 內容 |
---|---|
這個做業屬於哪一個課程? | 北航軟工 |
這個做業的要求在哪裏? | 第一次結對做業 |
我在這個課程的目標是? | 學習高效嚴謹的軟件工程開發過程,創建團隊意識 |
這個做業在哪一個具體方面幫助我實現目標 | 熟悉並瞭解軟件工程的基本知識,創建興趣 |
項目有兩個分支,master分支是命令行形式,UI分支是帶GUI的程序。c++
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 30 | 30 |
· Estimate | · 估計這個任務須要多少時間 | 30 | 30 |
Development | 開發 | 815 | 1200 |
· Analysis | · 需求分析 (包括學習新技術) | 30 | 120 |
· Design Spec | · 生成設計文檔 | 30 | 90 |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 15 | 30 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 30 | 15 |
· Design | · 具體設計 | 50 | 30 |
· Coding | · 具體編碼 | 300 | 600 |
· Code Review | · 代碼複審 | 60 | 90 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 300 | 500 |
Reporting | 報告 | 240 | 195 |
· Test Report | · 測試報告 | 120 | 120 |
· Size Measurement | · 計算工做量 | 15 | 15 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 105 | 60 |
合計 | 1085 | 1700 |
信息隱藏是指在設計和肯定模塊時,使得一個模塊內包含的特定信息(過程或數據),對於不須要這些信息的其餘模塊來講,是不可訪問的。 在咱們的設計過程當中,模塊除了被調用的兩個接口或者說成員函數之外,其餘的成員都是private
屬性的,它如何實現算法,如何存儲數據,過程當中某個變量的值如何,都與外部無關,從外部不可訪問和修改,保證編程的安全性。git
對調用者和使用者而言,不須要知道函數內部的實現,只須要掌握接口的信息。接口設計主要是做用和反作用的明確性,若是接口應該一開始就設計的比較成熟,這樣咱們修改實現接口的程序時,調用接口的程序就不用修改。咱們設計的兩個接口,約定了函數的具體做用即以不一樣的方式尋找最長單詞鏈,約定了傳入參數的具體意義,而且規定了只能修改char * result
變量做爲結果的輸出,其餘的參數應該不改變。程序員
鬆耦合和接口設計是相輔相成的。只有在規定好接口規範之後,才能實現進一步的解耦合。咱們只規定接口的做用,而不規定接口的內容。這樣不一樣組件之間能夠輕易地作到互相獨立。github
咱們在完成代碼編寫後,與其餘組同窗互換了GUI和DLL,另外一個組是週二的白世豪(16061167),宋卓洋(16061170)組。因爲生成dll的教程相似,並無出現什麼問題,對於無異常狀況能夠正常運行,以下圖所示:算法
其中Core.dll是咱們生成的dll,DLL1.dll是另一個組的dll,通過測試,加載兩個dll時GUI的行爲一致。
編程
整個程序的邏輯大體以下圖所示:設計模式
由於GUI程序是不會涉及到普通的參數正確性的(只有關於指定頭尾的字母是否正確),因此 出於解耦合的須要,咱們並無將處理參數的程序集成在Core類之中,而是獨立出來,在main函數中判斷參數的正確性。Core類中確保接受到的是正確的單詞組char *words[]
和其餘合適的參數。咱們暴露在外的只有兩個接口。安全
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);
其餘的部分以private
成員的形式,供內部使用。微信
而後每一個接口中對單詞的處理也須要分紅兩種。
\\沒有-r選項,檢測有環時直接報錯,無環時以寬度優先搜索的形式(不會陷入死循環)找到最長單詞鏈; \\有-r選項,不須要檢測是否有環,直接以深度優先搜索的形式搜索最長單詞鏈; \\僞代碼以下 if(!enable_loop) { roundtest();//有環時拋出錯誤 createMap();//創建bfs的地圖 BFS();//寬度優先搜索 getBFSResult();//處於節省時間和空間的考慮,上一步寬度優先搜索並無保存路徑,而是得出了最長的長度,而後根據長度倒推出路徑。 } else { createMap();//創建dfs的地圖 DFS();//深度優先搜素 getDFSResult();//推導最終路徑,緣由同上 }
基礎的函數大體就是這些,兩種類型chain_word
和chain_char
的各有一套。而後咱們還引入了get_tails()
就是在掃描邊的時候,排除不可能的首尾選項。大體原理就是當不成環的時候,出度爲0的點纔多是尾字母,不然不多是最長鏈。這樣咱們能夠剪枝,減小搜索時的複雜度。
使用了自動化工具生成類圖與調用關係,參考工具Github,生成的調用關係以下: 手畫類圖以下,咱們的類關係至關簡單。
總體上說,咱們採起了BFS解決沒有-r的狀況,使用DFS解決有-r的狀況。
首先是沒有-r的部分。因爲算法在設計之初就已經考慮到了一些優化,咱們重複執行同一條指令50次,取得更好的採樣效果。如圖所示,整個算法的耗時最長是在建圖與刪重邊。程序在輸入8000個單詞時運算時間在1s之內。所以沒有作進一步改進,這裏介紹一下完成的優化。
咱們主要完成了如下幾個優化:
在含有-r的部分,考慮到這是一個NP問題,並且要求的是準確解,不是近似解,咱們採用回溯法進行深度搜索。程序輸入90個單詞,摘自Wikipedia的一個隨機網頁,運行時間3分04秒。
能夠發現,程序在DFS上耗費了大量的時間。咱們對於這種模式依然作了一些優化,咱們同BFS同樣減小了可能的起點,由於起點的出度>=入度,終點的入度>=出度,也有必定效果。
此外,咱們還在總體上對程序進行了優化。考慮處處理器支持AVX指令集,咱們在編譯選項中選擇了支持生成AVX2指令的編譯選項,取得了不錯的效果,對於一組較複雜的測試用例,運行時間從2分58秒減小到2分03秒,提高接近1/3。
契約式設計要求軟件設計者爲軟件組件定義正式的,精確的而且可驗證的接口,接受一個合規的輸入,並保證合規的輸出。根據百科的定義來看,這種設計模式重在精確二字。
本次結對做業中,首要契約是做業要求中規定的接口,這個下降了溝通的一部分任務。實際編程中咱們制定的契約主要是雙方完成的函數方法部分對於類成員的行爲,以及對於異常狀況的處理。在如此契約之下,咱們才完成了從Core
類到GUI的低耦合。
單元測試總體覆蓋率91%。未覆蓋到的部分主要是拋出異常的if語句。
計算模塊暴露的接口共有兩個,分別爲
咱們對其進行了單元測試。測試的流程是測試程序加載一組測試數據,放入char * words[]中,與一些參數一塊兒傳入函數,獲得返回的result後加載標答並逐個比較,以下面的代碼片斷所示:
TEST_METHOD(TestMethod1) { Core * core = new Core(); // do sth to update words core->gen_chain_word(words1, len, result1, 0, 0, false); // get true value into realAnswer Assert::AreEqual(51, length_of_result1); for (int i = 0; i < length_of_result1; i++) { Assert::AreEqual(strcmp(result1[i], realAnswer[i]), 0); } }
對於正常數據,咱們使用隨機生成+對拍的方式檢驗。 對於異常數據,咱們構造瞭如下幾個特殊狀況:
其中對於有環的狀況,咱們還分了如下幾種狀況:
如下爲單元測試展現,因爲太長默認收起。
注意,請依次運行每一個單元測試,不要一塊兒運行,防止出錯。
TEST_METHOD(TestMethod1) { Core * core = new Core(); int len = readFile1("../WordChainUnitTesr/words1.txt"); core->gen_chain_word(words1, len, result1, 0, 0, false); int len2 = readFile1("../WordChainUnitTesr/solution1.txt"); Assert::AreEqual(51, len2); for (int i = 0; i < len2; i++) { Assert::AreEqual(strcmp(result1[i], words1[i]), 0); } }其中 words1.txt, solution1.txt能夠在Github上找到。