软件构造Lab2记录 实验目标概述 本次实验训练抽象数据类型(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并据此设计测试用例。
实验环境配置 由于IDEA中集成了jacoco ,故直接在配置界面开启即可
实验过程 Poetic Walks 该任务主要是实验一个图的模块,并基于此使用。
完善Graph接口类,并运用泛型的思想,将String拓展为泛型L类;
实现Graph类的方法:add、set、remove、vertices、sources、targets;
利用实现的Graph类,应用图的思想,实现GraphPoet类,如果输入的文本的两个单词之间存在桥接词,则插入该桥接词;若存在多个单一桥接词,则选取边权重较大者。
Get the code and prepare Git repository git clone即可
Problem 1: Test Graph 测试静态方法生成String类型的Graph。
Problem 2: Implement Graph 该部分要求重写Graph里的方法,分别以点为基础的图和以边为基础的图。两种类型的图都经过同一个实例测试。
Implement ConcreteVerticesGraph Vertex是点的抽象类,包含3个信息:点的标识、指向该点的边、由该点引出的边。Vertex需要能访问这3个信息,以及增加/删除进边/出边。 ConcreteVerticesGraph是以点为基础的图,每个点通过唯一的标识进行区分,set和remove都依赖与Vertex类中的添加和删除操作,sources和targets也调用了Vertex类的方法。
Problem 3: Implement generic Graph Make the implementations generic 在程序中选择选择“String”并选择更改所有匹配项,即可实现泛化类型。
Implement Graph.empty() 使Graph.empty()能返回一个新的空实例即可。
Problem 4: Poetic walks 给定一个语料库corpus,根据corpus中的文本生成一个单词图,然后给定一条语句输入,在图中搜索词之间的关系,自动补全语句中可能可以完善的部分。 图的构建规则是,在corpus中,对每一个不一样的单词看作一个顶点,相邻的单词之间,建立一条有向边,相邻单词对出现的次数,作为这条有向边的权值。在输入信息补全时,对相邻单词A和B做检查,如果存在一个单词C,在图中可以由前一个单词A通过这个单词C到达单词B,那么就在A和B之间补全C,补全的优先级按照权值越大者优先。
Implement GraphPoet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public GraphPoet (File corpus) throws IOException { BufferedReader reader = new BufferedReader (new FileReader (corpus)); String line = "" ; String[] words; while ((line = reader.readLine()) != null ) { line = line.replace("." , " " ); words = line.split(" " ); for (int i = 0 ; i < words.length; i++) { graph.add(words[i].toLowerCase()); if (i > 0 ) { int lastEdgeWeight = graph.set(words[i - 1 ].toLowerCase(), words[i].toLowerCase(), 1 ); if (lastEdgeWeight != 0 ) graph.set(words[i - 1 ].toLowerCase(), words[i].toLowerCase(), lastEdgeWeight + 1 ); } } } reader.close(); checkRep(); }
Re-implement the Social Network in Lab1 这部分任务就是用我们在3.1中写的ADT,把第一次实验中的FriendshipGraph重新实现一遍,图中的节点仍然是Person类型,所以泛型L一律为Person. 而对于已经写好的FriendshipGraph中的方法,要用3.1中的Graph ADT中的方法来实现它们。
FriendshipGraph类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import graph.*;import java.util.*;import java.util.LinkedList;import java.util.Queue;public class FriendshipGraph { private final Graph<Person> graph = Graph.empty(); public boolean addVertex (Person newPerson) { return graph.add(newPerson); } public int addEdge (Person a, Person b) { int lastEdgeWeight; lastEdgeWeight = graph.set(a, b, 1 ); lastEdgeWeight = graph.set(b, a, 1 ); return lastEdgeWeight; } public int getDistance (Person sta, Person end) { if (sta.equals(end)) return 0 ; Map<Person, Integer> dis = new HashMap <>(); Map<Person, Boolean> vis = new HashMap <>(); Queue<Person> qu = new LinkedList <Person>(); Set<Person> persons = graph.vertices(); for (Person person : persons) { dis.put(person, 0 ); vis.put(person, false ); } vis.remove(sta); vis.put(sta, true ); for (qu.offer(sta); !qu.isEmpty();) { Person person = qu.poll(); for (Map.Entry<Person, Integer> edge : graph.targets(person).entrySet()) { Person target = edge.getKey(); if (!vis.get(target)) { qu.offer(target); vis.remove(target); vis.put(target, true ); dis.remove(target); dis.put(target, dis.get(person) + 1 ); if (target.equals(end)) return dis.get(target); } } } return -1 ; } }
Person类 1 2 3 4 5 6 7 8 9 10 11 public class Person { private final String Name; public Person (String PersonName) { this .Name = PersonName; } public String getName () { return this .Name; } }
客户端main() 1 2 3 4 5 6 7 8 9 10 11 12 13 package poet;import java.io.File;import java.io.IOException;public class Main { public static void main (String[] args) throws IOException { final GraphPoet nimoy = new GraphPoet (new File ("src/P1/poet/mugar-omni-theater.txt" )); final String input = "Test the system." ; System.out.println(input + "\n>>>\n" + nimoy.poem(input)); } }
实验过程中收获的经验和教训