首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

亲身体验行为驱动开发(4)

亲身体验行为驱动开发(4)

栈的逻辑至此,通过允许传递多个行为方法,我已经实现了 push() 和 pop() 方法。但是我还没有处理栈的实际内容,这是与多个 push() 和 pop() 相关联的逻辑,间或出现一个 peek()。
首先,我将通过 shouldPopSecondPushedValueFirst() 行为确保栈的基本算法(先进先出)无误。
清单 19. 确保典型的栈逻辑
1
2
3
4
5
public void shouldPopSecondPushedValueFirst() throws Exception{
stStack.push("test 1");
stStack.push("test 2");
Ensure.that(stStack.pop(), m.is("test 2"));
}




清单 19 中的代码可以按计划运行,所以我将实现另一个行为方法(在清单 20 中),以确保两次使用 pop() 都能表现出正确的行为。
清单 20. 更深入地查看栈行为
1
2
3
4
5
6
public void shouldPopValuesInReverseOrder() throws Exception{
stStack.push("test 1");
stStack.push("test 2");
Ensure.that(stStack.pop(), m.is("test 2"));
Ensure.that(stStack.pop(), m.is("test 1"));
}




接下来,我要确保 peek() 能按预期运行。正如 Linda 所说,peek() 遵从和 pop() 相同的规则,但是 “应该保留栈顶的项目”。相应地,我在清单 21 中实现了 shouldLeaveValueOnStackAfterPeep() 方法的行为。
清单 21. 确保 peek 保留栈顶的项目
1
2
3
4
5
6
public void shouldLeaveValueOnStackAfterPeep() throws Exception{
stStack.push("test 1");
stStack.push("test 2");
Ensure.that(stStack.peek(), m.is("test 2"));
Ensure.that(stStack.pop(), m.is("test 2"));
}




由于 peek() 还没有定义,因此清单 21 还不能编译。在清单 22 中,我定义了 peek() 的一个最简单的实现。
清单 22. 当前,peek 是必需的
1
2
3
public E peek() {
return null;
}




现在 StackBehavior 类可以编译,但是它仍然不能运行。
清单 23. 返回 null 并不奇怪,对吗?
1
2
3
4
5
1) StackBehavior should leave value on stack after peep:
VerificationException: Expected:
same instance as <test 2>
but got:
null:




在逻辑上,peek() 不会从内部集合中移除 项目,它只是传递指向那个项目的指针。因此,我将对 ArrayList 使用 get() 方法,而不是 remove() 方法,如清单 24 所示。
清单 24. 不要移除它
1
2
3
public E peek() {
return this.list.get(this.list.size()-1);
}




栈为空的情况现在重新运行  中的行为,结果顺利通过。但是,在这样做的过程中发现一个问题:如果栈为空,则 peek() 有怎样的行为?如果说栈为空时调用 pop() 会抛出一个异常,那么 peek()  是否也应该如此?
Linda 对此没有进行解释,所以,显然我需要自己添加新的行为。在清单 25 中,我为 “当之前没有调用 push() 时调用 peek() 会怎样” 这个场景编写了代码。
清单 25. 如果没有调用 push 就调用 peek,会怎样?
1
2
3
public void shouldReturnNullOnPeekWithoutPush() throws Exception{
Ensure.that(stStack.peek(), m.is(null));
}




同样,不会感到意外。如清单 26 所示,问题出现了。
清单 26. 没有可执行的内容
1
2
1) StackBehavior should return null on peek without push:
java.lang.ArrayIndexOutOfBoundsException: -1




修复这个缺陷的逻辑类似于 pop() 的逻辑,如清单 27 所示。
清单 27. 这个 peek() 需要做一些修复
1
2
3
4
5
6
7
public E peek() {
if(this.list.size() > 0){
  return this.list.get(this.list.size()-1);
}else{
  return null;
}
}




把我对 Stack 类作出的所有修改和修复综合起来,可以得到清单 28 中的代码。
清单 28. 一个可正常工作的栈
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
import java.util.ArrayList;

public class Stack<E> {

private ArrayList<E> list;

public Stack() {
  this.list = new ArrayList<E>();
}

public void push(E value) {
  if(value == null){
   throw new RuntimeException("Can't push null");
  }else{
   this.list.add(value);
  }
}

public E pop() {
  if(this.list.size() > 0){
   return this.list.remove(this.list.size()-1);
  }else{
   throw new RuntimeException("Nothing to pop");
  }
}

public E peek() {
  if(this.list.size() > 0){
   return this.list.get(this.list.size()-1);
  }else{
   return null;
  }
}
}




在此,StackBehavior 类运行 7 种行为,以确保 Stack 类能按照   Linda 的(和我自己的一点)规范运行。Stack 类  还可能使用某种重构(也许 pop() 方法  应该调用 peek() 进行测试,而不是执行 size() 检查?),但是由于一直使用了行为驱动过程,我可以很自信地对代码作出更改。如果出现了问题,很快就可以收到通知。
返回列表