自從20世紀50年代第一臺電子計算機的問世,軟件也同時誕生。1960年代美國大學裏開始出現授予計算機專業的學位,教人們寫軟件。在計算機發展的初期,因爲軟件編寫沒有規範,它們的通用性是十分有限的。人們除了源碼和註釋外沒法獲取有關軟件的更多信息。最初的程序設計是純粹面向機器的,而機器碼的可讀性太差。對於程序規模的需求增大,面向過程的設計思想也應運而生。程序員
20世紀60年代,軟件做爲計算機的剛需,覆蓋的範圍愈來愈普遍,與此同時的是軟件的維護成本愈來愈高,由軟件錯誤而引發的信息對視、系統報廢事件屢有發生。爲此,1968年,荷蘭學者E.W.Dijkstra提出了程序設計中經常使用的GOTO語句的三大危害:破壞了程序的京東一致性,程序不易測試,限制了代碼優化,此舉引發了軟件界長達數年的論戰,並由此產生告終構化程序設計方法,同時誕生了基於這一設計方法的程序設計語言Pascal。編程
然而在20世紀70年代末,隨着計算機科學技術的進一步發展,面向過程的程序設計已經難以用戶需求的變化。因而程序員們開始尋找更加先進的軟件開發技術,也就是後來的面向對象的程序設計。學習
至此,就簡潔的歸納了程序設計的發展歷史,在接下來的幾十年程序設計還有更多的發展和優化,但爲了與課程相呼應,就簡單的到此爲止吧。測試
四次編程做業我總共被找了六個功能性bug,請由我一一道來。優化
(1)ui
第一次做業中,個人兩個bug來自於系統運行時間過長的bug,簡單來講就是200ms的一段路,個人出租車實際要走300多秒,這是由於get_path()方法太複雜的緣由。一樣的還有stop狀態停了超過1s的狀況。這個bug在以後個人處理方法是sleep(time+200-System.currenttime),這裏sleep是系統記錄的時間,並在sleep以後加上200,在輸出端則嚴格使用假時間,避免在這種地方再丟分。this
(2)spa
第二次做業中,因爲流量問題的誕生,我使用了gui類中的getFlow()方法,而且不管怎麼修改都會有回頭的狀況,因而被細心的測試者發現,分別在wait狀態閒逛和流量路兩個點給我扣了分。在以後的編寫中我使用了一個新的得到流量的方法,就避免了這樣的問題。設計
(3)code
第三次做業中個人程序由於引進了light功能,因此在map的初始化部分稍微改了一下位置,這一改就改出問題了,本來程序支持的load中map不存在會有默認地圖如今成了個bug,被糾正以後很後悔,也很自責。做爲一個程序員,每次的編程都要添加新的功能,若是不能保證以前的功能正確性,那就是自掘墳墓了。另一個bug則是被數據攻破,也修復了。
(4)
第四次做業並無被找到bug,很幸運。
規格bug中的兩個,一個是純輸出類Output的effect被揪出錯誤,這一點我也不知道算不算bug,因此申請了仲裁,另外一個是modified少寫了一個被修改的參數,測試者很細心。
總結一下本身給別人找bug的流程吧,首先是文件讀入,確保map文件存在與否都能運行,map文件格式問題,出租車初始化接單,同時執行兩條指令,信譽值不一樣取車等等。。。
1.
/** * *@REQUIRES: this.light!=null; *@MODIFIES: this.LightMap; *@EFFECTS: (\all Point e in this.light; this.LightMap[e.x][e.y]==true); */
其中 this.light 是由Point組成的隊列,這裏有點天然語言的風格,改成。 (\all i; 0<=i<this.light.size(); .......
2.
/** * *@REQUIRES: None; *@MODIFIES: None; *@EFFECTS: \result==this.LightMap[x][y]; */
前置條件應該有限制,改成0<=x<=79&&0<=y<=79
3.
/** * *@REQUIRES: None; *@MODIFIES: None; *@EFFECTS: \result==1; */
在這一系列做業當中,run()方法我都寫了好些行,致使方法規格根本無法寫。在和大佬們的交流學習中,我認識到這個是不對的,之後重構以後但願可以作的更好
4.
/** *@REQUIRES: None *@MODIFIES: this.credit; *@EFFECTS: this.credit==\old(this).credit+a; */
這是出租車的增長信譽值的方法,該方法應該有限制,即Require中 a>0
5.
/** *@REQUIRES: None *@MODIFIES: None *@EFFECTS: \result==this.taxi_list; */
該方法是得到路徑的方法,後置條件寫錯,應該爲 this.queue == getRoad()
6.
/** *@REQUIRES: None *@MODIFIES: None; *@EFFECTS: \result==distance(); */
前置條件加一個guigv.m != null
7.
/** * @REQUIRES:None; * @MODIFIES:None; * @EFFECTS:read.start(),sf.start();Output.start(); */
這是main方法的規格,說實話,慘不忍睹。。。最後決定直接刪除掉了,畢竟main方法功能多,比較難寫
8.
/** *@REQUIRES: File(path) == A File; *@MODIFIES: None *@EFFECTS: 1==1; */
前置條件很奇怪, 改成 File(path).exist()
9.
/** *@REQUIRES: None; *@MODIFIES: this.time_list; *@EFFECTS: this.time_list.contains(t); */
方法爲添加一個點,這裏前置條件和後置條件都有誤。前置條件爲this.time_list!=NULL。後置條件是this.time_list.contains(t)&&\old(this).time_list.size==this.time_list.size()-1;
10.
/** * *@REQUIRES: this!=null; *@MODIFIES: None; *@EFFECTS: \result==this.num; */
前置條件有點無謂,刪掉。
撰寫類規格和方法規格都是第二次出租車做業纔有的事情,因此實際上這是一個先寫方法再寫規格的過程,我並無感覺到太多先寫規格再寫方法的必要性。但經過寫規格,我不得不將幾個方法的功能打碎而且細化,從而寫出有用的規格。方法規格仍是有用的,在以後添加方法的過程當中都有注意這一點。但迴歸到課程自己,則是跟分數掛鉤的問題,不少人不找功能bug就期望着jsf來過日子,而jsf自己還不成熟,很容易被鑽空子扣不少,到最後申訴半天仍是被判有效,這是課程組須要解決的問題。仍是那句話,出現問題時該解決問題,而不是解決提出問題的人