閱讀本文后,希望你能夠有如下收獲:
- 掌握保齡球的計分規(guī)則,下次打球不再迷茫碳柱。
- 通過保齡球的計分系統(tǒng)端到端業(yè)務(wù)功能分析,避免陷入細節(jié)熬芜。
- 通過業(yè)務(wù)抽象產(chǎn)出一份需求任務(wù)列表莲镣,從而指導(dǎo)下一步的TDD。
如若與你期望相符涎拉,歡迎你繼續(xù)閱讀瑞侮!
需求背景
請你設(shè)計一個計算保齡球比賽一局總得分的程序的圆,保齡球的計分規(guī)則如下:
- 每一局總共有十輪,每輪一開始會有十支球瓶区岗,球手可以扔兩次球略板,目標(biāo)就是用盡量少的球把全部球瓶擊倒。
- 如果第一球就把全部的球瓶都擊倒了慈缔,也就是STRIKE叮称,畫面出現(xiàn)“X”,就算完成一輪了藐鹤,所得分數(shù)是10分再加后面兩球的倒瓶數(shù)瓤檐。
- 如果第一球沒有全倒,就要再打一球娱节,如果第二球?qū)⑹O碌那蚱咳紦舻鼓域龋簿褪荢PARE,畫面出現(xiàn)“/”肄满,也算完成一格谴古,所得分數(shù)為10分再加下一輪第一球的倒瓶數(shù)。
- 如果第二球也沒有把球瓶全部擊倒的話稠歉,那分數(shù)就是第一球加第二球倒的瓶數(shù)掰担,沒有獎勵(bonus),再接著打下一輪怒炸。依此類推带饱。
- 第十輪有機會扔三次球。如果在第十輪出現(xiàn)STRIKE或者SPARE阅羹,則球手可再加打第三球勺疼。
- 全部十輪的得分相加就等于這一局的總得分。
上述記分牌建議你逐個數(shù)一下,能夠幫助你理解透徹保齡球的積分規(guī)則导梆,打下良好基礎(chǔ)轨淌。
系統(tǒng)分析
拿到需求后,第一件重要的事情永遠都是理解需求问潭,第二件重要的事情是拆分需求。
通讀業(yè)務(wù)描述婚被,分析出系統(tǒng)要解決的核心業(yè)務(wù)問題是為每一局統(tǒng)計總分狡忙,這就是系統(tǒng)將提供面向用戶的端到端功能。最終的需求分解始終應(yīng)該聚焦在這個點上址芯,要避免陷入某一輪的細節(jié)中灾茁。
每一局游戲又分為10輪窜觉,最終的總分是根據(jù)一局比賽中每輪中每次擊倒的瓶數(shù),按照一定的業(yè)務(wù)與規(guī)則計算出來北专。所以禀挫,為了統(tǒng)計每局結(jié)束后的總分,系統(tǒng)還要能夠記錄每次擊倒瓶數(shù)拓颓,從而為統(tǒng)計總得分提供數(shù)據(jù)语婴。
到此,我們識別出系統(tǒng)需要提供的核心功能是統(tǒng)計總分驶睦,還需要支撐的功能是能夠記錄每次擊球數(shù)砰左。
需求拆分
從需求描述中得到信息,每一輪中的倒瓶數(shù)的規(guī)則會對總分產(chǎn)生不同的影響场航,對于某一輪缠导,有如下幾種場景:
- 某輪中,兩次扔球都沒有碰到球溉痢,所得分數(shù)為0僻造。
- 某輪中,兩次扔球都沒有將球瓶全部擊倒孩饼,所得分數(shù)為兩球的倒瓶數(shù)髓削。
- 某輪中,第一球就把全部的球瓶都擊倒捣辆,STRIKE蔬螟,所得分數(shù)是10分再加后面兩球的倒瓶數(shù)。
- 某輪中汽畴,第二球?qū)⑹O碌娜壳蚱窊舻咕山恚琒PARE,所得分數(shù)為10分再加下一輪第一球的倒瓶數(shù)忍些。
其實場景1是場景2的極端情況鲁猩,我回想起了第一次玩保齡球的時候,就出現(xiàn)過這種情況罢坝,所以我很快就想到了它廓握。
經(jīng)過上述分析,我們將每輪得分規(guī)則分為3大類嘁酿。此時隙券,你可能會問,這只是1輪的4種場景闹司,如果要統(tǒng)計10輪的總得分娱仔,窮舉出來,是不是應(yīng)該得有3^10 = 59049種業(yè)務(wù)場景(一個極端負責(zé)任的QA或許會想辦法去測試這么多場景游桩,此QA能用程序生成測試數(shù)據(jù)~ ~)牲迫。理論上耐朴,這樣窮舉出來的結(jié)果就是現(xiàn)實中真實存在的全部場景。這樣去拆分業(yè)務(wù)需求盹憎,本身是沒有錯的筛峭,但看到這個數(shù)字,還沒有開始寫測試陪每,估計你內(nèi)心就已經(jīng)崩盤了影晓。
英雄難過Tasking關(guān),TDD的踐行顯然無望了奶稠。為了拯救英雄俯艰,我們需要進一步業(yè)務(wù)抽象。多琢磨琢磨锌订,其實10輪只是1輪的重復(fù)竹握,這里說的重復(fù)是計分規(guī)則重復(fù)。比如說:我第1輪打出STRIKE辆飘,和第5輪打出STRIKE計分規(guī)則沒什么區(qū)別啦辐。
通過進一步業(yè)務(wù)抽象,我們可以通過某一輪打出STRIKE來覆蓋包含了STRIKE的場景蜈项,確保了某一輪STRIKE計分準(zhǔn)確芹关,打出2輪、3輪或10輪STRIKE都是一樣的紧卒。同理侥衬,SPARE和其他的場景也一樣。
結(jié)合我們識別出來的系統(tǒng)核心端到端功能 -- 統(tǒng)計每一局的總分跑芳,我們對進行業(yè)務(wù)拆分轴总,得到如下列表:
- 每一輪的兩次扔球都沒有碰到球,所得分數(shù)為0博个。
- 每一輪的兩次扔球都沒有全部擊倒球瓶怀樟,所得分數(shù)為每次扔球的倒瓶數(shù)總和。
- 存在一輪SPARE盆佣,所得分數(shù)為每次扔球的倒瓶數(shù)總和再加SPARE輪后的一球的倒瓶數(shù)往堡。
- 存在一輪STRIKE,所得分數(shù)為每次扔球的倒瓶數(shù)總和再加STRIKE輪后兩球的倒瓶數(shù)共耍。
- 十輪均為STRIKE虑灰,所得分數(shù)300。
你可能會問痹兜,明明需求描述上強調(diào)了第10輪的特殊性穆咐,是不是最起碼要區(qū)分一下前9輪和第10輪。你想到了這一點是非常好的佃蚜,如果你想到了庸娱,盡管添加到你的任務(wù)列表,然后你會得到一個更詳細的任務(wù)列表谐算,繼續(xù)前進就好熟尉。
我解釋一下這里沒有區(qū)分的原因。從業(yè)務(wù)描述上洲脂,第10輪加了這一個特殊的區(qū)分斤儿,正好滿足了:“打出STRIKE,獎勵兩球的倒瓶數(shù)恐锦,打出SPARE往果,就獎勵一球的倒瓶數(shù),都沒打出一铅,就是本身的兩球倒瓶數(shù)”陕贮。所以,這個特殊化恰好跟前九輪保持了一致的業(yè)務(wù)規(guī)則潘飘,應(yīng)用在場景3或4中了肮之。