標籤:des style blog http io os ar 使用 for
結對程式設計人員:
徐鈞鴻 學號 12061193
李睿琦 學號 12061187
一、結對程式設計的優點和缺點
優點:
(1)在開發層次,結對程式設計能提供更好的設計品質和代碼品質,兩人合作能有更強的解決問題的能力。
(2)對開發人員自身來說,結對工作能帶來更多的信心,高品質的產出能帶來更高的滿足感。
(3)在企業管理層次上,結對能更有效地交流,相互學習和傳遞經驗,能更好地處理人員流動。因為一個人的知識已經被其他人共用。
(4)結對程式設計的過程也是一個互相督促的過程,每個人的一舉一動都在別人的視線之內,所有的想法都要受到對方的評價。由於這種督促的壓力,使得程式員更認真地工作。結對程式設計“迫使”程式員必須頻繁地交流,而且要提高自己的技術能力以免被別人小看。
(5)結對程式設計讓兩個人所寫的代碼不斷地處於“複審”的過程。複審是不斷地審核,提高設計和編碼品質的過程,這樣能夠及時地發現問題和解決問題,避免把問題拖到後面的階段。
(6)結對程式設計中駕駛員和領航員的互換可以讓程式員輪流工作,從而避免出現過度思考而導致觀察力和判斷力下降。
缺點:
(1)結對程式設計是一個相互學習、相互磨合的漸進過程。開發人員需要時間來適應這種新的開發模式。剛開始的結對程式設計很可能不比單獨開發效率更高。
(2)如果團隊的人員要在多重專案中工作,不能充分保證足夠的結對程式設計時間,那麼成員要經常處於等待的狀態,反而影響效率。
(3)當兩個人的技術水平或經驗不均衡的時候,那麼水平較弱或缺乏經驗的一方往往會成為旁觀者,或者需要對方給予一定的講解,這無疑拖延了編程的進度。
(4)當其中一人希望獨自思考一段時間時,有可能會被認為是一種不合作的表現。
二、結對的成員的優點和缺點
姓名 |
優點 |
缺點 |
徐鈞鴻 |
代碼編寫與調試經驗相對豐富 |
編寫程式時邏輯性、層次性強 |
體力充沛,可以長時間連續進行編碼 |
在遇到非常規bug的時候會比較煩躁 |
李睿琦 |
接受能力強,能夠通過搜尋互連網快速學習不熟悉的文法內容 |
英語閱讀水平較好,能夠充分理解作業要求 |
善於學習,能夠不斷反思不斷進步 |
完美主義傾向,容易將數學思維帶入到工程實踐中去,導致很多想法無法實現 |
三、關於利用Information Hiding, interface design, loose coupling等設計方法
資訊隱藏(Information hiding)是程式設計過程中的一種隔離原則,可以防止使用者接觸到一個類的某些部分。一個程式模組可以將它的資訊隱藏起來,對外僅僅展現出一種介面。當這個模組的具體實現發生改變時,只要保證它的介面不發生變化,則就算不修改模組外的其他代碼,程式依舊可以正確執行。這種介面的設計保證了整個工程的穩定性。
所以在進行資訊隱藏時,一定要認真地研究各個模組的介面的設計,設計得越恰當,當需要修改模組的實現時會顯得更加容易。介面設計(Interface design)主要考慮的就是兩個模組之間串連和發送訊號的方式。
介面的設計要滿足的一個原則就是松耦合(loose coupling)。當一個類為了使另一個類做出一些改變而包含一個指向它的指標的時候,這兩個類是強耦合的。在這種情況下,當後者發生改變時,前者很難保持不變。而如果一個類包含的指標指向的不是類而是一個介面,當實現這個介面的類的具體實現發生改變時,由於介面沒有改變,則不需要修改引用介面的類,程式依舊可以正確運行。松耦合的介面設計使得程式設計的可拓展性大大增強。新設計的類通過實現某個介面,可以輕輕鬆鬆地替換當前的某個類,而無需修改調用這些介面的類。
四、Design by Contract, Code Contract的優點與缺點
契約式設計(Design by Contract)是一種軟體設計方法,它規定軟體設計者應該為軟體的各組成部分定義規範的、清晰的、可以實現的介面規格,這些規格的定義擴充了抽象資料類型關於前提條件、後置條件和不變式的一般形式。在這裡規格的含義與通常意義上講的商業合約的性質是一樣的,它的本質就是一種契約。
契約式編程的優勢在於我們只需要觀察模組的介面規格就可以迅速瞭解到這個模組的功能作用以及介面形式。但另一方面,若契約被違反(有意地或無意地)則程式中則一定會有bug。
在完成作業的過程中,我們詳細閱讀了程式的介面和實現相關介面的類,從介面和類的內容中分析提取出規格,在修改這些類的時候我們依靠這些規格來實現代碼,即通過規格來指導過程的再設計。
五、UML圖
六、演算法說明
其實在拿到整個程式的時候整個人夠不好了。將近1000行代碼的閱讀+理解,再在一個很不熟悉的環境(C#)下進行編碼,起始時間很辛苦的事情。不過最後看看這個過程還是很有意義的。
下面講一下代碼的實現思路
在看代碼的時候知道,整個電梯分為乘客、電梯運行和電梯調度幾個部分。而乘客和電梯運行這兩個部分已經實現的相當完整,基本不用改動,而我們需要做的就是在Schedule類的調度演算法中調用Elevator類的ReqStopAt()方法,讓電梯停在該停的地方,以實現電梯調度。而在已經寫好的Schedule類,有一個IRequest類的Queue,是裝載目前時間點之前的發出的指令。而在老師提供的簡單調度演算法中沒有使用,但是已經成功的將指令加入到隊列之中了,所以我決定實用這個請求隊列,來控制整個調度演算法。
首先,電梯是不知道電梯外的人的目標樓層與體重的,這與現實相符。
在設計演算法的時候,先假設不考慮代碼的細節(比如電梯上升一層需要五秒這種一步一步的事情,當做直接5秒一步上來)。我們設計出來的演算法是:
針對電梯外的指令x,發出樓層n
①如果電梯i在這個時刻恰好到達樓層n,並且一定要停下來,那麼這次開門的時間原本就是要浪費的。所以就講指令x分配給電梯i。
②如果不存在①的情況,但是恰好有電梯j路過樓層n,而且電梯方向與請求的方向相同,那麼就停下來將指令x帶走
③如果沒有前兩種情況,指令待機
針對電梯內指令:
既然乘客已經上了電梯,就一定要將乘客送到目標。而且在設計演算法中我們設定電梯內指令的優先順序大於電梯外指令(雖然這個條件會使代碼達到不了最優平均時間,但是相對來說比較符合現實生活。而且,代!碼!好!寫!)。這樣,電梯就會在同次同方向運行時將目標指令完成。
而在設計的過程中,由於電梯可以一次帶走多條指令,而且還會有電梯內指令,所以我在電梯裡設計了一個記錄目標樓層的布爾型數組,用來記錄此電梯需要在哪些樓層停下。這樣,在之前的演算法中,只需要將電梯需要停的樓層的序號對應的布爾型變數標記為TRUE(原來都是FALSE),在整個指令迴圈結束的時候進行判斷就可以確定該電梯最近一個的目標樓層了。
而且,在指令集合裡面,有完成的也有沒完成的指令,所以我們需要給指令添加一個標誌位,表示這個指令是否已經完成。原本我是想設計成0,1,2的標誌位,分別表示沒完成,已經或者馬上就能完成(比如電梯在8層已經向上走,9層指令就是馬上完成)和很快就能完成(用於最佳化,比如9層向上指令就可以選取8層或7層向上電梯,但是7層不是馬上來,所以置為2)。不過由於最佳化的代碼處理起來比較麻煩,加上時間緊迫,所以我在程式裡將有把指令置為2的,但是作用於0相同。
對於空閑電梯的使用方法,我認為將空閑電梯轉起來是非常不錯的。因為,轉動起來的電梯很有可能在分布相對比較平均的資料中,更容易快速搭載乘客。所以,當有電梯空閑時,我會讓電梯走向最早的未完成指令的樓層。至於中間會不會被其他乘客搭載就看天命了。
還有一個關鍵點是對於乘客上電梯的條件判斷。原始程式在兩個地方都有判斷(Passenger類的EnterElevator()方法和ElevatorStopped()方法)。但是,如果一條指令在ElevatorStopped()方法中被拒絕,在我的程式設計中這條指令不會回到調度器的指令庫裡。在這裡產生了n多個bug,最後才發現在調試的時候,很多的錯誤就是在這裡出現的,浪費的很多時間。所以,我在ElevatorStopped()方法只判斷了電梯的停靠樓層是不是乘客的請求發出樓層和乘客的is_Inside和is_Arrived這兩個狀態,而將其餘的所有判斷送到EnterElevator()方法進行統一處理。
軟體工程:結對程式設計