BUAA_OO_U4_Summary
目錄- BUAA_OO_U4_Summary
- 一 / 架構設計
- 1.0> 題目決議
- 1.1> HW13
- 1.1.1> 關于UML
- 1.1.2> 關于類圖
- 1.1.3> 找到全部父介面
- 1.1.4> 代碼構架
- 1.2> HW14
- 1.2.1> 關于狀態圖
- 1.2.2> 關于順序圖
- 1.2.3> 代碼構架
- 1.3> HW15
- 1.3.1> 迭代開發
- 1.3.2> 讀不懂指導書
- 1.3.3> 代碼構架
- 二 / 架構設計思維及OO方法理解的演進
- 2.1> 架構設計
- 2.2> oo方法理解
- 三 / 測驗理解與實踐的演進
- 五 / 課程識訓
- 六 / 改進建議
- 一 / 架構設計
一 / 架構設計
1.0> 題目決議
實作UML類圖的分析,
1.1> HW13
1.1.1> 關于UML
從JML到UML,對于從模型到實作的能力訓練,此單元從上一單元的Java Modeling Language升級到了Unified Modeling Language——統一建模語言,它是通用的,不是針對某一種語言而制,
截止UML2.0,一共有13種圖模型,在pre中便已讓我們接觸了類圖,在接下來兩個單元的總結中本人也對著代碼繪制了相應類圖(但其實老師強調了多次,這是一個錯誤的順序,應該先有類圖,再對照著類圖形成代碼,所以這個錯誤的順序只能更加凸顯本人架構能力的脆弱,只能邊寫邊想從而產生一些不必要的重構),第二個單元在處理執行緒問題時也用到了順序圖,在這個單元中新增了對狀態圖的認識,
- 類圖:描述系統中類的靜態結構,
- 順序圖:物件之間的動態合作關系,強調物件發送訊息的順序,同時顯示物件之間的互動
- 狀態圖:是描述狀態到狀態控制流,常用于動態特性建模
1.1.2> 關于類圖

這里借用第四單元手冊里面的一張圖,它已經很清晰的展示了類圖里面的元素及其結構,本人在編程時也采用的此結構進行的所需類的設計,可見下面的代碼架構部分,
1.1.3> 找到全部父介面
這個單元說難也不難,說簡單也不簡單(至少令本蒟蒻感到比較頭疼),一個是讀不懂指導書,另一個就是拿不準應該怎么實作,最后本人的所有功能都是能跑但是暴力的做法,沒有追求任何時間上的優化了(因為實在來不及優化了),但是在找父介面的地方,如果每次都遞回到曾曾…曾祖父去,未免太浪費時間了,所以采取記憶化搜索的方式,
按理說,記憶化搜索很好寫,即如果已經搜索過這個介面,那么這個介面的全部父介面都應該已經被存盤到這個介面里了,直接拿來用即可,否則繼續遞回下去,但是對于一個java資料結構新手來說,遇到Null Pointer Exception已經是家常便飯了,這種時候有兩種解決方式,一個是單步除錯,看是哪個陳述句報了錯,另一個是利用idea的流調功能,其實和單步除錯很相似但是不用自己去運行了,
1.1.4> 代碼構架

MyImplementation:用于實作官方包的介面,但是在這一次作業中,本人把大量的處理代碼都塞在了這個類中,導致行數極多,翻起來也非常復雜
MyClass:通過組合封裝了一個UmlClass,用于處理類之間的關系(父類、子類、聯系等)和類自身的屬性(擁有的屬性、方法等)
MyInterface:通過組合封裝了一個UmlInterface,用于處理介面之間的關系(泛化等)和介面自身的屬性(擁有的方法)
MyOperation:通過組合封裝了一個UmlOperation
MyType:用于判斷一個UmlParameter的型別是否合法,在這里本人卡了很久,因為遲遲沒有發現怎么使用官方包進行型別的判斷,直到發現需要先轉型然后才能用NameType中的型別進行字串比較,
1.2> HW14
新增對狀態圖和順序圖的分析,
1.2.1> 關于狀態圖

再次從手冊里截一張圖,
狀態圖相對來說比較好理解,一方面原因是它長得就是一個狀態機(在上個學期已經被折磨過了),另一方面是第四單元手冊中對于狀態圖的講解非常詳細,還有原因就是其中涉及的結構相較來說簡單一些,如上圖右上角所示,狀態機表示的就是從一個狀態到下一個狀態,需要什么條件誘發,誘發的結果是什么,
1.2.2> 關于順序圖
順序圖在第二單元便已經接觸過了,但是當時畫的那幅圖一言難盡,首先是混亂,其次是用錯了很多箭頭,通過這次的手冊本人也深刻意識到了這兩點,

