這個做業屬於以下課程:軟件工程
這個做業的要求位於以下連接:結對編程
我在這個課程的目標是:鍛鍊複雜軟件開發能力,取得大於85分的成績。
這個做業在以下方面幫助我實現目標:快速上手C++語言;將結對編程、單元測試、添加註釋、拋出異常等付諸實踐。git
一、在文章開頭給出GitHub項目地址。
項目地址程序員
二、在開始實現程序以前,在下述PSP表格記錄下你估計將在程序的各個模塊的開發上耗費的時間。
見附錄部分。github
三、看教科書和其它資料中關於Information Hiding, Interface Design, Loose Coupling的章節,說明大家在結對編程中是如何利用這些方法對接口進行設計的算法
In computer science, information hiding is the principle of segregation of the design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed.編程
——引用自維基百科"Information Hiding"
我對Information Hiding比較有感觸的是處理來自文件的輸入的子程序。在第一遍實現時,咱們將文件讀入和解析的功能所有寫在一個readFile函數中,鼓搗了半天也沒調通。以後,我重寫了這一部分代碼:readFile函數只負責不停地以行爲單位讀取文件中的內容,而具體解析的工做交由另外一個process_line函數完成。重寫後的代碼長度更短,並且調試花費的時間更少。在這個例子中,process_line向readFile函數隱藏瞭解析用戶輸入的信息。並且,一旦用戶輸入的格式發生變化,通常只須要修改process_line函數便可;代碼的可維護性較好。app
沒有找到太多資料。核心模塊的函數接口在做業要求的基礎上略做修改(例如使用了vector和string),其他函數基本遵循以下原則:名稱易於理解、參數儘量少。less
In computing and systems design a loosely coupled system is one in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services.
Components in a loosely coupled system can be replaced with alternative implementations that provide the same services. Components in a loosely coupled system are less constrained to the same platform, language, operating system, or build environment.ide
——引用自維基百科"Loose Coupling"
咱們沒有完成選作做業「鬆耦合」,對鬆耦合的支持不夠好:咱們將FileInput類的一個對象做爲了wordHandler的成員變量,爲以後寫單元測試代碼帶來了必定的麻煩。更好的作法是讓wordHandler僅擁有一個存有文件中全部單詞的容器(例如vector
四、計算模塊接口的設計與實現過程。
在設計之初,爲了下降代碼單元間的耦合度,咱們將整個程序拆分爲3個類:FileInput讀取用戶文件,wordHandler尋找單詞鏈,output將單詞鏈以文件形式輸出。這樣的設計使得各個代碼單元之間儘可能分離,避免糾纏不清,形成修改困難。性能
在算法上,咱們採用蠻力算法進行求解。儘管在單詞數量增多後難以取得使人滿意的性能,可是可以返回最優解,而不是像某些算法只能返回近似解。
五、畫出UML圖顯示計算模塊部分各個實體之間的關係。
六、計算模塊接口部分的性能改進。
因爲採用蠻力算法,且時間有限,咱們未對計算模塊進行性能改進。一個可能的方向是將全部單詞排序,而後採用索引查找方法,以提升時間效率。
性能分析圖以下:
七、看Design by Contract, Code Contract的內容;描述這些作法的優缺點, 說明你是如何把它們融入結對做業中的
契約式設計在同一個軟件項目的開發人員之間造成契約:在前置條件下,程序員必須保證本身編寫的方法維持了不變式內容,且知足後置條件。其優勢是程序員能夠認爲前置條件爲真而無需進行大量檢查。其缺點是不遵照契約的程序員會爲整個項目帶來巨大破壞,並且程序員須要多花一部分時間撰寫契約規格。
本次做業中,咱們未能使用契約式設計,形成了一些不良後果。一個典型的錯誤是某個變量究竟表明容器中元素的個數仍是下標的最大值(兩者差1)。這一點兩人事先沒有約定好,最終形成了BUG的發生。
八、計算模塊部分單元測試展現。
TEST_METHOD(TestMethod1) { FileInput fin; fin.readFile("D:\\word_chain\\01.txt"); wordHandler wh(fin); char *words[20]; vector<string> result; wh.gen_chain_word(words, 0, result, 0, 0, false); Assert::IsTrue(result.at(0) == "apple"); Assert::IsTrue(result.at(1) == "elephant"); Assert::IsTrue(result.at(2) == "toad"); } TEST_METHOD(TestMethod2) { FileInput fin; fin.readFile("D:\\word_chain\\02.txt"); wordHandler wh(fin); char *words[20]; vector<string> result; wh.gen_chain_char(words, 0, result, 0, 0, false); Assert::IsTrue(result.at(0) == "pseudonym"); Assert::IsTrue(result.at(1) == "moon"); }
01.txt
apple
elephant
toad
方法1測試了gen_chain_word方法的正確性,狀況設置得比較簡單:在輸入上沒有設置干擾單詞,且給出的單詞順序就是鏈的順序。
02.txt
leaf, fox
pseudonym, moon
moon
方法2測試了gen_chain_char方法的正確性,狀況較爲複雜:設置了重複的單詞做爲干擾項。
咱們還編寫了其它單元測試代碼,限於篇幅沒法一一展現,請前往GitHub項目地址查看相應代碼。
九、計算模塊部分異常處理說明。
十、界面模塊的詳細設計過程。
按指導書中的命令行參數,設計瞭解釋程序。如出現'-r',則將對應的bool型變量置爲true,'-h'則按順序讀入下一個命令行參數,將其複製給char型變量,'-t'同上。'-w'先按順序讀入下一命令行參數做爲文件路徑,調用gen_chain_word()接口;'-c'同上,不一樣在於調用gen_chain_char()接口。讀到文件路徑後完成對命令行的解析。
while (true) { con = false; switch (ptr[1]) { case 'r': recur = true; con = true; break; case 'h': ptr++; head = *ptr; con = true; break; case 't': ptr++; tail = *ptr; con = true; break; case 'w': fun = 'w'; break; case 'c': fun = 'c'; break; default: break; } if (con) { i++; ptr = argv[i]; continue; } else { break; } } try { fin.readFile(argv[i + 1]); } catch (FINException& fine) { fine.what(); return 0; } if (fun == 'w') { wordHandler whword(fin); whword.gen_chain_word(_words, _len, result, head, tail, recur); } else if (fun == 'c') { wordHandler whchar(fin); whchar.gen_chain_char(_words, _len, result, head, tail, recur); } else { cout << "Invalid command!" << endl; }
十一、界面模塊與計算模塊的對接。
咱們在main函數中實例化了FileInput, wordHandler兩個類的對象,wordHandler的構造方法傳入FileInput類的對象。main函數接受了命令行參數後,將識別的文件路徑傳入FileInput的相關方法,從而實現對接。
十二、描述結對的過程,提供非擺拍的兩人在討論的結對照片。
我和楊亦鑫是隔壁班的同窗,之前在打籃球時有過接觸。課程開始後,咱們分別進入了不一樣的團隊。所以,咱們符合結對編程的條件,通過簡短的溝通後正式結對。
咱們結對編程的形式主要是先由我約一個兩人都方便的時間,而後來到新主樓2層,找一個走廊裏的座位,開始結對編程。
因爲是初次接觸結對編程形式,咱們在實際操做中出現了必定的問題。我在時間控制上不太敏感,常常是連續工做了一個多小時而忘記了交換角色。領航員有時候注意力開了小差,沒有進行隨時複審。不過兩人合做的氛圍較爲輕鬆愉快,沒有發生劇烈衝突。
總的來講,此次結對編程並未提升咱們的工做效率。可是,因爲是兩我的一塊複審,咱們最終仍是發現了很多BUG,並且對於每一個概念上的錯誤都能在過後牢記。此次體驗對個人開發能力有所促進,但也提出了更高的要求。
1三、說明結對編程的優勢和缺點。結對的每個人的優勢和缺點在哪裏 (要列出至少三個優勢和一個缺點)。
優勢1:寫代碼和查API的工做能夠交由兩人並行完成,既提升了效率也造成了知識的共享。
優勢2:定時休息能夠避免一我的長時間敲代碼(這種狀況經常致使BUG數增長)
優勢3:錯誤被發現時兩人都留下了深入的印象。
缺點1:做爲課程的一部分時,結對編程須要在兩個學生都有空的時候進行,並且缺少好的環境(大運村沒有公共休息室),所以效果打了折扣。
1四、在你實現完程序以後,在附錄提供的PSP表格記錄下你在程序的各個模塊上實際花費的時間。
見附錄。
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | ||
· Estimate | 估計這個任務須要多少時間 | 15 | 4 |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 180 | 120 |
· Design Spec | · 生成設計文檔 | 240 | 0 |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 60 | 0 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 120 | 0 |
· Design | · 具體設計 | 480 | 20 |
· Coding | · 具體編碼 | 1440 | 480 |
· Code Review | · 代碼複審 | 480 | 180 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 960 | 120 |
Reporting | 報告 | ||
· Test Report | · 測試報告 | 480 | 30 |
· Size Measurement | · 計算工做量 | 45 | 5 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 60 | 5 |
合計 | 4560 | 964 |