PHP で Fizz Buzz 問題の史上最低な解答を考える

はじめに

コードが書けないプログラマ志願者を見分ける手法として有名な FizzBuzz(フィズ・バズ)問題。実務で遭遇したスーパークソコードを参考に、史上最低なリアリティに満ちた筋金入りの失格解答を考えました。誰得なサンプルのソースコードを公開しています。

サンプル

  • GitHub

検証環境

解説

FizzBuzz 問題 とは、2007年頃に流行したコードが書けないプログラマ志願者を見分ける有名な手法です。問題の内容は、1 から 100 までの数を出力する、ただし、数が 3 の倍数のときは「Fizz」、5 の倍数のときは「Buzz」、3 と 5 の倍数のときは「FizzBuzz」と出力するプログラムを書けというものです。

「史上最低」の定義について、他人が最長時間で理解できるコードを史上最低と考えています。コードをただ無闇矢鱈に複雑化するだけでは面白くないので、私が実務で地雷原を潜り抜けている途中に遭遇した低品質で男前なコードを参考に、最高に最低な解答を考えたいと思います。

まずは、よくある解答を書きます。

for ($i = 1; $i <= 100; ++$i) {
  if ($i % 15 === 0) echo 'FizzBuzz';
  elseif ($i % 3 === 0) echo 'Fizz';
  elseif ($i % 5 === 0) echo 'Buzz';
  else echo $i;
}

このコードを叩き台に可読性を下げていきます。

でたらめインデント

インデント(indent)とは、文章の行頭に半角スペース、又はタブを入力して、人間が読みやすいように開始位置をズラすことです。字下げとも言います。

私は実務でインデントに一貫性があるソースコードをあまり見たことがありません、半角スペースとタブの混在による乱射乱撃雨霰は日常茶飯事です。Python のソースコードでさえインデントの数が不規則になっていることがありました

よく動いてたな、いや、よくも動いていたな

この経験を活かして、叩き台のインデントをでたらめに修正しました。

  for ($i = 1; $i <= 100; ++$i) {
    if ($i % 15 === 0) echo 'FizzBuzz';
 elseif ($i % 3 === 0) echo 'Fizz';
   elseif ($i % 5 === 0) echo 'Buzz';
       else echo $i;
     }

でたらめインデントって名前、ロマンシング サ・ガの技にあっても違和感なさそうです。

ぼくのかんがえたさいきょうの if ぶん

私は実務で if 構文 の波括弧に一貫性があるソースコードをあまり見たことがありません。

マニュアル 通りにやるなら下記のように書くでしょう。

if ($a > $b) {
  echo 'aはbより大きい';
} elseif ($a == $b) {
  echo 'aはbと等しい';
} else {
  echo 'aはbより小さい';
}

しかし、こんな書き方をする人がいます。

if ($a > $b){
  echo 'aはbより大きい';
}elseif ($a == $b)
{
  echo 'aはbと等しい';
} else
{
  echo 'aはbより小さい';
}

他にも、こんな書き方をする人もいます。

if ($a > $b)
{
  echo 'aはbより大きい';
}
elseif ($a == $b)
{
  echo 'aはbと等しい';
}
else
{
  echo 'aはbより小さい';
}

こんな書き方をする人まで。

if ($a > $b){echo 'aはbより大きい';}
elseif($a == $b){echo 'aはbと等しい'; }
else {echo 'aはbより小さい';}

