項目 | 內容 |
---|---|
此做業屬於北航軟件工程課程 | 班級博客連接 |
做業要求見右方連接 | 做業要求 |
我在這門課程的目標是 | 培養專業的軟件開發能力 |
這個做業在哪一個具體方面幫助我實現目標 | 對結對編程有了必定的實踐經驗,對合做開放項目的大體步驟有了必定了解和實踐; |
本次做業GitHub項目地址 | https://github.com/NanonaN/WordChain |
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | ||
· Estimate | · 估計這個任務須要多少時間 | 30 | |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 120 | |
· Design Spec | · 生成設計文檔 | 30 | |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 30 | |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 30 | |
· Design | · 具體設計 | 100 | |
· Coding | · 具體編碼 | 420 | |
· Code Review | · 代碼複審 | 90 | |
· Test | · 測試(自我測試,修改代碼,提交修改) | 240 | |
Reporting | 報告 | ||
· Test Report | · 測試報告 | 50 | |
· Size Measurement | · 計算工做量 | 30 | |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 90 | |
合計 | 1260 |
Information Hiding即信息隱藏,很容易理解,就是把一個類中重要銘感的信息隱藏在自身內部,類以外的代碼沒法獲取並更改這些信息,以此來提升程序的安全性;git
在這次的項目實現中,由於程序實現難度並不大(若不是對性能有極致的要求),因此計算模塊僅一個類——Core,該類中有八個屬性(下一部分中有介紹),分別存儲計算單詞鏈相應的信息,這些信息對於不一樣的功能需求是不一樣的,可是如果直接生成get,set方法甚至將屬性改成public屬性,這將大大下降程序的安全性,也是破壞了Information Hiding的原則;github
因此對於每次調用程序的信息,咱們採用了先存儲在構造Core實例的方法,好比GUI界面下,用戶能夠實時改變功能選項,這時程序所作的事只是存儲選項的改變,當用戶點擊「開始計算」時,才構造core實例(傳入以前存儲的信息)進行計算 ;算法
Interface Design和Loose Coupling在我看來是結合一體的吧,接口設計實際上就是實現鬆耦合(我的觀點);編程
以前看過一個博客中的例子簡明的指出了二者的好處:設計模式
在作一個團隊項目時,有人可能負責領域模型m(model),有人負責前臺v(view),有人負責業務邏輯c(controller),在這種mvc的設計模式模式驅動下,咱們首先想到的就是:定義一套公共的接口,方便各個模塊之間的通信。面向接口的程序設計思想是一種有效的手段。好比一個作業務邏輯的team,他們並不清楚業務數據的curd實現,但他們只要經過面向於數據組提供的一整套接口進行編程便可,同時,數據組的開發能夠並行進行,這樣,不須要等待一個模塊的完成就能夠預先「使用"這個模塊,極大的提升了團隊的效率。安全
在該程序實現中,程序的主體就分爲三個部分,第一是處理輸入,第二是進行計算,第三是輸出(這裏也包括GUI的調用);mvc
三個部分之間的鏈接簡單明瞭,相互之間沒有什麼衝突,故不須要等一個模塊完成在進行下一個模塊,而是並行編碼;app
程序計算模塊就一個類:core類;ide
其中,charMode和wordMode分別表明(-c和-w選項),head和tail表明限定的首尾單詞,input表明輸入的字符串,inputIsFile表明文本輸入仍是文件輸入(GUI中須要此選項);模塊化
main函數構造core類實例,構造函數中經過調用ParseCommandLineArguments()函數將命令函輸出的字符串分割並提取出其中的信息;
而後交由GenerateChain()函數進行計算,ReadContentFromFile()爲讀取字符串,DivideWord()函數爲將字符串分割爲單詞,FindLongestChain()函數爲計算最長單詞鏈。
這一部分花費了咱們大約三個小時吧,該問題能夠等價爲尋找有向有環圖中最長路徑的問題,是一個NPC問題,因此對於容許單詞環的狀況下,算法複雜度沒法在數量級層面進行優化,故對一些細節進行優化,好比訪問尋找單詞的效率,無-r選項時及時退出;核心算法上,沒有作根本上的優化,採起BFS算法遍歷找出最長的單詞鏈。
VS性能分析工具分析結果如圖:
按合同設計相似於以前OO課中編寫JSF的規格化設計思路,個人理解實際上就是上文中接口設計的細化和量化,即對於整個程序編碼,細化到每個函數,都進行量化的規範設計,如連接中的前置條件、後置條件等規範;
這樣作的好處是:
缺點是:
核心思路就是儘量覆蓋全部的狀況,即包括正確和錯誤的輸入樣例,正確的輸入樣例分別測試該程序支持的各類功能,錯誤的輸入樣例則測試程序在遇到不合法輸入時可否正確報錯和退出;
private readonly List<string> _wordList1 = new List<string>() { "Element", "Heaven", "Table", "Teach", "Talk" }; private readonly List<string> _wordChain1WithR = new List<string>() { "table", "element", "teach", "heaven" }; private readonly List<string> _wordList2 = new List<string>() { "Algebra", "Apple", "Zoo", "Elephant", "Under", "Fox", "Dog", "Moon", "Leaf", "Trick", "Pseudopseudohypoparathyroidism" }; private readonly List<string> _wordChain2 = new List<string>() { "algebra", "apple", "elephant", "trick" }; private readonly List<string> _wordChain2WithC = new List<string>() { "pseudopseudohypoparathyroidism", "moon" }; private readonly List<string> _wordChain2WithHe = new List<string>() { "elephant", "trick" }; private readonly List<string> _wordChain2WithTt = new List<string>() { "algebra", "apple", "elephant" };
public unsafe void gen_chain_wordTest() { TestGenChain(_wordList1, _wordChain1WithR, enableLoop: true); TestGenChain(_wordList2, _wordChain2); TestGenChain(_wordList2, _wordChain2WithHe, head: 'e'); TestGenChain(_wordList2, _wordChain2WithTt, tail: 't'); } [TestMethod()] public void gen_chain_charTest() { TestGenChain(_wordList2, _wordChain2WithC, mode: 1); } private unsafe void TestGenChain(List<string> wordList, List<string> expectedChain, int mode = 0, char head = '\0', char tail = '\0', bool enableLoop = false) { var resultArray = CreateStringArray(wordList.Count, 100); var wordListArray = ConvertToArray(wordList); var len = 0; switch (mode) { case 0: len = Core.gen_chain_word(wordListArray, wordListArray.Length, resultArray, head, tail, enableLoop); break; case 1: len = Core.gen_chain_char(wordListArray, wordListArray.Length, resultArray, head, tail, enableLoop); break; default: Assert.Fail(); break; } var result = ConvertToList(resultArray, len); CollectionAssert.AreEqual(expectedChain, result); } [TestMethod()] public void ParseCommandLineArgumentsTest() { TestWrongArgs("-w"); TestWrongArgs("-c"); TestWrongArgs("-h"); TestWrongArgs("-t"); TestWrongArgs("-"); TestWrongArgs("-h 1"); TestWrongArgs("-t 233"); TestCorrectArgs("-w input.txt"); TestCorrectArgs("-c input.txt"); TestCorrectArgs("-w input.txt -h a"); TestCorrectArgs("-w input.txt -t b"); TestWrongArgs("abcdefg"); TestWrongArgs("-w input.txt -h 9"); TestWrongArgs("-w input.txt -t 0"); TestWrongArgs("-c input.txt -h 7 -t 1"); TestWrongArgs("-w input.txt -h 123"); TestWrongArgs("-c input.txt -t 321"); TestWrongArgs("-h a"); TestWrongArgs("-w input.txt -w input.txt"); TestWrongArgs("-w input.txt -c input.txt"); TestWrongArgs("-c input.txt -c input.txt"); TestWrongArgs("-c input.txt -w input.txt"); TestWrongArgs("-w input.txt -h a -h c"); TestWrongArgs("-w input.txt -t a -t c"); TestWrongArgs("-w input.txt -r -r"); TestCorrectArgs("-w input.txt -r"); }
程序中的異常分爲讀入參數時發生的異常和運行發現單詞環(沒有-r選項)
對應的程序的中測試樣例爲:
public void ParseCommandLineArgumentsTest() { TestWrongArgs("-w"); TestWrongArgs("-c"); TestWrongArgs("-h"); TestWrongArgs("-t"); TestWrongArgs("-"); TestWrongArgs("-h 1"); TestWrongArgs("-t 233"); TestWrongArgs("abcdefg"); TestWrongArgs("-w input.txt -h 9"); TestWrongArgs("-w input.txt -t 0"); TestWrongArgs("-c input.txt -h 7 -t 1"); TestWrongArgs("-w input.txt -h 123"); TestWrongArgs("-c input.txt -t 321"); TestWrongArgs("-h a"); TestWrongArgs("-w input.txt -w input.txt"); TestWrongArgs("-w input.txt -c input.txt"); TestWrongArgs("-c input.txt -c input.txt"); TestWrongArgs("-c input.txt -w input.txt"); TestWrongArgs("-w input.txt -h a -h c"); TestWrongArgs("-w input.txt -t a -t c"); TestWrongArgs("-w input.txt -r -r"); }
注:計算默認爲計算單詞最多和直接輸入單詞文本,可改變選項爲文件輸入,文件輸入分爲輸入文件路徑或者點擊「選擇單詞文件」按鈕選擇指定文件;
結果默認爲輸出到當前界面,如:
亦可選擇導出到指定文件,導出完成會有彈窗提示:
若發生異常,會彈窗提示錯誤信息,如:
下面簡單介紹實現過程:
在顯示的GUI界面中,每個選項框都是一個窗體控件,由checkBox控件實現可選可不選的功能選項(好比容許單詞環選項),由radioButton實現多選一的必選項(這裏須要用pannel容器框起來);由Button實現按鈕點擊(如開始計算按鈕);由textBox實現文本輸入;由label實現顯示功能;經過MessageBox.show函數實現彈窗提示;
編寫各控件的事件代碼,除「開始計算單詞鏈」按鈕之外,其他事件主要功能爲將用戶選擇的信息(作相應處理)存儲起來,當用戶點擊「開始計算單詞鏈」按鈕後,程序將GUI中的信息及以前存儲的信息傳入構造函數Core()以此構造一個示例,而後調用core.GenerateChain()方法計算出最長單詞鏈,最後進行輸出。
個人缺點:
在系統的工程開發中存在部分短板,好比寫單元測試不夠熟練;
編碼規範還有待提升。
至於優勢…仍是由隊友評價比較客觀吧hh;
隊友的優勢:
恩…有點多…受益良多,一一道來:
編碼能力比較強,代碼規範且效率很高;
工程能力很強,各方面能力全面;
學習能力強且工做效率高;
至於缺點…沒發現…(是實際感受)。
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | ||
· Estimate | · 估計這個任務須要多少時間 | 30 | 30 |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 120 | 100 |
· Design Spec | · 生成設計文檔 | 30 | 30 |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 30 | 30 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 30 | 30 |
· Design | · 具體設計 | 100 | 60 |
· Coding | · 具體編碼 | 420 | 480 |
· Code Review | · 代碼複審 | 90 | 120 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 240 | 180 |
Reporting | 報告 | ||
· Test Report | · 測試報告 | 50 | 40 |
· Size Measurement | · 計算工做量 | 30 | 30 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 90 | 60 |
合計 | 1260 | 1250 |