第三單元總結性部落格
第九次作業
本次作業主要完成了一個社交網路的基本框架,主要包含以下三個部分:
Person
組成了社交網路中的“節點”,本身具有一定的屬性,並且與其它的 Person
之間有熟人關係,形成了社交網路中的“邊”。
Group
是一個 Person
群組,主要用於統計群組中的 Person
屬性。
Network是我們建立的社交網路,相當於資料結構中的“圖”,和後面的查詢具有緊密的關係。
我們要完成的任務就是理解整體架構並實現JML的描述。
第十次作業
第十次作業主要完成了增量開發:
實現 Message
介面,並且修改原來的程式碼,實現訊息的傳送和接收。
實現新指令的增加,尤其注意的是指令queryLeastConnection
第十一次作業
第十一次作業主要完成的增量開發:
拓展 Message
類,實現其三個子類,以用來實現不同的功能。
實現新指令的增加,尤其注意的是指令sendIndirectMessage
。
測試資料的構建
針對本單元的需要,我主要採用了隨機生成資料的方法,並且對於資料進行一定的限制,自動化對拍進行測試。
首先是常規指令的生成,在資料生成初期只生成ap
、ar
、ag
、atg
指令,並且儘量縮小資料的範圍,並且保證資料的數量,來構建一個比較大規模的社交網路。
之後,隨機生成各種查詢指令,在最初,只是無規律的隨機將作業中需要的二十餘類資料進行生成並進行測試,但是這樣的方法查詢效果並不是很好,完全隨機生成的資料讓大多數指令的結果都是丟擲某種異常,這樣就很大程度喪失了測試的覆蓋範圍。
之後我們增加了相關部分的程式碼,通過新增一定數量的Person和Group,保證了後續查詢指令的有效性。此外,對於一些相關規格細節和效能的測試,我們通過手動來構造,比如檢查 qlc
指令的效能,通過新增足夠的簡單指令,在課程要求的範圍內,增加足夠的此指令,就能夠檢查出來一定的效能問題。
程式碼問題和修復情況
非效能問題
查詢方法,當查詢的某一個屬性出現 null
時,應該要對其特別處理,比如我的程式碼中出現對 null
的物件使用了其它方法,這顯然是不合適的。
效能問題
主要出現在 qci
, qlc
, sim
,方法的複雜度問題,在我的第一版程式碼中,並沒有注意這方面的維護,因此除了很多問題。
修復情況
qci:使用並查集進行查詢。這是本單元第一次作業中最困難的一個函式,之後根據討論區中的帖子,改成使用並查集的方式實現。
qlc:由於以及實現並查集,我選擇使用通過並查集來優化Kruskal演算法在合併劃分以及判斷劃分時的時間複雜度,從而實現優化的Kruskal演算法。
Network拓展
首先,對於產品,設計一個介面Product,對於每一個產品,我們關心的是他的屬性,在我們的要求中並沒有體現出來價格,不過價格也是重要的因素。
price
:商品的價格,可能影響到客戶能否購買,影響 Person
類的資金查詢。
type
:商品的類別,可以設定為列舉類。
其次,對於 “Advertiser:持續向外傳送產品廣告” ,我們可以拓展自己的 Messgae
,增加新的商業廣告資訊 saleMessage
,對於此類增加的資訊可以有:
toGroup
:除了之前直接傳送給個人,或許可以直接傳送給 Group
,比較貼近現實
對於 Person
類,題目中說明關注廣告並選擇和自己偏好匹配的產品來購買,那麼就應該增加其它的屬性:
首先是涉及的三類人可以通過繼承Person介面實現。
Advertiser
:經銷商。需要儲存傳送的廣告資訊saleMessage[]
,並負責傳送推銷訊息;
Producer
:產品商。需要儲存自己生產的products[]
,產品數目 nums[]
和收入inputs[]
,負責提供產品。
Costomer
:消費者。需要儲存自己的需求types[]
和需求量demands[]
,已經擁有的產品。
Person
保持原狀,不過也需要增加對相關屬性的查詢。
判斷消費者是否會購買這個產品
/*
@ public normal_behavior
@ assignable \nothing;
@ ensures \result == ((\exists int i; 0 <= i && i <= types.length;
@ product.getType.equals(types[i]) &&
@ product.getPrice < money));
*/
public boolean checkDemand(Product product);
查詢消費者是否購買此類產品
/*
@ public normal_behavior
@ assignable \nothing;
@ ensures \result == ((\exists int i; 0 <= i && i <=
@ products.length;
@ products[i].getType.equals(product.getType))
*/
public boolean checkProduct(Product product);
消費者購買產品
/*
@ public normal_behavior
@ assignable \nothing;
@ requires product.getPrice < money;
@ requires (\exists int i; 0 <= i && i <= types.length;
@ product.getType.equals(types[i]))
@ ensures money + product.getPrice = \old(money);
@ ensures (\forall int i; 0 <= i && i < \old(products.length); products[i] == \old(products[i]));
@ ensures products.length = \old(products.length) + 1;
@ also
@ public exceptional_behavior
@ signals (PersonNotPurchase e)
*/
public void getProduct(Product product);
心得體會
這一單元整體難度不大,但是我做的效果不好,究其原因,是對於 jml
規格的閱讀不夠熟練,對於複雜方法的 jml