なぜ、そのような書き方をしたのか訊ねると、本人曰く、下記のような理由がありました。

  1. 本屋で売ってた中古の参考書にこうやれって書いてあったから。
  2. ググったら検索トップの記事がこうやって書いてあったから。
  3. 俺が見やすいから、他の書き方が間違ってる。
  4. 動いてるからどうでもいいじゃん。
  5. 別案件のソースコードをコピっただけ。
  6. スピードが大事だから!可読性よりスピード、Facebook のザッカーバーグもさぁ〜何よりも重視するのはスピードって言ってただろ、Google のジェフ・ディーンもさぁ〜(ry
  7. こう書けって死んだじっちゃんが言ってた。

死んだじっちゃんは知らんけど、他の理由は実務あるあるですね。誰が悪いとかではなく、色んな企業、又は個人のエンジニアがシステムを開発していると有り勝ちです。

情報は 1 つの情報源を鵜呑みにしないで、複数の情報源から客観的に精査しましょう。

この経験を活かして、叩き台の if 構文を独善的なエンジニア達が描き殴ったように修正しました。

  for ($i = 1; $i <= 100; ++$i) {
    if ($i % 15 === 0)
{echo 'FizzBuzz';
}
 elseif ($i % 3 === 0) {echo 'Fizz';}
   elseif ($i % 5 === 0)
{
echo 'Buzz';
}
       else {echo $i;
  }
     }

すし詰めコード

私は実務で 言語構造(language constructs)、関数(function)、演算子(operator)前後の半角スペースに一貫性があるソースコードをあまり見たことがありません。

この半角スペースには、読み手が言語構造なのか関数なのかを一目でわかるようにするという意味があります。マニュアルから制御構造と関数の書き方を見比べてみてください。

// 言語構造は名前の後ろに半角スペースがある
if ()
while ()
for ()
foreach ()
switch ()
match ()

// 関数は名前の後ろに半角スペースがない
printf()
preg_match()
str_replace()
explode()

また、演算子とオペランドの区別をわかりやすくするという意味もあります。

// 演算子とオペランドの区別がわかりやすい
$a = 1;
$a += 1;
$b = &$a;
$a === $b;
$a <=> $b;
$a ?? $b;

// 演算子とオペランドの区別がわかりにくい
$a=1;
$a+=1;
$b=&$a;
$a===$b;
$a<=>$b;
$a??$b;

しかし、これを無駄であると考える人がいます。C 言語の組み込みであればまだ理解できるのですが、ハードウェアが進歩したこの時代に可読性を捨ててまで半角スペースを排除する必要を私は感じません。

単純に、なぜ半角スペースが書かれているのか全く疑問を持たない人もいます。疑問を持たないから、根拠無しに半角スペースを排除しています。逆もまた然り、必要以上に半角スペースを描く人も疑問を持っていないからです。

半角スペースには、意味があります。

この経験を活かして、叩き台の言語構造、関数、演算子前後の半角スペース有無を無邪気に修正しました。

  for( $i = 1; $i <= 100; ++$i ){
    if ($i%15===0)
{echo     'FizzBuzz';
}
 elseif  (  $i  %  3  ===  0  ) {  echo  'Fizz'  ;  }
   elseif($i%5===0)
 {
echo'Buzz';
}
       else  { echo$i ;
  }
     }

空の変数名

私は実務で変数名に情報を持たせていないソースコードを見ることがよくあります。

例えば、下記のような変数名です。嘘でしょって思いますよね、稀に出現するレア変数名なんすよコレ。

$a=$b=$c;
$変数=&$変数2;
$𓁿;
$👀👀👀;

他にも、同じシステム内で記法がバラバラだったり。

$fizzbuzz;
$fizzBuzz;
$FizzBuzz;
$FIZZBUZZ;
$fizz_buzz;

実は格納する値と名前が一致しない偽名でしたちゃんちゃんってパターンもあります。例えば、$users という変数にユーザー ID が格納されていたりします。

変数に意味を持たせないで、コメントで説明しちゃう人もいます。考え方が逆です、変数名だけで表現できないこと、伝えられないことをコメントにするんです。

// これはユーザーIDです。
$a;
// これはユーザーの名前です。
$b;
// これはユーザーの登録日です。
$c;

読み手のクソコード耐性が高いと変数名なんて無視して読めてしまうのですが、確実に他人の時間を奪うコーディングであることは間違いないです。

変数名には、意味を持たせるようにしましょう。

この経験を活かして叩き台の変数名を意味のない絵文字に修正しました。

  for( $🐊 = 1; $🐊 <= 100; ++$🐊 ){
    if ($🐊%15===0)
{echo     'FizzBuzz';
}
 elseif  (  $🐊  %  3  ===  0  ) {  echo  'Fizz'  ;  }
   elseif($🐊%5===0)
 {
echo'Buzz';
}
       else  { echo$🐊 ;
  }
     }

マジックナンバー(改)

私は実務で マジックナンバー だらけの ハードコーディング 祭りを見ることがあります。

その中で、整数リテラル を特に理由もなく 2, 8, 16 進数表記で記述されていることがあります。アーサーブレイク博士に尋ねても「私にもわからん」と答えるでしょう。

付け焼刃、生兵法といいますか、覚えたことをすぐに使いたかったのかなと思っています。

他人がすぐに理解できないリテラルは定数化するなどして名前を付けてあげましょう。

この経験を活かして、叩き台の 整数リテラル を 2, 8, 16 進数に書き換える修正をしました。

  for( $🐊 = 0x1; $🐊 <= 0144; ++$🐊 ){
    if ($🐊%0b1111===00)
{echo     'FizzBuzz';
}
 elseif  (  $🐊  %  0b11  ===  0_00_000  ) {  echo  'Fizz'  ;  }
   elseif($🐊%0b101===0x0)
 {
echo'Buzz';
}
       else  { echo$🐊 ;
  }
     }

Go To トラブル

私は実務でたま〜に goto が使われているソースコードを見ることがあります。C 言語畑の人が書いたのかな。

goto とは、プログラム中の他の命令にジャンプすることができる演算子です。これは繰り返し文の中で複数レベルの break として使われることがあるのですが、break の引数にループを抜けるレベルを指定できるので、わざわざ goto を使うことはあまりないです。

一番困ったのは、goto で複数のループ処理をしているコードを読むことでした。

goto を積極的に使用するとトラブルの元になるので気を付けましょう。

この経験を活かして叩き台の一部の繰り返し文を goto に書き換える修正をしました。

  $🐊=0x0;ك:if( ++$🐊 <= 0144  ){
    if ($🐊%0b1111===00)
{echo     'FizzBuzz';
}
 elseif  (  $🐊  %  0b11  ===  0_00_000  ) {  echo  'Fizz'  ;  }
   elseif($🐊%0b101===0x0)
 {
echo'Buzz';
}
       else  { echo$🐊 ;
  }
     goto ك;}

ノーコメもありや

私は実務でたくさんのクソコメと出会いました。

デバッグコードや TODO の消し忘れ、内輪ネタや嘘の仕様、アスキーアート、コードでわかることをわざわざ書いてあるコメントなどです。

コメントは、他人にソースコードでは表現できない意図や概要を伝える為に書き残します。

この経験を活かして、叩き台に不必要なコメントを書き残しました。

  $🐊=0x0;ك:if( ++$🐊 <= 0144  ){ // 100 R.I.P.
    if ($🐊%0b1111===00) //ifで判定しています。。。
{echo     'FizzBuzz';
} //TODO:〇〇さん修正よろしく(^_−)−☆
 elseif  (  $🐊  %  0b11  ===  0_00_000  ) {  echo  'Fizz'  ;  }
   elseif($🐊%0b101===0x0)
 {
echo'Buzz';
}//強強打破3つ並べて一気飲みするのジェットストリームアタックって言うの草
       else  { echo$🐊 ;
  }
     goto ك;}//    var_dump($🐊);

デザイナー殺し

私は実務で PHP のループ処理で HTML を何度も何度も連結させてから最後に出力しているコードをよく見ます。

PHP が読めない Web デザイナーにとっては、文書構造がコードから理解できないのでデザイン修正がストレスでしかありません。私はこのような文書構造を無駄に難解にしている人をデザイナー殺しと呼んでいます。

デザイナー殺しの意味を全く理解できない人もいます。Web デザイナーはブラウザのデベロッパーツールを使って修正すれば良いのであって、動的な部分だけを出力する必要はないという考え方です。属性や class の追加とかはどうするんだよと聞いても、そんなの PHP で連結してる文字列を検索すればわかるでしょといった具合です。

まぁ、自分のやり方を意地でも変えたくないってのが本音の場合が多いです。

この経験を活かして、叩き台に無駄な文字列結合をする修正をしました。

 $𓁿=''; $🐊=0x0;ك:if( ++$🐊 <= 0144  ){ // 100 R.I.P.
    if ($🐊%0b1111===00) //ifで判定しています。。。
{     $𓁿.=    "Fizz".'Buzz';
} //TODO:〇〇さん修正よろしく(^_−)−☆
 elseif  (  $🐊  %  0b11  ===  0_00_000  ) {  $𓁿 .='Fizz'  ;  }
   elseif($🐊%0b101===0x0)
 {
$𓁿.= "Buzz";
}//強強打破3つ並べて一気飲みするのジェットストリームアタックって言うの草
       else  { $𓁿.=$🐊 ;
  }
     goto ك;}echo$𓁿;//    var_dump($🐊);

完成です、良い感じに実務でも見るかなってレベルですね。

まとめ

エンジニアの採用試験で FizzBuzz 問題 が出題されてこのゴミクズみたいなコードを提出したら、確実にお祈りメールが届くか連絡がないと思います。或いは、謎に正しく出力されているだけに採用担当者からナメとんのかワレメールが届くかもしれません。

絶対に内定が欲しくない人は、このクソコードのエレクトリカルパレードみたいな解答を提出しましょう。

おわりに

他にも酷いコードにはたくさん出会っていますが、偶さかにこのようなコードを提出しているプログラマー志願者がいるのではないかという加減で止めておきました。

少しでもお楽しみいただけたなら幸いです。