oo 第四單元UML&課程總結
oo 第四單元UML&課程總結
一、 總結本單元作業的架構設計
本單元的作業是寫一個UML圖的解析器,而具體的將UML圖解析成一個個的UmlElement元素的過程已經在官方包中給出,我們需要做的就是對UmlElement中的元素進行組織與資料結構的設計,以便獲取圖中的相關資訊。
第一次作業
第一次作業僅僅涉及了Uml類圖的解析,與我們平常寫的Java程式碼有很大的相似性(當然剛開始的時候看不懂)。在一番時間的理解之後,對於Uml圖內部的元素就有了基本的認識,然後就按照自己的理解來進行了資料結構的設計:
為了方便程式碼的重用,為所有的元素設定了一公共父類Node
,裡邊存放了一些基本的屬性與最基礎的一些功能例如獲取id與name等等。之後所有帶Node字樣的類均繼承此結點,下面介紹一下各個類中的一些基本的設計。
ClassNode
,這是用來表示類的結點。在其中存放了其具有的屬性(Attribute)與方法(Operation),並存放了子結點(Class)與父節點(Class)以及其實現的介面(Interface)與其有關聯的對端 (Class or Interface)。值得一提的是,對於屬性與方法的儲存方式均採取了二級索引的方式,即以name為一級索引,以id為二級索引,以HashMap<String, HashMap<String, AttributeNode>>
或是HashMap<String, HashMap<String, OperationNode>>
OperationNode
,表示方法的結點,在其中利用HashMap<String, ParameterNode>
存放了方法中涉及到的變數。AttributeNode
,表示類屬性的結點。ParameterNode
,表示變數的結點。InterfaceNode
,表示介面的結點,其中存放了其父結點(Interface)與子結點(Interface),同時存放了直接實現該節點的類(Class)以及關聯的對端(Class or Interface)Initial
,進行初始化的類,利用Initial
UmlElement
分發重組為自己設計的Node
,從而進行下一步工作。MainClass
,程式入口。MyUmlInteraction
,實現題目要求的種種方法。
考慮到查詢的過程中出現了很多重複操作,且查詢的過程中不再涉及到資料的新增,採用了快取的思想來進行效能的優化,在第一次查詢的時候按照正常計算的過程進行,同時將結果儲存下來;在第二次以及之後的相同查詢中,直接呼叫之前儲存下來的結果,這樣可以大大減少計算量,提高效能,缺點是浪費大量空間,但好像不卡空間。
下面是第一次作業的類圖:
從類圖中可以看出,整個架構還是比較明確的,所有的節點都通過ClassNode與MyUmlInteraction進行互動。
第二次作業
第二次作業在類圖部分沒有改動,新增了狀態圖與順序圖部分,但是新增部分的功能要求都較為簡單,下面是對新增類的一些介紹:
-
StateMachineNode
,用來表示狀態機的結點,其中存放了Region結點。 -
RegionNode
,是狀態機的一個“區域”(自己起的名),狀態機中狀態以及狀態轉移等等都在Region的基礎上完成,裡邊儲存了各種狀態(State)。 -
StateNode
,用來表示狀態的結點,可以表示普通狀態,初始狀態,終止狀態,維護一個flag變數來實現。 -
InteractionNode
,是用來表示順序圖的結點,其中存放了了生命線(Lifeline)。 -
LifelineNode
,是用來表示生命線的結點,其中存放了收發的訊息(Message)。 -
MessageNode
,是用來表示訊息的結點,其中存放了訊息的發出者與接收者。
下面是第二次作業的類圖:
從類圖可以看出,在第一次作業的基礎上新增了兩個部分,從以ClassNode
為核心轉變為了以ClassNode
,StateMachineNode
,InteractionNode
為核心的結構,最終由MyUmlGeneralInteraction
來進行呼叫。
第三次作業
第三次作業在第二次作業的基礎上增加了有效性檢查,為了功能實現的獨立性,新增了一Check
類用以專門判斷各種型別的錯誤,而檢查的方法是最基礎的遍歷。值得一提的是debug時發現了自己的漏洞,在判斷自關聯兩個end重名的情況時無法正確處理,根源是利用end的name作為key值維護了一個HashMap,改成了以id為索引的方式之後就能夠成功運行了。
下面是第三次作業的類圖:
可以看出是在第二次作業的基礎上增加了Check
類,其餘變化不大。
二、總結四個單元中架構的設計以及oo方法理解的演進
在oo四個單元的學習過程中,對於專案架構的設計以及面向物件方法的理解有了很大的提升,下面簡單回顧一下:
- 第一單元表示式求導,由於之前C語言課程的影響,第一次接觸Java的時候,寫出來的程式碼其實還是面向過程的,裡邊的各個模組之間耦合性非常強,並沒有做到功能的分離,這就導致了在三次任務之中重構了兩次。因為對於oo理解的不深刻,當時並不明白“低耦合”這句話的意思,因此在設計出的類的方法之中加入了非常多的引數,這時候本質上其實就是面向過程的寫法了。在具體設計的時候,按照層次(例如表示式-項-因子)進行了劃分,但是由於每一個模組之間聯絡較強,這樣的設計並沒有很好的效果。
- 第二單元中的電梯,架構較之第一次有了非常大的提高,做到了每一個模組的功能分離,因此在每一次的迭代開發之中工作量大大減少,相比於第一次開發每個類的方法都是依賴於這個類的屬性實現的,實現了很好的降耦,同時採用了分散式電梯的排程策略。但是由於是第一次接觸多執行緒,對於執行緒安全的控制並沒有做的非常好。
- 第三單元中,由於是按照JML給定的架構進行實現的,對於結構的設計並沒有多大的參與。重點是對於效能的優化,採用了並查集的資料結構,同時採用了迪傑斯特拉演算法的堆優化。
- 第四單元中的UML部分是設計的較為成功的一次,在每一個類的設計上都實現了良好的降耦,因此在第二三次的任務中,並不需要對原本的程式碼進行大的改動,僅僅需要新增新的屬性與方法就能夠實現功能的擴充。
三、總結在四個單元中測試理解與實踐的演進
在四個單元之中的測試其實做的並不算成功,第一單元之中的測試在同學的幫助之下成功地搭建了評測機,做了充分的黑箱測試,也進行了部分極端的白箱測試;而在於之後的三個單元,由於自己不會搭建評測機,黑箱測試部分就很難進行下去,都採取了白箱測試的方式,但是白箱測試本身具有覆蓋面並不廣泛等缺點,因此對於專案的功能測試並不能做到十分的全面。經歷了一個學期的學習之後,我愈發地認識到了測試對於專案的重要性,寫好程式碼僅僅是第一步,之後一定要採取多種方式來進行測試,否則就很容易暴雷。
四、 總結自己的課程收穫
在一個學期的學習之中還是收穫良多的,最直接的是對於Java語言的應用以及對多執行緒內容的瞭解,更重要的是對於面向物件思想的初步接觸與理解,對於UML圖的相關知識有了一定的瞭解,能夠看懂一些簡單的JML規格,python水平也有了一定的增長(第一單元評測機),但同時由於經常通宵熬夜來完成oo作業,也增長了爆肝能力與心理承受能力。
五、立足於自己的體會給課程提三個具體改進建議
- 每一次作業的難度設定
第一二次作業的難度相較於第三四次大了不是一點半點,尤其是在剛剛接觸oo這門課的時候,第一單元的作業非常容易勸退人,而第一單元的第一次作業與第二次作業之間的跨度還非常大(正則表示式不支援遞迴),本菜雞在第一單元第二次作業的時候通宵達旦地更改程式碼,差點就放棄了,建議增加一些提示(比如遞迴下降)或者適當的調整一下作業的順序
- 適當提前題目下放時間
每次題目的下放都是在本週的oo課結束之後才進行的,可能是想讓同學們聽課之後再去做題,但是在不知道題目的情況之下很可能出現聽課沒有重點的情況(參考隔壁OS實驗課之前講課),如果能夠適當下放題目,提前知道自己需要學習什麼知識,可能對於聽課的側重點就有了更明確的想法。
- 實驗課給出評測結果(課下也行)
每一次實驗課提交的程式碼都不知道結果如何,感覺就像對牛彈琴,如果是課上不給出評測結果可以理解,是讓我們自己充分測試,但是課下依舊不給出評測結果實在是有些令人摸不著頭腦。