作業小結3 規格化設計的發展歷史 最早的程式設計都是採用機器語言來編寫的,直接使用二進位碼來表示機器能夠識別和執行的指令和數據。簡單來說,就是直接編寫0和1的序列來代表程式語言。例如:使用0000代表載入(LOAD),0001代表存儲(STORE)等。 面向機器的語言通常情況下被認為是一種“低級語言 ...
作業小結3
規格化設計的發展歷史
最早的程式設計都是採用機器語言來編寫的,直接使用二進位碼來表示機器能夠識別和執行的指令和數據。簡單來說,就是直接編寫0和1的序列來代表程式語言。例如:使用0000代表載入(LOAD),0001代表存儲(STORE)等。
面向機器的語言通常情況下被認為是一種“低級語言”,為瞭解決面向機器的語言存在的問題,電腦科學的前輩們又創建了面向過程的語言。面向過程的語言被認為是一種“高級語言”,相比面向機器的語言來說,面向過程的語言已經不再關註機器本身的操作指令、存儲等方面,而是關註如何一步一步的解決具體的問題,即:解決問題的過程,這應該也是面向過程說法的來由。
第一次軟體危機:結構化程式設計。根本原因就是一些面向過程語言中的goto語句導致的麵條式代碼,極大的限制了程式的規模。結構化程式設計(英語:Structuredprogramming),一種編程範型。它採用子程式(函數就是一種子程式)、代碼區塊、for迴圈以及while迴圈等結構,來替換傳統的goto。希望藉此來改善電腦程式的明晰性、質量以及開發時間,並且避免寫出麵條式代碼。
為瞭解決問題,在1968、1969年連續召開兩次著名的NATO會議,會議正式創造了“軟體危機”一詞,並提出了針對性的解決方法“軟體工程”。雖然“軟體工程”提出之後也曾被視為軟體領域的銀彈,但後來事實證明,軟體工程同樣無法解決軟體危機。
結構化程式設計的主要特點是拋棄goto語句,採取“自頂向下、逐步細化、模塊化”的指導思想。結構化程式設計本質上還是一種面向過程的設計思想,但通過“自頂向下、逐步細化、模塊化”的方法,將軟體的複雜度控制在一定範圍內,從而從整體上降低了軟體開發的複雜度。結構化程式方法成為了1970年代軟體開發的潮流。
規格化設計被重視的原因
所有的程式開發手冊都包含了各種規則。一些習慣自由程式人員可能對這些規則很不適應,但是在多個開發人員共同協作的情況下,這些規則是必須的。這不僅僅是為了開發效率來考慮,也是為了後期維護考慮。
代碼規格化設計正是為了培養規範設計和編程,養成良好的習慣,增強軟體產品的穩定,健壯,可靠性;同時也提高了軟體的可讀性,可以讓程式員儘快而徹底地理解新的代碼,使產品可維護性提高。
- 此外,還有如下好處:
- 減少維護成本。一個軟體的生命周期中,80%的花費在於維護,另一方面,幾乎沒有任何一個軟體,在其整個生命周期中,均由最初的開發人員來維護,規範的編碼減少人員變動帶來的維護成本。
- 改善軟體的可讀性。可以讓程式員儘快而徹底地理解新的代碼。在一個團隊中,代碼也容易在程式員之間共用。
- 維護部門交付產品的規範形象。
規格bug的表格分析
規格bug類別 | 所對應方法的代碼行數 | 產生原因 |
---|---|---|
第九次作業公測->JSF檢查->不符合JSF規範 | 4 | 測試者說REQUIRES必須是一個布爾表達式不能是自然語言 |
第九次作業公測->JSF檢查->Modifies不完整 | 5 | 改了this但沒寫 |
第九次作業公測->JSF檢查->Requires不完整 | 8 | 測試者說有參數必須寫requires |
第九次作業公測->JSF檢查->Requires邏輯錯誤 | 4 | 測試者說有參數必須寫requires |
第十次作業公測->規格檢查->方法規格檢查->JSF不符合規範 | 7 | 測試者說我沒使用布爾表達式 |
第十一次作業公測->規格檢查->抽象對象有效性實現檢查:Overview是否明確抽象對象 | - | 測試者說Overview過於簡陋,僅是名字的翻譯,未體現出數據抽象思想 |
第十一次作業公測->規格檢查->抽象對象有效性實現檢查:Overview是否明確抽象對象 | - | 測試者說您的Taxi類、Settings類、Light類等等,Overview都相當的“抽象”啊,僅僅將名字翻譯過來,或者是名詞,或者是動詞短語,並沒有體現其真正含義所在。 |
第十一次作業公測->規格檢查->方法規格檢查->JSF不符合規範 | 1 | 測試者說規範的表示是:\result==this.point0; 而你是* @EFFECTS: return this.point0;。 |
前置條件與後置條件案例
前置條件
* @REQUIRES: other != null
改進:* @REQUIRES: other instanceof TrackableTaxi && other != null
說明:requires不夠完整,對於某些方法應該更明確表明它的類型。* @REQUIRES: this != null
改進:* @REQUIRES: None
說明:一般情況下this是不會等於null的,這大概是一句廢話。* @REQUIRES: None
改進:* @REQUIRES: this.property > 0
說明:該方法要求其它方法執行過後才能執行,而其它方法執行過後的當且僅當的標誌是某個屬性大於零。於是就這樣子改了。* @REQUIRES: this.property != null
改進:* @REQUIRES: None
說明:類中有一個repOK的方法,要求property不是Null。而property屬性在構造方法中已經保證了不是Null。因此這是廢話。* @REQUIRES: x >=0 && x <= 79
改進:* @REQUIRES: x >= 0 && x <= MAP_MAX_LENGTH
說明:之前定義過常量MAP_MAX_LENGTH,這裡就不適合寫79了,不然以後要改地圖尺寸時得改很多東西。其它所有常量同理。
後置條件
* @EFFECTS: return this.property
改進:* @EFFECTS: \result == this.property
說明:常見的語法問題。感謝測試者幫我找到這個問題。* @EFFECTS: \result = this.property
改進:* @EFFECTS: \result == this.property
說明:常見的語法問題。感謝我舍友的測試者幫我舍友找到這個問題。* @EFFECTS: this != null
改進:* @EFFECTS: this.property == value
說明:構造方法不能寫的過於簡單。* @EFFECTS: 初始化該實例
改進:* @EFFECTS: this.property == value
說明:構造方法不能寫的過於簡單,即使使用自然語言。* @EFFECTS: linkedList.contains(request); 改進:
* @EFFECTS: linkedList.contains(request) && linkedList.size = \old(linkedList).size + 1`
說明:沒有列出所有變化。
功能bug與規格bug的聚集關係
方法名 | 功能bug數 | 規格bug數 |
---|---|---|
Line | 0 | 1 |
Taxi | 0 | 2 |
initTaxis | 0 | 1 |
checkSameUser | 0 | 1 |
getPoint0 | 0 | 1 |
看的出來,功能bug數跟規格bug數是相關的。如果一個方法連規格都寫錯了,那麼它的功能是很難正確的。不論是構造方法還是普通的方法,都是這樣子的。當然前提是寫代碼的人是根據規格來寫的代碼。
如果寫規格的人和寫代碼的人不是同一個人,這個結論應該就很顯然了。
我們常常做測試時,就對方法單獨的測試,只要輸入滿足規格的requires,檢查輸出是否滿足effects就好了。如果測試通過,且modifies正確,那麼就較大概率沒bug(因為並未進行完備的測試)。這樣單獨的方法對了,才是對的。
設計規格和撰寫規格的思路和體會
先說體會吧!首先感謝課程組讓我們訓練設計和撰寫規格。
老師課上總是強調設計規格的重要性,雖然大家寫得很累,但是我覺得老師說得很對。設計規格確實是最重要的。尤其是在團隊協作中。
所有的程式開發手冊都包含了各種規則。我們可能對這些規則很不適應,但是在多個開發人員共同協作的情況下,這些規則是必須的。這不僅僅是為了開發效率來考慮,也是為了後期維護考慮。所以我覺得老師說的很對。
關於設計規格和撰寫規格。我的思路如下:
首先,我們要根據設計需求,進行架構,做數據抽象,總結出幾個類,弄清楚各個類的定義,弄清楚各個類之間如何交互,弄清楚各個類如何相互合作最終把這些設計需求來實現。
其次,根據數據抽象,弄清楚各個類需要哪些屬性。
再然後,根據設計需求,弄清楚類需要哪些方法,而這些方法需要被哪個或哪些類調用。又或者它僅僅只是一個內部方法。弄清楚這個方法要實現什麼樣的功能。這裡我想起來老師上課常常講的話,就是寫JSF時千萬別去想演算法。所以,這一步,先不考慮演算法怎麼實現,只考慮這個方法的功能。另外這一步要保證代碼的邏輯是正確的。
再之後,開始寫設計規格。根據上一布自己所想的,寫好設計規格。註意require effect的正確性。
再之後,開始寫代碼,就實現那些方法。這裡要註意演算法的正確性,註意,如果有modify,可能還需要修改一下設計規格。
最後,測試程式,檢查代碼功能是否正確。如果功能錯誤,可能是在設計規格時邏輯錯誤,也可能是代碼在具體實現時演算法錯誤或者編碼錯誤。要從這兩個方向來找bug,最終得到正確的程式。
最後謝謝老師們謝謝助教們謝謝同學們!