OO第一次部落格--前三次作業分析:
第一次作業:
第一次作業的要求是實作有一定魯棒性的多項式加減法。對于大多數剛開始接觸JAVA語言和OO思想的同學來說,這次的難點主要是:JAVA文法、面向對象思想、正規表達式的使用和程式的魯棒性。相比以為的語言,我無法了解“面向對象”這個詞的含義。在膜拜已經對java有所了解并上過面向對象先導課的大佬們的代碼後,我才稍微對“面向對象”的寫法有所了解。雖然聽起來很不現實,但在了解了一個語言的基礎文法後,參觀和學習大佬們的代碼似乎是快速上手的好方法(這似乎與課程要求相違背但對于學習确實有所幫助)。在聽學姐講解後,有聽說正規表達式是一個便利的工具,便利用之。對于程式的正确性以及如何保證不crash,除了自己多加try來注意,還需要大量的測試驗證了。畢竟自己測得不夠全面,就隻能期望别人也不幫你測。。。
在設計上,我采用了一個Poly類型的數組Polylist來存放各個合法多項式,在首項前加“+”,再利用找操作符号來分割各項進行操作。這是一種常見的操作,效率算不得很高,但好在不至于逾時而且很便于了解。
以下是其類圖及其度量分析:
從度量分析中看出的是Match方法被标紅;該方法是本次作業中我的主方法。。。
(附:McCabe Cyclomatic Complexity(圈複雜度)用來衡量一個子產品的複雜程度,統計一個函數有多少個分支(if,while,for等),沒有的話複雜度為一,每增加一個分支複雜度加一。圈複雜度的作者McCabe認為,圈複雜度在3~7為比較好的結構化方法,圈複雜度大說明程式代碼可能品質低且難于測試和維護。Nested Block Depth(塊嵌套深度)則為嵌套深度。這兩塊出現超标,往往說明程式設計有缺陷,或部分代碼嵌套深,難以判斷邏輯,或直接寫成了面向過程的思想。)
作為一個菜雞的第一個java程式(除了HelloWorld),我代碼中的問題很多:
首先是對java語言的不熟練導緻處處像C,也直接導緻了一個函數到結尾(就像main)。另外因為初學面向對象程式設計,導緻代碼中對于對象的重視不夠,更多則是在面向過程。。。
而自己被爆出的bug中也展現了自己對代碼的了解不深刻:被人爆數組(公測同樣在爆但僥幸逃過一劫),對方刻意構造大型錯誤輸入,瞄準我在錯誤輸入處理時想當然的随意開了一個小數組來儲存結果,被爆兩組資料。這也讓我在之後的兩次作業中debug和找bug時對于代碼中的數字更加重視。
第二次作業:
傻瓜電梯的設計與驗證。傻瓜電梯的難點,應是對電梯的設計上,即如何實作電梯、分别給五個或者更多的類什麼功能、各個類之間如何串聯等問題上。我采用了dipatcher類對操作進行處理;而電梯類elevator和floor分别存儲電梯在該指令執行完成前後的時間、樓層、運動狀态,并給排程器計算指令完成時間。指令demand負責讀入,在work函數進行輸入篩選處理後将可執行的傳進指令隊列,再從頭開始逐條傳入dipatcher取出處理。
這次的作業相比第一次作業,面向對象的思想展現的就明顯多了;指導書中對于多個類的提示也在把我們從面向過程的誤區往出拉。
從類圖中能看出demand類幾乎是沒有起到任何作用,因為隻是在work函數對輸入進行暫存,進行篩選之後直接就傳給queue了。。。甚至沒有都可以。。。這帶來的問題也十分明顯:queue類過于龐大了,在第三次作業中更會有所展現,這又導緻了我的資料結構複雜備援,原本demand中應該實作的分類隻能在queue中狂開數組來分類儲存。。。在排程時也麻煩的一逼。。。
好在作為第二次作業,相比上一次的青澀少年我也是有了第一次經驗了。。。在資料處理上稍微嚴謹了一些,不幸地是,這次我被爆出的問題比上次還要多:
- 對分支結構的處理太過傻逼。在處理錯誤輸入時,因為經驗不足,面對諸多錯誤情況自亂了陣腳。。。一大堆的if,break,和flag自增在公測的幾個小資料面前就開始瞎幾把輸出(對錯誤判斷後的處理太混亂),好在為第三次提供了寶貴的參考。
- 采用了奇怪的計數和循環:do-while和一個從0開始的count,判斷條件裡的是[count-1]元素。。。有一個事先考慮大條導緻了隻有一個RUN的時候數組越界(count-1<0)。。。
- 對指導書的了解不深刻:指導書中對于“第一條指令時間不為0按crash處理”的描述,被我簡單的了解成了直接報錯結束程序。。。結果挂了兩組公測資料。。。也是參考。。。
度量分析中紅色的是新加入的度量類,幾乎是代碼中的核心處理部分,說明了我對于指令的處理還是應當有所精簡。
第三次作業:
學長口中的第一個“不好寫”:ALS電梯。
這次電梯的最大改動為允許捎帶,這就出現了主指令和最多兩條捎帶指令(即若存在捎帶,能找到一條最先捎帶的指令,以及可能會找到一條和它僅指令辨別符不同的指令一起被捎帶)。是以排在後面的指令有可能被先完成,不能單純隻從從隊列頭開始向後一次周遊。将所有指令按樓層進行儲存。再使用了一個指令隊列,規定頭指令為主指令,再每變動一層後判斷同質,向後找最優捎帶指令,執行後将其标記,不再執行。當所有比主指令先執行完的捎帶指令全部完成,執行主指令并從隊列删除,将新的主指令置頂。循環下去至隊列為空。然而在完成代碼的時候,還是被炸出了一些奇怪的bug(主指令為同質指令時沒有将其篩除,說到底還是判斷邏輯不夠完備)。此外,要求使用對于我們菜鳥來說新學習的繼承、接口、重寫。。。(然而慚愧的是自己代碼中幾乎沒有對這些的展現。。。接口無用,繼承基本全是重寫。。。)
作為單線程第二次電梯作業,她已經向現實中的電梯有所靠攏。。。同時對于我們第一次的電梯要求更高了(得先調好第一次才能避免第二次出現上一次的bug)。遺憾的是還是出現了問題(上面已提到)。。。
度量中展現的還是老生常談的問題:depatcher的龐大。而導緻這些的原因之一是對資料結構的組建太混亂(第二次中的queue在本次中不減反增)。。。
好在debug方面總算把第二次的問題解決了,可是測試資料太弱還是沒能發現一些特殊的問題,比如提到的主指令為同質。。。以上這些原因這也導緻了我後來de了好久也沒de完。。。
至于心得體會,從一個菜雞的角度來看有以下幾點吧。。。
- 基本文法得學明白。。。Java作為新的工具,欲善其事不利其器是絕對不行的。。。不然就會出現像我一樣申明數組卻沒有沒有挨個執行個體化的de了好久bug的傻叉行為。。。
- 打出提前量;周二晚上寫肯定寫不完,除非你通宵。。。
- 多向大佬們學習;這很重要,菜雞閉門一個月造的車也不一定跑的過大佬三天寫的sports car。。。畢竟一個月的學習和大佬幾年的積累還是沒得比,面對人家的豐富經驗,我們還是要多學習。。。(遺憾的是很多大佬并不願意分享代碼)是以我們要多接受大佬的點撥和教育,這是我們盡快走向熟練甚至成熟的不二之法。