圖片依舊來自于第四單元手冊,
這個結構圖看起來就更加清晰明了了,但是很有趣的一點是,UmlAttribute不僅在類圖里作為class的屬性出現,也可以作為狀態圖中表示協同行為的屬性成員,每個UmlLifeline都關聯到一個UmlAttribute ,也就是對應了一個具體的物件,
1.2.3> 代碼構架

這張圖以MyImplementation類為中心,左上是狀態圖,左下是順序圖,右側是類圖的元素們,
MyImplementation:用于實作官方包的介面,這次作業沒有新建utils類,并把這個類控制在了剛好500行的位置
MyClass:通過組合封裝了一個UmlClass,用于處理類之間的關系(父類、子類、聯系等)和類自身的屬性(擁有的屬性、方法等)
MyInterface:通過組合封裝了一個UmlInterface,用于處理介面之間的關系(泛化等)和介面自身的屬性(擁有的方法)
MyOperation:通過組合封裝了一個UmlOperation
MyType:用于判斷一個UmlParameter的型別是否合法
MyStateMachine:通過組合封裝了一個UmlStateMachine,用于保存當前狀態模型最頂層的結構,但是本單元作業保證了每個StateMachine下面只有一個Region,所以這個類可有可無,本人只是想讓自己代碼的類圖看起來完整一點
MyRegion:通過組合封裝了一個UmlRegion,里面存盤了所有的state和所有的transition,是一個畫布的存在
MyState:通過組合封裝了UmlState、UmlPseudostate和UmlFinalState,并設定變數記錄狀態的型別,存盤從此狀態遷出的trasition集合
MyCollaboration:通過組合封裝了UmlCollaboration,存盤所有的attribute和interaction
MyInteraction:通過組合封裝了UmlInteraction,存盤所有的訊息和生命線
MyLifeLine:通過組合封裝了UmlLifeline
1.3> HW15
1.3.1> 迭代開發
對類圖、狀態圖、順序圖中的例外進行判斷,
1.3.2> 讀不懂指導書
對于這樣一條R002的規則,給出的解釋如下:“針對類圖中的類(UMLClass),其成員屬性(UMLAttribute)和關聯的另一端所連接的 UMLAssociationEnd 這兩者構成的整體中,不能有重名的成員,”
拆詞能看出來,他讓我找成員屬性+關聯+另一端的連接+整體+重名+成員,成員屬性和成員是一個東西嗎?我只知道屬性是屬性,UMLAttribute可以被當做是屬性,現在這個解釋告訴我它也教成員屬性,那成員究竟指什么?雖然最后的事實證明,屬性=成員=成員屬性,整體又是什么?自己這個類中的這個屬性和關聯的另一個類或介面的全部屬性,以及兩個UmlAssociationEnd構成了這個整體的入侵時成員,所以只需要再這個里面找重名的即可,但是理解這個概念遠比我寫完這次作業所需時間長的久——現在看懂了,便有億點體會不到當時那種焦慮無助的感受了,但指導書中的各種文字真的充滿了陌生與掙扎,
1.3.3> 代碼構架

這個是完整版,這張圖以readDiagram類為中心,左上是類圖,左下是順序圖,右側是狀態圖圖的元素們,
MyImplementation:用于實作官方包的介面,新建的Utils類分走了很多代碼
ReadDiagram:工具類,用于讀入
MyClass:通過組合封裝了一個UmlClass,用于處理類之間的關系(父類、子類、聯系等)和類自身的屬性(擁有的屬性、方法等)
MyInterface:通過組合封裝了一個UmlInterface,用于處理介面之間的關系(泛化等)和介面自身的屬性(擁有的方法)
MyOperation:通過組合封裝了一個UmlOperation
MyAssociation:通過組合封裝了一個UmlAssociation,用于保存關聯關系的兩端
MyElement:慶祝一下蒟蒻終于使用了介面這件事,其實沒有必要,這個只是作為統一MyClass和MyInterface,便于跑dfs和bfs處理例外的時候用
MyType:用于判斷一個UmlParameter的型別是否合法
MyStateMachine:通過組合封裝了一個UmlStateMachine,用于保存當前狀態模型最頂層的結構,但是本單元作業保證了每個StateMachine下面只有一個Region,所以這個類可有可無,本人只是想讓自己代碼的類圖看起來完整一點
MyRegion:通過組合封裝了一個UmlRegion,里面存盤了所有的state和所有的transition,是一個畫布的存在
MyState:通過組合封裝了UmlState、UmlPseudostate和UmlFinalState,并設定變數記錄狀態的型別,存盤從此狀態遷出的trasition集合
MyTransition:通過組合封裝了UmlTransition,存盤其上的所有event
MyCollaboration:通過組合封裝了UmlCollaboration,存盤所有的attribute和interaction
MyInteraction:通過組合封裝了UmlInteraction,存盤所有的訊息和生命線
MyLifeLine:通過組合封裝了UmlLifeline

