LoginSignup
14
10

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-03-29

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

わりと何でもありの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文」と記述がありますが、他言語では一般には「節」と表現されます。 

14
10
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10