哈爾濱工業大學2022春軟體構造Lab2實驗經歷與實驗心得,可供後來學子借鑒學習 ...
(防扒小助手)
本人CSDN博客:
本人博客園博客(同步CSDN):
如果對你有用的話歡迎點贊關註喲!
目錄
3.1.1 Get the code and prepare Git repository
3.1.3 Problem 2: Implement Graph
3.1.4 Problem 3: Implement generic Graph
3.1.6 Before you’re done
3.2 Re-implement the Social Network in Lab1
1、實驗目標概述
本次實驗訓練抽象數據類型(ADT)的設計、規約、測試,並使用面向對象
編程(OOP)技術實現 ADT。具體來說:
- 針對給定的應用問題,從問題描述中識別所需的 ADT;
- 設計 ADT 規約(pre-condition、post-condition)並評估規約的質量;
- 根據 ADT 的規約設計測試用例;
- ADT 的泛型化;
- 根據規約設計 ADT 的多種不同的實現;針對每種實現,設計其表示 (representation)、表示不變性(rep invariant)、抽象過程(abstraction function)
- 使用 OOP 實現 ADT,並判定表示不變性是否違反、各實現是否存在表示泄露(rep exposure)
- 測試 ADT 的實現並評估測試的覆蓋度;
- 使用 ADT 及其實現,為應用問題開發程式;
- 在測試代碼中,能夠寫出 testing strategy 並據此設計測試用例。
2、實驗環境配置
(1)安裝測試用例代碼覆蓋度插件
經過網上查閱資料瞭解到,在IDEA中已經集成了代碼覆蓋度插件JaCoCo,切換方式如下:
點擊Edit Configuration,彈出如下視窗:
在Code Coverage一欄點擊Modify勾選紅框中的選項,則會彈出切換代碼覆蓋度工具的選項:
通過咨詢軟體構造課程老師與助教老師,瞭解到使用IDEA自帶的代碼覆蓋度工具即可,不需要切換到JaCoCo,因此下文代碼覆蓋度測試均使用IDEA自帶的coverage runner進行測試。
2、GitHub Lab2倉庫的URL地址(Lab2-學號)
略。
3、實驗過程
3.1 Poetic Walks
該任務主要是通過實現一個圖的模塊來練習ADT的規約設計和ADT的不同實現。
(1)完善Graph介面類,並運用泛型的思想,將String拓展為泛型L類;
(2)實現Graph介面類:以邊和點兩種方式實現介面;
(3)利用實現的Graph類,應用圖的思想,實現GraphPoet類。如果輸入的文本的兩個單詞之間存在橋接詞,則插入該橋接詞;若存在多個單一橋接詞,則選取邊權重較大者。
3.1.1 Get the code and prepare Git repository
從要求文件中對應網址下載得到實驗代碼,建立好project,進入目錄,打開Git bush
依次輸入:
git init
git remote add origin [email protected]:ComputerScienceHIT/HIT-Lab2-120L022408.git
git pull origin master
git add .
git commit -m “init”
git push origin master
3.1.2 Problem 1: Test Graph <String>
測試Graph的靜態方法。
為了方便測試Graph的多種實現,在 GraphInstanceTest 中測試了實例方法。
編寫測試用例主要利用等價類劃分的思想進行測試,測試策略如下:
分別編寫覆蓋以上條件的測試用例。
運行GraphStaticTest得到測試結果如下:
3.1.3 Problem 2: Implement Graph <String>
3.1.3.1 Implement ConcreteEdgesGraph
(1)Edge類實現
定義兩個private String類型的變數source和target存放每個邊的起止點
定義一個private int類型的變數weight保存這條邊的權重(長度)
private final String source, target;
private final int weight;
關於AF,RI和rep exposure:
① 構造器 constructor
構造方法,使用上述三個數據域聲明一個新的邊
public Edge(L source_new, L target_new, int weight_new)
{
this.source = source_new;
this.target = target_new;
this.weight = weight_new;
checkRep();
}
② 檢查表示不變數 checkRep
檢查表示不變數,其中source和target必須非空,weight必須大於0
public void checkRep()
{
assert source != null;
assert target != null;
assert weight > 0;
}
③ get方法
get_Source:返回source域
get_Target:返回target域
get_Weight:返回weight域
④ toString方法
返回一個字元串表明這條邊是從哪個source到哪個target,其weight是多少。
public String toString()
{
return source.toString() + "->" + target.toString() + "\t權重為" + weight + '\n';
}
(2)ConcreteEdgesGraph實現
vertices和edges分別記錄當前graph所含有的點和邊
private final Set<String> vertices = new HashSet<>();
private final List<Edge<String>> edges = new ArrayList<>();
關於AF,RI和rep exposure:
① add方法
public boolean add(String vertex)
如果頂點不為空,添加一個頂點。如果在vertices的Set集合中成功添加了vertex,則返回true。
② Set方法
public int set(String source, String target, int weight)
輸入source,target,weight,確定一條有向邊。
具體做法:如weight!=0,移去可能已經存在的相同起始點的邊,然後加入新的邊,如weight=0,尋找可能已經存在的相同起始點的邊,刪去。
③ remove方法
public boolean remove(String vertex)
從vertices中刪去給定的vertex點,遍歷edges,尋找該vertex是否為某條邊的起點或者終點,刪去相應的邊。在使用迭代器遍歷時要使用iterator.remove方法保證安全性。
④ vertices方法
public Set<String> vertices()
返回vertices集合。註意做到safety from rep exposure ,使用Collections.unmodifiableSet()方法。
⑤ sources方法
public Map<String, Integer> sources(String target)
參數:target。根據傳入的target參數尋找以targe為終點的邊。返回一個鍵值對為(點,權重)的map。
實現:建立一個map,利用迭代器遍歷edges,如果某個edge的edge.get_Target()和傳入參數target相等,則將該邊的source和weight存入map中。
⑥ targets方法
public Map<String, Integer> targets(String source)
參數:source。根據傳入的source參數尋找以source為起點的邊。返回一個鍵值對為(點,權重)的map。
實現:建立一個map,利用迭代器遍歷edges,如果某個edge的edge.get_Source()和傳入參數source相等,則將該邊的target和weight存入map中。
⑦ 檢查表示不變數 checkRep
思路:n個點,最多構成n*(n-1)條有向邊,因此存在這種不可變的數學關係
⑧ toString方法
對每條邊調用toString方法,整合起來。
public String toString()
{
String s = "";
for (Edge<L> e : edges)
{
s = s + e.toString();
}
return s;
}
(3)ConcreteEdgesGraphTest測試
JUnit測試結果如下:
測
試覆蓋率:
3.1.3.2 Implement ConcreteVerticesGraph
(1)Vertex類實現