第一次
架構設計
第一次作業要求實現UML類圖解析器。
我才用自頂向下依次解析的方法,首先將類圖中涉及的所有元素分成三層:
第一層 | 第二層 | 第三層 |
---|---|---|
Class, Interface, AssociationEnd | Association, Attribute, Operation, Generalization, InterfaceRealization, | Parameter |
根據需要,實現了MyClass, MyInterface, MyAssociationEnd,MyOperation四個類,按照所屬關系(例如屬性屬於類/接口, 關系屬於兩個類/接口)將其他元素作為屬性保存在這四個類中,並在主解析器中保存以上四種的HashMap(id為key,對應實例為value),用於找出需要的元素調用。
在解析元素時,進行三次遍歷,依次解析第一、二、三層。
對於主解析器中的函數調用,多下降到新實現的類中完成。
對於涉及搜索的函數(例如尋找所有關聯的類、所有實現的接口等),采用轉入hashmap作為函數參數,遞歸調用進行修改的方法,最終返回時參數hashmap就已經加入了所有符合要求的元素。同時,為了提高效率,設置緩存機制。
例如:
public void getInterfaceList(HashMap<String, String> names) { if (hasInterfaceList) { // 如果已經調用過該方法,則直接返回結果 names.putAll(interfaceList); return; } for (MyInterface a : interfaces.values()) { // 遍歷所有該類直接實現的接口 interfaceList.put(a.getId(), a.getName()); // 更新實現的接口hashmap a.getFatherInterfaces(interfaceList); // 調用該接口的該方法,尋找間接接口 } if (father != null) { // 如果有父類,則調用父類的該方法 father.getInterfaceList(interfaceList); } hasInterfaceList = true; names.putAll(interfaceList); // 更新傳入的names }
UML類圖
第二次
架構設計
第二次作業要求實現時序圖和狀態圖的解析,架構方法與第一次相同,更新層次表格如下
時序圖:(僅列出需要使用的)
第一層 | 第二層 | 第三層 |
---|---|---|
Interaction | Lifeline | Message |
狀態圖:(僅列出需要使用的)
第一層 | 第二層 | 第三層 |
---|---|---|
StateMachine, Region(由於本次作業中一對一,所以簡化) | State | Transition |
UML類圖
第三次
架構設計
第三次作業涉及模型的有效性檢查,基本架構與第二次完全相同。
在進行有效性檢查時,檢查方法與之前的查詢方法類似,下降到對應的類中遞歸調用。
對於R005,R006,采用在初始化架構時進行預處理的方法更為方便。
UML類圖
和第二次架構相同。
設計架構及對OO的理解演進
我認為第一單元對於面向對象思想的體現是最明顯的,我的設計重點主要在如何實現某個對象。將表達式從上到下進行解析,提取出表達式類、因子類、各種項類。通過成員變量等方法建立其中的包含關系和函數調用關系,每個類只需要完成自己的任務。綜合來看,第一單元是我心中最OO的一個單元,也是闡釋OO思想的很典型的一個樣例。
第二單元延續OO的設計思想,但增加了重要的功能性,也就是這一單元的特點——多線程,這使得我的設計重點由如何實現某個對象,變為對象之間的如何交互。線程安全等問題非常結合實際又難度,並且調度算法的開放性也激發了我對於不同調度策略的嘗試和比較。通過本單元的學習,我明白了對於OO而言,設計好一個對象的行為是遠遠不夠的,如何讓他們系統地、高效地、安全地交互才是將架構真正付諸實踐的關鍵。
第三單元涉及JML,讓我體會到了在實際工程實現中根據規格要求實現具體方法的過程,我的設計重點放在了如何高效實現方法要求上。針對特定的JML規格,方法的具體實現方法有許多種,但總有效果更好的一種。我認為在閱讀JML時,最重要的是要深層次理解其設計目標的內涵(如最短路、連通分量數量等),而不應該僅停留在JML字面意思,否則將難以將需求抽象出來,可能造成方法復雜度過高等后果。
第四單元學習了UML的相關知識,UML模型模型化設計將對象、對象之間的關系全部抽象出來,組建成模型。我認為設計的重點在於層次化抽象成模型。對於層次化,需要將UML圖中的各種元素進行層次划分,形成從抽象到具體的邏輯關系。對於抽象,需要深入理解UML圖的本質,並采用某種數據結構將元素進行統籌整理。
測試理解與實踐
我在每個單元中的測試流程都基本相同:
-
手動構造基本功能測試
-
JUnit單元測試(主要在第三單元采用)
-
對拍(主要在第一、二、三單元采用)
-
自動生成輸入數據(第一、二、三單元)
-
自動判斷答案正確性
-
對輸出答案進行special judge(第一、二單元)
-
生成正確答案,與輸出進行比對
-
多份代碼一起跑,比對輸出之間的差異(第三單元)
-
-
-
手動構造邊緣數據
綜合來看,對於不同測試方法,我給出以下結論:
-
找bug效率最高的是邊緣數據測試
-
清掃詭異bug最有效的是對拍(有的bug只有在某些條件同時滿足時被觸發,不對拍難以覆蓋)
-
輸寫最有條理的是JUnit(針對單個方法測試,需要考慮的條件少)
課程收獲
-
對OO思想從無到有的建立
通過本課程的學習,我理解了面向對象和面向過程的具體含義(之前沒有面向對象做對比,我連面向過程的意思都不是很理解),並掌握了OO的基本實現思路和應用場景,能夠使用面向對象思想對於某問題進行分析和給出解決方案。
-
對java語言從0開始的學習
掌握了一門編程語言,通過書寫具有一定代碼量的作業熟練了java的語法和應用,學會了容器等java元素的使用,提高了我的代碼能力。
-
對拍測試機制的學習
在去年計組首次接觸對拍,但當時沒有自己動手實現多少。本學期OO過程中學會自己實現對拍測試的各個部分,並學會了使用bat實現自動化。
-
一些其他的技能
打包工程、markdown使用、git使用、rubyonrails了解……
改進建議
-
強測結果不同分數用不同顏色表示可能更顯眼(研討課有同學提的,我覺得很有道理
-
希望實驗課有反饋結果,給個答案就行
-
第三單元東西確實有點少(感覺后來是因為JML沒啥可考的才搞算法),或許可以考慮壓縮成兩次?這樣就可以提前一周結課了,不會影響烤漆(雖然我好像也沒受啥影響,畢竟6系這學期無烤漆
線上OO感受
線上學習對於OO的影響幾乎為0。
除了理論課和研討課的效果稍微不如線下以外,作業的完成、測試都完全沒受影響。
感言
體驗極佳的一門課,很系統很完整,從發布指導書到中測、互測、強測一氣呵成,感覺學到了很多東西,不限於OO,還提升了我很多基本的計算機素養
雖然內容很多也不簡單,也很瘋狂雞肉卷,但總有一些亮點讓我覺得學習這門課很有趣,比如互測的聖杯戰爭(Lancer是我本命,還經常被分到Lancer,喜滋滋,忽略幸運E)
老師們上課各有風格,溫文爾雅和幽默風趣我都可以,討論時也很認真在群里引導我們,老師辛苦了
感覺助教團隊為良好的學習體驗貢獻超多,太強大了,請允許我發自肺腑地吶喊一聲助教nb
作為瘋狂雞肉卷中的一根蔥絲,感謝其他從者幫我找到的錯誤