前言
FizzBuzz 大概是最广为人知的程序设计题目之一,它的题目是这样的:
- 打印出
1
到100
的数字- 假如数字是
3
的倍数,则打印Fizz
- 假如数字是
5
的倍数,则打印Buzz
- 假如数字是
3
和5
的公倍数,则打印FizzBuzz
- 假如数字是
解题
基本解
最直接的解法即是制作一个函数会打印 1 ~ 100
的数字,并依照规则判断是否要打印 Fizz
、Buzz
或 FizzBuzz
。但明显这样的做法会将所有数值都写死在程序当中,未来要扩充条件时就需要修改代码,尚不够灵活。
分离数据与逻辑
既然可以预期规则都是 某数字
要打印 某结果
那么或许可以使用对象来记录这些 Key-Value 结构的数据:
数据是抽离出来了,但逻辑还是依赖指定 map
对象当中的特定内容,让我们再写个循环自动的将 map
对象的内容取出来,让数据来驱动逻辑:
保持数值不变(Immutable)
以上解法可以观察到目前定义了 i
以及 output
两个变量并且于程序中持续的变动其内容,在某些程序开发风格当中会被视为应当避免的习惯,我们可以尝试看看将覆盖变量的部分改为纯粹函数。
补齐文档与检查边界案例
JavaScript 是动态类型语言,因此其他人在使用这个函数时可能不清楚具体参数的需求,这里通过 JSDoc 来补齐文档,也可以考虑使用 TypeScript 来检测类型或于 Runtime 进行类型检测:
通过局部应用来简化 numberReplacer
你可能会想说:老天!只是要印个 FizzBuzz
为什么每次都要通过 numberReplacer
来计算?有没有办法单纯创个函数只传入最大值就好?就像一开始一样?让我们用局部应用函数来通过创造抽象达成简化:
在这次解题过程中我贯彻 DRY 原则,并且通过不断的重构来提升代码的可读性与可维护性,但也可以思考真的有必要制造更多抽象吗?过早的优化是万恶之源,或许 YAGNI。