皆さん、なんでswitch文のcaseをインデントするんですか?

この記事は最終更新日から1年以上が経過しています。

お断り: この記事の内容は、所属先の見解ではありません。

わりと何でもありのPHP界隈ですが、長年その状態を放置してきたため様々なスタイルのコードが存在することになり、PEARのようにまともにメンテナンスされてないコードを生み出してしましました。
さすがに何かしらの標準が必要では? ということで、PHP-FIGという組織がPHPに関するコーディングスタイル、autoload仕様、インターフェイス仕様を決めており、事実上の標準になっています。

PHP-FIG発足とほぼ同時に制定されたPSR-1, PSR-2はコーディングスタイルに関する標準で、PSR-1が基本的な内容、PSR-2がそれに追加してカッコの位置、スペースの入れ方、インデントのとりかたなど細かい内容になっています。

PSR-1は誰でも割りと受け入れられやすい内容だとは思いますが、PSR-2はコーディングスタイルに深く踏み込んでるので、人によっては異論があると思います。

特に個人的に受け入れがたいのが2つあります。1つ目は

制御構造の開始時は、その後に1スペースを開けなければなりません。メソッドや関数の呼び出しはスペースを開けてはいけません。1

というものです。

つまり、ifforwhiledoswitchとその次のカッコとの間にスペースを入れろ。というものですね。

PSR-2-NG
if($var == "abc"){
}
PSR-2-OK
if ($var == "abc") {
}

スペースを入れる必然性がよくわかりません。実際のコードではスペースを入れるほうがむしろ少数派のように思えます。なんでわざわざスペースを置くことを決めたんでしょうか? 別にそこまで決めなくても良かったのではないかと思います。

そして、もう1つ。こちらが本題。

switch制御は下記のようになります。 括弧、スペースの位置に注意してください。 case文はswitchからインデントし、break(またはその他の終端キーワード)は、case内本文と同じレベルのインデントで揃えなければなりません。 また意図的に処理スルーさせる場合は「// no break」等、コメントしなければなりません。

という部分です。case節はswitch文からインデントしろ。と言ってるわけですね。

PSR-2-NG
switch($var){
case 'A':
    break;
case 'B':
    break;
case 'C':
    break;
default:
}
PSR-2-OK
switch ($var) {
    case 'A':
        break;
    case 'B':
        break;
    case 'C':
        break;
    default:
}

こちらについては、PSR-2のスタイルのほうが一般的なスタイルだとは思いますが、個人的に書くコードでは断固caseをインデントしないスタイルを取っています。

なぜか。caseをインデントするとインデントは(制御構文における)分岐の範囲を表すものである。という原則を壊してしまうからです。

先程のコードを例に取ります。

PSR-2-NG
switch($var){
case 'A':
    break;
case 'B':
    break;
case 'C':
    break;
default:
}

このswitch文によって分岐された各パターンがcase節で表記されているわけであって、switch文の結果がcase節によってさらに分岐されるわけではありません。

このことは、ifelse ifelse構文で書き換えてみればすぐにわかります。

こうすると、わかりやすいでしょ?
if($var == 'A'){

} else if($var == 'B'){

} else if($var == 'C'){

} else {

}

ほら、見比べてみるとcase節をインデントしない方が自然に見えませんか?

さらにcase節をインデントするスタイルだとswitch文の中にswitch文を置いた場合、一番内側のcaseが3インデント分深くなってしまい、ますます分岐のネストとインデントのネストが乖離してしまいます。2

多段switchすると更にわけわかめ…
switch($foo){
    case: 'A'
        switch($bar){
            case 'a':
                break;
            case 'b':
                break;
        }
        break;
}

caseは文ではなく節であり3goto用の)ラベルに近い存在であるということ考えても、インデントしないほうが自然なんですけど、なんでインデントするとしてしまったのでしょう?

さて、ここで問います。「皆さん、なんでswitch文のcase節をインデントするんですか?」

追記: 「その定義だと、何もしない{}もインデントするなってことになるような。」とコメントを頂いたので、「(制御構文における)」という前提を追加しました。


  1. 日本語訳はこちらから引用。 

  2. もっともswitch文の中にswitch文を置くこと自体がアンチパターンであって、リファクタリングされるべきです。 

  3. PHPのマニュアルには「case文」と記述がありますが、他言語では一般には「節」と表現されます。 

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
コメント
この記事にコメントはありません。
あなたもコメントしてみませんか :)
すでにアカウントを持っている方は
ユーザーは見つかりませんでした