软件构造lab2小结

实验感受

面向ADT的编程

面向ADT的编程可以对实际问题进行抽象,提供更好的代码服用能力。
直接面向应用场景编程简单直接,而面向ADT的编程需要更多抽象能力。

泛型的好处

泛型增加了代码的复用性,减少重复代码。可以在不同的软件包和程序中使用同一套代码。
也方便代码的改进和重构。

测试驱动开发的优势

先写测试可以帮助我们去思考需求;任务被分解成了一个个小部分,减轻了负担;测试覆盖完全,有利于提高代码质量。

为ADT撰写specification, invariants, RI, AF的意义

specification既可以表明类的作用,以便将来可以快速读懂代码,又可以在编码使提醒自己应该编写怎样的功能,严格按照预定实现。
在编程的过程中,时刻提醒自己要注意表示泄露等问题,可以减少bug,提高编程效率。

实验目标概述

本次实验训练抽象数据类型(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 并据此设计测试用例。

实验环境配置

使用IntelliJ IDEA创建Maven项目。

实验题目

Poetic Walks

这个问题集的目的是练习设计、测试和实现抽象数据类型。

  • 完善Graph接口类,并运用泛型的思想,拓展为泛型类
  • 实现Graph接口类,以边和点两种方式实现接口
  • 利用实现的Graph类,应用图的思想,实现GraphPoet类。如果输入的文本的两个单词之间存在桥接词,则插入该桥接词;若存在多个单一桥接词,则选取边权重较大者。

测试Graph<String>

测试add():

按照Graph中有的点,Graph中没有的点,不同长度的字符串来测试

测试set():

按照增加边、修改边、删除边的策略来测试。

测试remove():

按照Graph中有的点,Graph中没有的点的策略来测试

测试vertices():

按照空图、有一个点、有多个点的策略来测试

测试source():

按照空图、非空图;target在Graph中存在、Graph中不存在;sources.size()为 0,1,>1的策略来测试

测试targets():

按照空图、非空图;source在Graph中存在、Graph中不存在;targets.size()为 0,1,>1的策略来测试

实现Graph<String>

Edge类:
Edge中定义三个字段,分别代表边的源点,目标点,边权。

private final String source;
private final String target;
private final int weight;

表示不变性:source、target不能为空,权值weight>0
检查表示不变性:

private void checkRep() {
    assert source != null;
    assert target != null;
    assert weight > 0;
}

ConcreteEdgesGraph
字段定义题目已给出:

private final Set<L> vertices = new HashSet<>();
private final List<Edge<L>> edges = new ArrayList<>();
```java

表示不变性:顶点不能为空,顶点不能重复,不能有重边,边的source和target包含于vertices
检查表示不变性:
```java
private void checkRep() {
    for (L v : vertices)
        assert v != null;
    for (int i = 0; i < edges.size(); i++) {
        Edge<L> e1 = edges.get(i);
        assert vertices.contains(e1.getSource());
        assert vertices.contains(e1.getTarget());
        for (int j = i + 1; j < edges.size(); j++) {
            Edge<L> e2 = edges.get(j);
            assert !e1.getSource().equals(e2.getSource()) || !e1.getTarget().equals(e2.getTarget());
        }
    }
}

实现 ConcreteVerticesGraph

定义Vertex类:存储一个顶点和此顶点的所有出边
定义两个私有字段,分别存储顶点的标签和此顶点的出边:

private final L label;
private final Map<L, Integer> targets = new HashMap<>();

表示不变性:label不为null,边权大于0

ConcreteVerticesGraph类:
实现add():
将节点添加至列表中即可

if (findVertex(vertex) == null) {
        vertices.add(new Vertex<>(vertex)); 
        return true;
    }
    return false;

实现remove():
从列表中删除节点即可

Vertex<L> v = findVertex(vertex);
    if (v == null) {
        checkRep();
        return false;
    }
    vertices.remove(v);
    checkRep();
    return true;

实现泛型Graph<L>

将各类型改为泛型类

public class ConcreteEdgesGraph<L> implements Graph<L> 
class Edge<L>
public class ConcreteVerticesGraph<L> implements Graph<L>
class Vertex<L>

各个字段、函数返回值等都作相应修改

Poetic walk

测试GraphPoet

测试策略:

  • graph: 空图、非空图
  • 权值: 1,>1
  • file:空文件、非空文件
实现GraphPoet

实现poem():
逐个读取单词,每两个单词之间插入亲和度最高的bridge单词

while (scanner.hasNext()) {
        String now = scanner.next();
        String bridge = null;
        int maxAffinity = 0;
        for (Map.Entry<String, Integer> entry1 : graph.targets(prev.toLowerCase()).entrySet()) {
            for (Map.Entry<String, Integer> entry2 : graph.targets(entry1.getKey()).entrySet()) {
                if (!entry2.getKey().equals(now)) continue;
                if (entry1.getValue() + entry2.getValue() > maxAffinity) {
                    bridge = entry1.getKey();
                    maxAffinity = entry1.getValue() + entry2.getValue();
                }
            }
        }
        if (bridge != null) sb.append(" ").append(bridge);
        sb.append(" ").append(now);
        prev = now;
    }

Re-implement the Social Network in Lab1

使用本次实验中编写的两种Graph之一重新实现即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值