稍微更清晰但簡略的版本如上圖所示,本想歸類更明顯一點,奈何這個連線動起來實在是太麻煩,但是大致可以看出來,從左往右分別為類圖、狀態圖和順序圖的架構,
二 / 架構設計思維及OO方法理解的演進
2.1> 架構設計
盡管每個單元各有各的側重點,但是在所有的博客中,必要的環節都是架構分析,它是一個抽象,一個對于我需要實作的任務目標的抽象,不考慮實作細節,不需要考慮每個物件如何作業,只考慮需要什么物件,他們各自做什么的程序,就像一個大老板,安排好任務,怎么實作是勞動力的事情——這就很面向物件了,Uml圖是很好的一個表達方式,但可惜本人有此意識而無此行動,每次都是寫完代碼才著手繪制UML圖,在其之前都只是在腦子中構想我需要怎么化解這個任務,
第一單元的目標是決議運算式,所以物件就是運算式,架構設計體現在把這些運算式分類,分成多項式、單項式等的抽象,然后進行處理,

第二單元的目標是讓電梯安全的運行,涉及到的物件有電梯、請求、生產著消費者模型中的托盤等,在套用改模型的前提下需要考慮生產者和消費者都是什么的問題,其余更多的執行緒安全實作不在架構考慮范圍內,

第三單元跟著JML走,通過JML告訴我們的社交網路中基本單位(人、小組)和需要實作的查詢方法構建整個社交網路的結構,是架構非常清晰的一個單元,

第四單元分析UML,架構同樣很清晰,于是直接采用了UML類圖的架構,三種不同的圖示型別也讓本人清晰的了解了三種處理不同問題的架構應該是怎樣的,只不過這個架構是從比確定問題中的物件是什么而言更抽象、更高的角度,來看待一個問題可以被劃分成類、介面或是各個狀態、各個生命線的模樣的方法,

