我在极限编程训练营中用了FizzBuzz这个题目,题目大致需求如下:
你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有N名学生在上课。游戏的规则是:
1. 让所有学生排成一队,然后按顺序报数。
2. 学生报数时,如果所报数字是3的倍数,那么不能说该数字,而要说Fizz;如果所报数字是5的倍数,那么要说Buzz;如果所报数字是第7的倍数,那么要说Whizz。
3. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如3和5的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。
4. 学生报数时,如果所报数字包含了3,那么也不能说该数字,而是要说相应的单词,比如要报13的同学应该说Fizz。
5. 如果数字中包含了3,那么忽略规则2和规则3,比如要报30的同学只报Fizz,不报FizzBuzz。
6. 如果数字中包含了5,那么忽略规则4和规则5,并且忽略被3整除的判定,比如要报35的同学不报Fizz,报BuzzWhizz,其他case自己补齐。
7. 如果数字中包含了7,则忽略被5整除的判定,若同时还包含5,就忽略规则6中忽略被3整除的判定,比如要报75的同学只报Fizz,其他case自己补齐。
拿到需求Tasking,拆出一个这样的任务:
Given 数字不包含3,5,7 且不能被3,5,7整除 When 报数 Then 学生报数字本身
然后翻译成测试代码:
@Test
void should_report_order_self_as_string_when_reporting_given_order_not_mod_by_3_and_5_and_7_and_not_contains_3_and_5_and_7() {
assertThat(FizzBuzzGame.report(1)).isEqualTo("1");
}
不难发现,这个测试名称是真的有点长,袁帅提出一个问题 -- 这个测试命太长了,有这个必要吗?课堂上,于是七嘴八舌讨论起来了,怎么办呢?
- A说:“用注释表示”
- B说:“简化单词,比如string改成str,reporting改为report”
- C说:“3_and_5_and_7改成3_5_7”
- D说:“3_and_5_and_7改成357”
- ......
我问:“命名长了又有什么问题吗?” 突然安静了下来,片刻之后,开始有人说:
- 太长了,超过IDE的显示上限了
- 太长了,读半天才能读完
我接着又问:“你读懂了吗?”,于是有人回答:“读完了能够很快读懂,但总感觉太长了有点别扭。”
我继续问:“别人写的代码让你更快读懂重要,还是你觉得不别扭重要”。好像没人往下接了。
感觉别扭这个事情总是不那么客观。就好比,一个女孩子,其实五官长得很好看,但是你因为知道她是一个小气巴拉、勾心斗角、无比自私的人,你可能不会觉得她漂亮。但如果一个相貌一般,但心地善良、口碑很好、乐于助人的女孩子,恐怕你也会觉得她是美丽的。(别不承认,你的感觉不会受这些因素的影响)
你写的代码能不能然别人看懂就很考验你的功底了。很简单,想想你在看别人的代码,看半天都看不懂,等你看了一天后(一天是个梗)看懂了,才明白他是为了耍酷,用了生僻的语法和简写,你会觉得这个人代码Sense好吗?而另一个人写得代码,你读完之后,基本上很快读懂代码的意图,即便有些单词语法有点小问题,或者行有点长,没换行,你也不会觉得这个人代码Sense差吧。
你写得代码终究是给人阅读的。写多长、怎么写,这背后的可理解性是你首要追求的点,不到迫不得已,你不应该牺牲这个点而去追求华而不实的技巧。就好比你玩王者荣耀,你把英雄的技能和操作技巧搞得再熟练,基础意识很差的话,也只是一场花瓶秀。
有了这个保底基础,你再去思考如何做一些优化工作,比如:
- A说:“用注释表示” -- 画蛇添足,将活文档硬生生的憋死(注释不是代码,代码是活的)
- B说:“简化单词,比如string改成str,reporting改为report” -- 不影响意图传达,有点作用
- C说:“3_and_5_and_7改成3_5_7” -- 基本不影响意图传达,有点作用
- D说:“3_and_5_and_7改成357” -- 意图很容易别理解错,不可取
其实,不管用了什么方式,总是有得必有失的,3_and_5_and_7改成3_5_7,确实缩减了,但是 你仔细思考,中间还是有一点小小的Gap,读者需要接受3_5_7就是表示3_and_5_and_7的意图,但这个代价比较小,而且一旦接受第一个,后面就会自然全盘接受。你觉得这个牺牲还划算,所以做了无可厚非。
留个思考题,我简写成下面的格式,你觉得优、劣分别是什么?
@Test
void should_report_self_as_string_when_reporting_given_common_order) {
assertThat(FizzBuzzGame.report(1)).isEqualTo("1");
}
网友评论