前陣子遇到 UI 上有要求做個 Time picker 有以下要求:
遇上一題:在一個時間輸入有 0-9 鍵,在每輸入一鍵時就必需廢下一個輸入時用不用的鍵。例,輸入 2 時廢 6-9 鍵,輸入 1 時不用廢鍵,輸入 16 時廢 6-9 鍵。時間格式支持 24 小時制,並加可限制最大最小可入時間。暫時想不到很乾淨的寫法。
— Jacky (@jackysee) March 29, 2014
這個要求要處理很多特殊 cases,如:
- 2 –> 可以是 23:50 或 2:59 –> 可按 0-5
- 15 –> 可以是 1:39 或 13:59 –> 可按 0-9
- 16 –> 可以是 16:59 –> 可按 0-5
如果再加可設定最大最小就更麻煩。
起初的想法是先用 regexp 先對好時間格式,然後才處理可按甚麼的問題。 @angusdev 做的這個 sample 就用這個方法,不過就未有最大最小的限制。
我想不到很好的寫法,就讓 unit test 去 drive,寫 jasmine test case:
var testData = [
{input:'', min:'', max:'', expect:[0,9]},
//...
];
testData.forEach(function(d){
it("should expect time input:"+d.input+
" min:"+d.min+" max:"+d.max+
" to have "+d.expect.toString()+"",
function(){
expect($scope.expectTimeKeys(d.input, d.min, d.max))
.toEqual(d.expect);
});
});
(我在用 angular 所以見到
$scope
, 不過沒差啦..)
在一路加入 test case 的情況下,我漸漸寫出了一些類似計算數字進位的東西,有點像樣了 (見這 plunker )。可是到了後期,越加 test case 卻變得越難改動,程式有點彊化。
我想像到日後如果發現有 bug 我可能很難才找到問題所在,所以決定砍掉重練好了。新的想法是先用暴力發窮舉所有可能性,再在當中 filter 好了。因為已發展了一堆 test case 出來,就整個 test case 抄出來,重新寫過。結果是這個 plunker 。用暴力法的好處是比較易明,但會有效能考慮,我自己測試下在當代 browser 強勁的 js 執行力下,其實也足夠快了。
當中教訓是:TDD 未必能給你摸到最好的答案,但它給你改變心意的機會。