兩次UML解析程序,主要是遞進式的,第一次解析了類圖,第二次在類圖基礎上,增長檢查規則和順序圖及狀態圖。java
整體架構思路主要有五點:算法
一、儘可能還原圖自己的結構(組裝)json
二、分類(狀態圖、順序圖、狀態圖)設計模式
三、元素與關係分離安全
四、對同一類element進行合併數據結構
五、抽象Element多線程
先從類圖來說:架構
一、還原框架
每一個class有attribution、operationide
每一個operation有parameter
所以有
UMLPARAMETER-->UMLOPERATION + UMLATTRIBUTION -------> UMLCLASS
對接口有相似操做,繼承Class便可
簡單的畫個類圖他們關係大概就是這樣
咱們只需經過json中的_parent和id就能夠把他們聯繫這一塊兒,至此重組完成。
針對第二次解析程序這裏有一些小改變(元素重名檢查):
因爲類圖檢查須要檢查Class對端的asscociationEnd與自身Attribution的重名問題。也就是說associationEnd也會屬於Class,所以AbstractClass中的內容須要增長asscociationEnd的存放(只需增長一個容器和規則檢查方法,總體難度不大,算是作了一次小拓展)
二、關係與元素分離
關係主要是類之間的,有繼承、實現、關聯。
因爲UMLClass是咱們元素組裝的最上層,天然關係與其同層次,放在任何一個裏面都不太合適,所以選擇了將他們分離的策略。
咱們單獨創建一個Relation來存放他們。
解析json-->識別type-->分類存放 便可。
針對第二次解析程序這裏有一些小改變(關係檢查):
不管是循環繼承的檢查仍是重複繼承的檢查,都整合了這兩種關係(繼承、實現),所以爲了操做方便,這裏選擇增長一個RelationCheck類,構建一個繼承和實現關係構成的圖。而後用上各類搜索方法(如DFS)就能夠輕鬆解決上述檢查。
由此能夠看出,在這種架構之下,兩次解析程序的遞進針對類圖都不會出現重構的狀況,只需作少許拓展,便可完成。
再討論下狀態圖吧
一、還原
跟類圖同樣,按照層次關係:(關係比類圖要簡單點)
UMLState + UMLTransition --> UMLReion --> UMLStateMachine
重組便可
public class AbstractStateMachine {
private String name;
private String id;
//Region
private String regionId;
// UMLTransition
private HashMap<String, UmlTransition> idToTranstion = new HashMap<>();
private HashSet<AbstractTrans> transHashSet = new HashSet<>();
//UMLState
private HashSet<AbstractState> states = new HashSet<>();
private HashMap<String, AbstractState> idToState = new HashMap<>();
private HashMap<String, ArrayList<String>> nameToState = new HashMap<>();
//RELATION
private HashMap<AbstractState, HashSet<AbstractState>> transRelation
= new HashMap<>();
private HashMap<AbstractState, Integer> idToSubCount
= new HashMap<>();
可能會發現Region怎麼彷佛和State平級,主要是因爲Region實在對查詢功能無大用,更像是StateMachine的傀儡???
二、合併
這是我針對本次做業想重點討論的話題。
也是我認爲本次設計成功的點之一:爲了易修改,易拓展而設計
State
狀態機中有三類狀態:UmlFinalState、UmlPseudostate、UmlState,狀態統計須要考慮這三者,同時狀態轉移也是在這三者中進行,所以咱們能夠採用一個AbstractState類來代替這三種。
public class AbstractState {
//0: state -1:init 1:final
private int type;
private String name;
private String id;
public AbstractState(int type, String name, String id) {
...
}
這樣作有良好的可修改性,咱們能夠自行定義,什麼是共同狀態?。
好比針對以前一直比較有爭議的是否合併起始狀態等問題,只需修改重寫的equals方法便可。
一樣,對Transiton也採用一樣的方法。
package stategraph;
import java.util.ArrayList;
public class AbstractTrans {
private String id;
private String name;
private AbstractState source;
private AbstractState target;
private String guard;
private ArrayList<String> triggers;
public AbstractTrans(String id, String name, AbstractState source,
AbstractState target, String guard,
ArrayList<String> triggers) {
...
}
一樣,什麼是相同狀態,咱們就能夠在此定義,一旦規則有變,也只需修改這一處便可。(雖然最後限制了測試數據,這個地方沒有了大用)
三、分離
在這裏,相似於類圖中的操做,把轉移關係存儲爲圖架構。須要注意的是,因爲考慮了合併問題,所以能夠經過一個類AbstractTrans來封裝它,經過重寫equals方法便可實現合併。
最後是最簡單的順序圖:
順序圖整體比較簡單。
一、還原
跟類圖同樣,按照層次關係:
UMLLifeline + UMLMessage ----> UMLInteraction
重組便可
public class AbstractInaction {
private String name;
private String id;
//UMLLifeline
private HashMap<String, UmlLifeline> idToLifeLine = new HashMap<>();
private HashSet<String> represent = new HashSet<>();
private HashMap<String, ArrayList<String>> nameToLifeLine = new HashMap<>();
//UMLMessage
private HashMap<String, UmlMessage> idToMessage = new HashMap<>();
//RELATION
private HashMap<String, Integer> messageIn = new HashMap<>();
...
}
二、關係與元素分離???
(1)Interation跟message是從屬關係,不是同層次
(2)查詢命令簡單,無任何圖算法相關操做
所以,這裏不採用,只是加兩個容器儲存和統計一下便可
四個單元對OO的架構設計是從面向過程到面向對象的一個巨大的轉變。
第一單元,設計之初過多考慮功能性問題,致使多項式求導的設計很是沒有層次感(把因子,項等雜糅在一塊兒,經過遞歸處理,這樣很是不OO)
第二單元,電梯的設計主要是多線程的安全性問題。我遇到了比較大的困難,很差的架構致使了線程不安全的可能性增長。可是通過參考多線程各類設計模式,而且把電梯調度分部分考慮,架構有了必定提高,但代碼雜糅的程度仍是比較高的。
第三單元,JML部分因爲助教提供了一個大致框架,我也更多去思考設計的層面,總體的思路和結構都好轉。
第四單元,UML是我考慮拓展性和架構設計優劣性最多的一次。更多注重下一次功能可否垂手可得增長的內容,而且在本身的debug和修改的過程當中,體會到了很是大的好處。
我認爲OO設計一開始不能一味考慮算法(功能性)和AC的問題,更多應該聚焦在層次拆解。
以第四次單元爲例
(1)設計的最終目的(交互,最高層)
(2)分爲哪幾個大部分(順序圖,狀態圖,類圖)
(3)對每一個部分,有哪些小部分
主要考慮功能部分和元素部分
例如,狀態圖的元素有遷移、狀態,功能是查詢。
針對元素部分作適當有層次的封裝(也就是充分展示類之間的繼承關係,關聯關係)
(4)採用什麼樣的數據結構??
(5)具體實現算法
其實,只要把(1)-(3)重點考慮(通常能夠在紙上畫出層次圖(如使用UML))
(4)作必定考慮 (5)也就垂手可得了
綜上所述
(1)思考和設計大於寫碼,好的層次必定程度上能讓功能設計更加垂手可得。
(2)OO的設計是能幫助更好,更高質量的AC,若是一開始過度考慮AC,反而拔苗助長(慘痛教訓)。
從最開始做業使用手動測試,到多項式的後兩次做業開始嘗試本身編寫評測機制。
從固定結果的驗證方法,到多線程不肯定性如何驗證正確性的測試編寫。
從整體的黑箱測試到Junit作單元測試
從測試正確性到測試運行時間。
上述,大概就展示了我OO中的測試思路的轉變(幾乎每一次轉變都是爆掉幾個點以後的痛定思痛)
我認爲測試
(1)正確性和運行時間兼顧(保證明現的正確性和使用方法和結構的優良性)
(2)整體測試和單元測試兼顧(我後來採用了邊編碼邊JUNIT的歷程,不得不說,正確性更有保障)
(3)自動評測很是重要(利用隨機樣例去測試,經過較長時間的運行,保證黑箱測試的覆蓋率問題)
2、抗壓能力:屢次臨dll修改bug,有成功修改,有不成功修改的,這樣的經歷確實很是鍛鍊在短期的修改代碼並保證正確的能力。
3、需求分析能力:對指導書的內容進行分析,而且逐漸轉化爲程序語言。
4、還有對OO的理解和承認,對測試的體會,都是此次的巨大飛躍。
1、建議課程組提供自主測試平臺:本次測試和評測機測試存在運行時間上的偏差,所以建議給你們開放一個平臺,讓全部人均可以在上面進行測試,獲得運行時間,對多線程以及卡TLE的部分做業很是有幫助。
2、上機內容能夠考慮提早發佈一些預習任務,這樣能讓上機時候更加有針對性去應對,不至於手足無措。
3、適當預告後續做業的需求:有利於更好的拓展性設計。