1. 程式人生 > 其它 >BUAA OO 第四單元總結

BUAA OO 第四單元總結

BUAA OO 第四單元總結

寫在前面

完結撒花!

本單元是OO課程的最後一個單元,部落格內容主要為UML相關內容、本單元作業架構、以往作業回顧整理以及整個OO課程的總結。總的來說,雖然是很辛苦的一門課程,但收穫也真的很多。

第四單元作業架構設計

總體架構

本單元採取迭代開發,三次作業對於類圖基本資訊的解析思路完全一樣,都是犧牲了空間來換取效能,主要設計分為以下兩點。

  • 元素儲存:在輸入時將每一個元素按照型別分開儲存,然後在後續的解析中按順序處理。分型別進行儲存的原因是,這樣做可以避免因元素輸入順序問題帶來的反覆遍歷(如UmlGeneralization物件對應的UmlClass物件輸入較晚,故一次遍歷時無法解析等);而且在後續操作中可以方便地取出所需要的不同元素。

    值得一提的是:筆者儲存UmlClassUmlInterface等表示物件的類時用了兩個容器,一個對應Name,一個對應自身id,方便重名報錯;而對於UmlAttribute等表示物件的屬性的類,筆者用了其ParentId來進行對應,方便後續的查詢操作;最後對於UmlGeneralization這種表示關係的類,筆者在解析中直接將其表示的意義新增到對應的類中,所以只是儲存,在後續查詢中沒有用到。

  • 解析操作:由於類物件所含資訊過於複雜,所以新建了類似MyClassMyInterface等類,用來表示類物件的id等自身資訊和父子類、關聯類以及實現的介面等的關係資訊,方便後續的查詢和檢查操作;還有類似MyRegion

    等內部只用來儲存轉換狀態等關聯資訊的類,用來簡化後續的關係查詢工作。

第一次作業

由於將每個物件資訊都儲存了起來,所以大部分指令按照所給要求之間進行查詢就可輕鬆解決。唯一用到演算法的地方可能就是查詢頂級父類時用到的dfsbfs演算法了,總的來說難度不大。但是需要尤其注意的地方是,儘量把每個函式的主體內容放到對應的類下,不然可能會超過500行導致CheckStyle報錯(不是我,我沒有)

第二次作業

第二次作業加入了對狀態圖和順序圖的查詢,由於很好的儲存方式所以對程式碼的要求並不大,主要難在對於UML結構的理解,即清楚不同類之間的Parent指的是誰、Reference是誰、sourcetarget

又是什麼意思。筆者前期工作的難點主要就是不知道該用哪類物件的哪個函式,以致於無從下手,後來筆者仔細閱讀了所給程式碼和第四次訓練中的例題,理解各類之間的關係後很快就寫出來了。

第三次作業

第三次作業涉及到了對於規格檢查,難度較大,因為涉及到的內容錯綜複雜,且大部分涉及到了繼承的問題,思路稍有斷層便前功盡棄。筆者的主體思路是使用遞迴和dfs演算法,依舊還是用空間來換取時間,即在進行解析的時候就對所有的類和介面進行處理,用HashMap建立一種從類和介面查詢到其所有繼承的父類和實現的介面的關係,在後面規格檢查的時候直接遍歷對應的容器內容,即可完成最難的2、3和4格式檢查,正確性樂觀(雖然時間複雜度不太樂觀)

四個單元中架構設計及OO方法理解的演進

第一單元

第一單元是表示式的求導問題,主要運用的思想是遞迴下降。由於當時對Java的語法不熟悉,加上沒有體會到面向物件思想的好處,導致每一次作業基本上都與以往毫無關係,自己新建的類也只是為了應付CheckStyle的行數要求而寫的函式集合體,老師講到的設計模式更是用都沒有用過。在經歷了重構的三週後,終於體會到了面向物件思想的好處(哭唧唧)。

第二單元

第二單元是多執行緒電梯問題,主要涉及到的是多執行緒的相關操作,相關架構設計也是圍繞著電梯排程(如電梯掃描演算法啦、自由競爭演算法啦)和同步鎖的設定。並且,由於第一單元繁忙地重構,筆者在本單元作業中重點思考了程式碼整體的架構,使用到了工廠模式等設計模式,真正按照物件來劃分程式碼中的類,使得三次的作業每一次都是在前一次作業的對應類中進行少量優化就可。