2.2> oo方法理解
第一單元主要聚焦點有點跑偏到實作方面了,也就是遞回下降,對于面向物件的直觀體驗是從運算式中抽象出一個最小的不考慮它內部如何處理的單位,然后不斷合并為新的可處理的物件,直至合并至整個運算式,
第二單元學習了不少設計模式,這是面向物件編程的基礎,面向物件注重行為,設計模式就告訴你行為的藍圖,而設計模式的五大基本原則:單一職責、開閉(對擴展開放,對修改封閉)、依賴倒置(細節依賴于介面,針對介面編程,而不針對實作編程)、介面隔離(使用多個專門的介面)、里氏替換原則(子類必須能夠替換掉它們的父類)在后續的作業中,讓本人的架構設計和面向物件思想變得更清晰了一些,特別是幫助本人降低類與類之間的耦合度方面,以及降低復雜度,讓代碼變得易于除錯減少錯誤方面都有著很大的提升,
第三單元中,JML的規格約束讓本人更加深入的理解了面向物件的意義,即利用的高度抽象,清晰明確的展現需求,不考慮步驟而關注功能,不注重程序而關注行為的解決問題視角,
第四單元中,UML這樣的面向物件的建模語言,讓本人在實作的同時回顧了整個oo中用到的類、介面等元素以及繼承、泛化、組合、依賴、實作、關聯這六種關系,更加深刻的體會了面向物件的建模方式,
三 / 測驗理解與實踐的演進
其實本人只在一三兩個單元做了測驗程式的撰寫(包括評測和對拍),二四單元沒有寫評測機,從錯誤的數量來看,明顯沒有進行自行評測的兩個單元得分更低,所以如果時間允許,多做測驗,
從實踐方面,在第一單元作業中,本人學習了如何使用python的subprocess模塊中的popen,第一單元采用通過開啟pipe來和程式互動,第三單元輸入量較大,輸出量也大,所以如果輸入輸出都使用pipe進行的話,管道會炸掉,所以改用輸出至檔案的方式,
如第一單元:
process = subprocess.Popen(['java', '-jar', jarDir], stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate(strInput.encode())
ret = []
ret += stdout.decode().split('\n')
process.kill()
第三單元:
process = subprocess.Popen(['java', '-jar', jarName], stdin=PIPE, stdout=open(outputFile, 'w'), stderr=PIPE)
for ln in strInput:
process.stdin.write(ln.encode())
process.stdin.close()
process.communicate()
process.wait()
process.kill()
這個做法一直沿用了下去,對于每條指令的測驗,無論一三單元,本人都是通過一個個單獨撰寫的函式進行的,同時再用一個函式來生成所有的輸入,這樣可以便捷的更改測驗資料,
如:
def add_person():
···
def add_relation():
···
def query_value():
···
def getInput():
for j in range(5):
add_person()
for j in range(10):
add_relation()
···
從測驗的理解方面,兩個單元中均采用了手動構造+在給定范圍內的隨機測驗,從測驗范圍來看,均有從單元測驗到復雜測驗的程序,其中第一單元中“單元”的劃分為每個運算子,針對它的測驗本人做的極為有限,基本是手動輸入一些可能發生的復雜情況(比如-1**0),而第三單元中這個“單元”的概念被我放大到這一段干了同型別事情的指令,比如造人+造組+組里加人+造紅包資訊+發紅包+查詢錢數諸如這樣的組合,但這樣的測驗也需要注意順序,比如先測好基本的功能,如group加人刪人是否正常,再進行一個個功能單元的測驗,如收發紅包發表情發群公告等,最后再將其融合在一起,進行大雜燴的測驗,同時,由于完全隨機的效率低下,在第一單元中就遇到了在2k次中僅出現一次錯誤的情況,所以在第三單元中本人也改變了隨機測驗的思路,變為半隨機的樣子——手動控制人的id,隨機其他資料,這樣明顯提高了資料的強度,在自測和互測中都起到了非常好的作用,
在互測中,本人也學習了閱讀他人代碼并發現錯誤的能力,雖然這種錯誤僅限于字串處理或者一些程設方面的錯誤,其他的問題還是需要借助評測機的幫助才能被看出來,
所以總結來看,本人通過四個單元的評測,學習了測驗的步驟和方面,并在自己的實踐中不斷拓展測驗的方面,提高資料的有效性,向覆寫率高的測驗方向發展,
五 / 課程識訓
pre:進行了java的入門,并認識了非常典型的面向物件的例子,通過實踐體會了繼承、實作、關聯等關系,同時認識了UML類圖這樣的架構表述方式,
第一單元:運用pre中學習的基本知識,對運算式進行抽象,利用在training里學到的遞回下降方法實作運算式的決議,
第二單元:通過對電梯的安排,了解執行緒安全的實作方式(加鎖,加讀寫鎖,加sychronized修飾符,采用阻塞對了等),學習不同的設計模式(如創建型模式中的單例模式、工廠方法模式,結構型模式模型中的組合模式,行為性模式中的觀察者模式,以及在23中基本模式之外的生產者消費者模式),對架構能力的要求為四個單元中最高,
第三單元:閱讀JML,學習JML這種語言的語法和優勢,在構建社交網路的程序中復習圖論的演算法并在java中撰寫資料結構,學習java中例外的拋出與處理,JML具有非常明確清晰的需求描述,使得本人可以快速得到架構與實作方法,
第四單元:將modeling language從Jml上升至Uml,處理Uml類圖、順序圖和狀態圖三種常用繪圖方式的決議方法,更加深刻的體會如何拆分一個任務,并安排需要的物件,
六 / 改進建議
-
希望可以在每次上機后給出上機測驗的答案,雖然這種事情也可以通過問同學解決,但如果有更便捷的,能讓所有人都獲得答案的方式,看起來會更方便一些,這樣本人才能更好的意識到自己在某些地方對代碼理解上的偏差,特別是后面的三四兩個單元,不是程式能跑就說明寫的沒有問題,而且基本都是填空題,如果沒有標準答案的話,容易產生一些誤解,
-
研討課的分享可以擺脫“上一次作業我是如何實作的”這種話題(除非是非常精妙特殊的實作方式),畢竟大家都已經寫完了,而且有互測的代碼進行觀看,在組內討論的環節進行分享就夠了,再進行這樣的講解感覺有點耽誤了研討課的時間,
-
在每個單元第一次作業之前發布一點自愿思考的小任務,比如在pre階段接觸一點遞回下降的思路,在第一單元博客時寫一些比training中的限制多一些的生產-消費者模型等等,當然一定采取自愿的形式,稍微降低一點每個單元第一次作業的難度,否則經常到周四的上機后才能意識到應該怎么寫,感覺時間有點緊張(不過…可能菜是原罪吧),
-
第四單元的指導書中,有一些文字可能還可以斟酌一下,因為經過第三單元的JML之后,感覺文字表述的二義性還是有點明顯的,閱讀充滿文字的要求突然覺得陌生了起來(當然,也有可能是本人理解能力的問題),
-
討論區有時翻起來比較混亂,問題和助教回答混在一起,不知能否改進為每個回答都顯示在問題緊下方的形式,這樣不容易看漏也比較方便閱讀,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/498971.html
標籤:面向對象
上一篇:OO第四單元總結
