前陣子遇到 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 未必能給你摸到最好的答案,但它給你改變心意的機會。
如果要自動 pad-zero
1 -> 0001
12 -> 0012
123 -> 0123
1234 -> 1234
根本一開始無可能知道係第幾個 digit 去 limit, 除非再加上自動唔 pad-limit;
e.g. "2" can be
12 -> 0012 (0-9)
123 -> 0123 (0-5)
1234 -> 1234 (0-9)
depends which digit it should be
@angusdev 做的個 sample 由 "中間" 開始 input 會好奇怪 (e.g. 1 vs 01)