清单 25. 如果没有调用 push 调用 peek,会怎样?
public void shouldReturnNullOnPeekWithoutPush() throws Exception{
Ensure.that(stStack.peek(), m.is(null));
}
同样,不会感到意外。如清单 26 所示,问题出现了。
清单 26. 没有可执行的内容
1) StackBehavior should return null on peek without push:
java.lang.ArrayIndexOutOfBoundsException: -1
修复这个缺陷的逻辑类似于 pop() 的逻辑,如清单 27 所示。
清单 27. 这个 peek() 需要做一些修复
public E peek() {
if(this.list.size() > 0){
return this.list.get(this.list.size()-1);
}else{
return null;
}
}
把我对 Stack 类作出的所有修改和修复综合起来,可以得到清单 28 中的代码。
清单 28. 一个可正常工作的栈
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() 检查?),但是由于一直使用了行为驱动过程,我可以很自信地对代码作出更改。如果出现了问题,很快可以收到通知。
结束语
您可能已经注意到,本月对行为驱动开发(BDD)的探索中,Linda 实际上是客户。在这里,可以把 Frank 看作开发人员。如果把这里的领域(即数据结构)换成其它领域(例如一个呼叫中心应用程序),以上应用仍然类似。作为客户或领域专家的 Linda 指出系统、特性或应用程序应该 执行什么功能,像 Frank 这样的开发人员则使用 BDD 确保正确理解了她的要求并实现这些需求。
对于很多开发人员来说,从测试驱动开发转移到 BDD 是明智的转变。 如果采用 BDD,不必考虑测试,而只需注意应用程序的需求,并确保应用程序的行为执行它 应该 执行的功能,以满足那些需求。
在这个例子中,使用 BDD 和 JBehave 使我可以根据 Linda 的说明轻松地实现一个可正常工作的栈。通过首先 考虑行为,我只需倾听她的需求,然后相应地构建栈。在此过程中,我还发现了 Linda 没有提及的关于栈的其他内容。