同値性を確認してから条件を書き換えましょう - Fizz Buzz 問題を例に


Fizz Buzz を知らない方はこちらをご覧ください => https://ja.wikipedia.org/wiki/Fizz_Buzz

条件はシンプルに書きたい...

過去に php のモブプログラミングで Fizz Buzz をやったのですが,その中でこんな議論がありました.

「その数が 3 で割り切れる かつ 5 で割り切れる とき Fizz Buzz と出力する」とあるけど, 3 で割り切れて 5 でも割り切れるなら,初めから 3 と 5 を掛けて 15 で割り切れる にした方がよくない?

こうじゃなくて

if ($n % 3 === 0 && $n % 5 === 0) {

こう書いた方がよいと.

if ($n % 15 === 0) {

これは確かに正しいです.コードも見やすくなっていますよね.
でも,この 3 と 5 を 別の数字に変えて遊んでみよう となったらどうでしょう?
4 と 6 の場合は 4 と 6 をかけて 24 で割り切れる にしても良いでしょうか?
答えは NO です. 12 が 4 でも 6 でも割り切れますから.

「2 つの数字が互いに素」 で無ければ結果が破綻する

15 は単に 3 × 5 から導き出されるものではありません.理由は下記の通り:

n を自然数として,

「n が 3 で割り切れる かつ n が 5 で割り切れる」
<=> 「n が 3 の倍数 かつ n が 5 の倍数」
<=> 「n が 3 と 5 の 公倍数
<=> 「n が 『3 と 5 の 最小公倍数』 の倍数」
<=> 「n が 15 の倍数」
<=> 「n が 15 で割り切れる」 (end)

3 と 5 が互いに素であるから最小公倍数がたまたま 3 * 5 になっていたに過ぎないのです.

バグを生み出さないようにするために

今回の Fizz Buzz では 3 と 5 が題材に挙がっていたからスムーズにいきましたが,「割り切る数を後で変えられるようにする」などの拡張性を持たせようとするなら,少し考えなければいけないところです.

コーディングをする際に「この条件,こうすれば簡単じゃん」と思うことがあるかもしれません.でもコードを書き換える前に「変更前と変更後の条件は同値なのか?」という確認作業をしておくことが,テストフェーズに行ってからバグを生み出さないことにもつながると思います.