有一說一,筆者的程式碼編寫能力和架構設計思維在第二單元的作業中有了質的飛躍,此後單元的作業都是隻在第一次作業的基礎上修改,感覺確實從面向過程程式設計轉變了過來(才不是孩子重構怕了)

第三單元

第三單元是JML規格的相關問題,主要考察對於JML規格的理解和演算法效能的內容。在本單元可謂是讓筆者對面向物件思想的理解有極大的提升,並不像第二單元只是簡單地按物件的型別進行分類,通過閱讀所給程式碼,明白了用這種設計模式時可以將每一個小函式都抽離出來,單獨完成對其的實現,而且即使出現了問題,也不會影響到專案的大部分功能,還可以根據錯誤資訊快速找到對應的程式碼,可以說是極大地降低了複雜專案的工作量。

第四單元

第四單元是UML圖的解析問題,主要考察對於UML規格的理解和對儲存資訊容器的維護。繁雜的資訊量和關聯關係讓筆者再次深刻理解到了面向物件的思維方法是按照物件的型別和性質進行劃分,而不是對不同的任務進行劃分。

四個單元中測試理解與實踐的演進

第一單元和第二單元

在前兩個單元中,因為第一次側重正確性和化簡後的長度,而第二次則是側重時間長短,所以筆者只是用了簡單的手寫資料來檢測正確性,用隨機生成的無意義資料來檢測效能分,結果經常因為筆者考慮不周而導致強測和互測bug頻發。

第三單元

第三單元筆者學聰明瞭,測試資料多是根據自己對題目的理解而做的邊緣資料,其次加上大量資料來和同學進行對拍進行測試,這樣做正確率倒是有很大提升。但漸漸發現,在全寫完程式碼後進行測試,出現bug後一檢查發現往往是一層一層的bug疊加出了錯誤的結果,修改起來過於繁瑣,還容易導致新的問題。

第四單元

在最後一個單元筆者終於發現了單元測試的好處,寫一點查一點,極大地便利了debug的過程。筆者親身經歷:在最後一次作業中,筆者的R004檢查出現了問題,且在R004中用到了R002R003的相關內容,假設筆者沒有用單元測試,三個最複雜的函式一起檢查想想就頭疼的不行(筆者竊喜)

綜上,筆者最終的測試是在編寫程式碼的過程中進行的,每完成一點小內容後就依靠自己對題目的理解來製造邊緣資料進行測試,無誤後再開始接下來的工作。這樣到整體程式碼完成後,只需要用大量的隨機資料來檢測效能即可,極大縮減了測試的工作量。

三個具體改進建議

  • 建議課程組可以對每次的上機題目給出反饋,不然感覺好像每次都是去簽到,隨便寫一寫交上去,是不是對的也不知道,如果錯了應該怎麼改也不知道。
  • 希望可以增多研討課的次數,感覺在研討課上聽聽別的同學的分享對自己的程式碼編寫有很大的幫助,尤其是在毫無思路無從下手的時候。
  • 希望在第一單元中就加入不能用同一錯誤hack過多次的限制,不然的話,狼人只要找到一個bug,就能通過反覆提交獲得較多的分數,可能會導致狼人的分數過於不平衡,筆者在第一單元就被別人用同一組資料(每次只是改個數字)攻擊了好幾十次。

課程收穫

OO課程真的很辛苦,但堅持下來後收穫真的很多。

現在回想起我在一天從對Java零基礎到寫完整個Pre3和第一次作業,仍然有一股莫名的心悸...(那一天,筆者終於回想起了被OO支配的恐懼)。那一天也像是我這學期OO課程的縮影,忙碌但也收穫滿滿。雖然學會編寫Java程式、做程式碼測試、Markdown和寫部落格等一些事情非常重要,但在我心中,最重要的是學會了面向物件的思維方式。OO於我不僅僅一種編寫程式碼的方式,更像是一種思維方式:OO讓我明白了面對問題時應該如何分析,應該如何拆分,應該如何封裝,又應該如何進行測試,可以說是讓我整個人的程式碼風格和思維方式都受到了巨大的轉變。

感謝課程中的每一個人

最後的話,感謝老師們的悉心教導,感謝助教們的辛勤付出,也感謝身邊同學們的熱情無私的分享。真的很開心也很慶幸自己能夠經歷OO課程的一切。

希望咱們的OO課程可以越來越好!