清單 25. 如果沒有調(diào)用 push 調(diào)用 peek,會(huì)怎樣?
public void shouldReturnNullOnPeekWithoutPush() throws Exception{
Ensure.that(stStack.peek(), m.is(null));
}
同樣,不會(huì)感到意外。如清單 26 所示,問題出現(xiàn)了。
清單 26. 沒有可執(zhí)行的內(nèi)容
1) StackBehavior should return null on peek without push:
java.lang.ArrayIndexOutOfBoundsException: -1
修復(fù)這個(gè)缺陷的邏輯類似于 pop() 的邏輯,如清單 27 所示。
清單 27. 這個(gè) peek() 需要做一些修復(fù)
public E peek() {
if(this.list.size() > 0){
return this.list.get(this.list.size()-1);
}else{
return null;
}
}
把我對 Stack 類作出的所有修改和修復(fù)綜合起來,可以得到清單 28 中的代碼。
清單 28. 一個(gè)可正常工作的棧
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 類運(yùn)行 7 種行為,以確保 Stack 類能按照 Linda 的(和我自己的一點(diǎn))規(guī)范運(yùn)行。Stack 類 還可能使用某種重構(gòu)(也許 pop() 方法 應(yīng)該調(diào)用 peek() 進(jìn)行測試,而不是執(zhí)行 size() 檢查?),但是由于一直使用了行為驅(qū)動(dòng)過程,我可以很自信地對代碼作出更改。如果出現(xiàn)了問題,很快可以收到通知。
結(jié)束語
您可能已經(jīng)注意到,本月對行為驅(qū)動(dòng)開發(fā)(BDD)的探索中,Linda 實(shí)際上是客戶。在這里,可以把 Frank 看作開發(fā)人員。如果把這里的領(lǐng)域(即數(shù)據(jù)結(jié)構(gòu))換成其它領(lǐng)域(例如一個(gè)呼叫中心應(yīng)用程序),以上應(yīng)用仍然類似。作為客戶或領(lǐng)域?qū)<业?Linda 指出系統(tǒng)、特性或應(yīng)用程序應(yīng)該 執(zhí)行什么功能,像 Frank 這樣的開發(fā)人員則使用 BDD 確保正確理解了她的要求并實(shí)現(xiàn)這些需求。
對于很多開發(fā)人員來說,從測試驅(qū)動(dòng)開發(fā)轉(zhuǎn)移到 BDD 是明智的轉(zhuǎn)變。 如果采用 BDD,不必考慮測試,而只需注意應(yīng)用程序的需求,并確保應(yīng)用程序的行為執(zhí)行它 應(yīng)該 執(zhí)行的功能,以滿足那些需求。
在這個(gè)例子中,使用 BDD 和 JBehave 使我可以根據(jù) Linda 的說明輕松地實(shí)現(xiàn)一個(gè)可正常工作的棧。通過首先 考慮行為,我只需傾聽她的需求,然后相應(yīng)地構(gòu)建棧。在此過程中,我還發(fā)現(xiàn)了 Linda 沒有提及的關(guān)于棧的其他內(nèi)容。