PSR-2に準拠した PHP コードを書いてみて気づいたこと

PSR-2に準拠した PHP コードを書いてみて気づいたこと

実写版『ど根性ガエル』のピョン吉に声を当てているのが満島ひかりだといまだに信じられない kagata です。おととしのお気に入りだった『泣くな、はらちゃん』と同じ脚本・演出陣だそうで、今回も期待しています。

さて、最近ある開発プロジェクトでコーディング規約に PSR-2を導入しました。自分やチームのコーディングスタイルを改めて見直すと、いろいろと発見があるものです。今回はそういったいろいろの気づきについてご紹介します。

PSR-2とは、というか PSR とは

PSR-2 とは PHP の数あるコーディング規約の中でも現代の標準とされるもので…といちから解説しようかと思いましたが、すでにすばらしい解説がありました。規約の原文やその日本語訳もご参照ください。

PSR-0, 1, 2を日本語に翻訳してみました | 株式会社インフィニットループ技術ブログ

手っ取り早く概要をつかみたい方には、上の記事にも貼ってあるこちらのスライドがおすすめです。

現在ではロガーのインターフェイスに関する規約を定める PSR-3PSR-0にとってかわる PSR-4HTTP メッセージの取り扱いを定める PSR-7が追加されています。また、PSR-4の追加に伴って PSR-0は非推奨となりました。

PSR-3~7の概要については次の記事が参考になります。

気づいたこと

さて、冒頭にも書いたとおり、ある長く続く開発プロジェクトで PSR-2をコーディング規約として採用することになりました。「採用する」というのは、これまで口約束や慣習で成り立ってきたものを明文化されたものに置き換えるという意味と、PHP_CodeSniffer を使って規約が守られているかきちんと検査するという意味を含んでいます。

機械的にきっちり検査されながらひとつのコーディング規約を守ってみると、いろいろな気づきがありました。以下では規約のうち特に気になった項目と、そこから気づいたことをご紹介します。

行の長さ

PSR-2では行の長さをソフトリミット120字とし、80字以内におさまるようすすめています。

The soft limit on line length MUST be 120 characters; automated style checkers MUST warn but MUST NOT error at the soft limit.

Lines SHOULD NOT be longer than 80 characters; lines longer than that SHOULD be split into multiple subsequent lines of no more than 80 characters each.

たまにこの制限が厳しいなーと感じることがあるのですが、そういうときはだいたいネストが深くなっています。行の長さをおさえること自体でコードが読みやすくなるというよりは、読みやすいコードを書けば自然にそのくらいにおさまるという感じがしています。

また、PhpStorm で開発しているとシンボル名の補完が効くので、近ごろは長くて説明的なシンボル名をつけがちになっていました。あまり名前が長すぎるのも考え物だよ、という戒めの意味もあるかもしれません。

アクセス修飾子をつける

アクセス修飾子( public とか private とか)は必ずつけましょう。

Visibility MUST be declared on all properties.

PHP ではアクセス修飾子を省略したプロパティやメソッドは public 扱いになります。でも、ただ省略してあると「そうする意図があって public 」なのか「単に付け忘れた、深く考えてなかった」のか、書いた人の意図が読めなくなるんですよね。長くメンテするコードでは、開発者の意図をのちの人に伝える情報は特に大事になります。

さらに、「深く考えてなかった」のほうに関してはカプセル化に意識をはらうよう習慣づける効果ももちろんあるでしょう。

あと、 var は禁止です。

The var keyword MUST NOT be used to declare a property.

PHP4の名残で現在もサポートされてはいますが、アクセス修飾子を必ずつけるなら var を書くことはなくなりますね。PHP5から始めたわたしには var を書く習慣がもともとなかったのですが、古くからメンテされているようなプロダクトコードではいまだに見かけることがあってドキッとします。

アンダースコアで始まる名前

PSR-2の項目でいちばん意外だったのはここです。 private であることを示すためにプロパティ名をアンダースコアで始めてはいけないことになっています。

Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.

また、メソッド名も同様です。

Method names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.

private なときはアンダースコアで始める癖がすっかりついてしまっていたので、最初は少し戸惑いました。でも、これって考えてみたらハンガリアン記法なんですよね。古いコードをいじっていると、 public function _doSomething() なんていう public にしたいんだか private にしたいんだかよくわからない記述に時おり出くわします。確かに、やめたほうが罠は少なくなりそうです。

そして、思えばこの癖がついたのは コントローラのメソッド名をアンダースコアで始めると自動的に private になるという CakePHP の仕様がきっかけでした。この仕様も、最新の CakePHP3では廃止されています

引数の初期値

PSR-2には、初期値を持つ引数は引数リストの最後に置かなければならない…という記述があります。

Method arguments with default values MUST go at the end of the argument list.

でもそれ、コーディング規約というより PHP という言語自体の仕様なんじゃないの?

Note that when using default arguments, any defaults should be on the right side of any non-default arguments

と思いましたが、これを破ったコードを動かしたからといってエラーにはならないんですよね。これまた古いコードで時々見つけては「うっ」となるポイントです。

else if より elseif

else if じゃなくて elseif を使いましょう。 ifelse も1単語なんだから、それにあわせるということで。

The keyword elseif SHOULD be used instead of else if so that all control keywords look like single words.

PHP では else ifelseif も同じだから、あとは見た目で合わせておきましょうということですね…とマニュアルを見ていたら、実は微妙に違うという話を見つけました。

When using a colon to define your if/elseif conditions, you must not separate else if into two words, or PHP will fail with a parse error.

波括弧でブロックを囲むのではなくコロンをつかうときは例外的に、 else if でなく elseif を使わないとパースエラーになるんですね。それならもう elseif を常に使うことにしたほうが、確かによさそうです。

意図的に break しない switch 文

switch 文の中でわざと break させないときは、その旨をコメントしておかないといけません。

There MUST be a comment such as // no break when fall-through is intentional in a non-empty case body.

これもアクセス修飾子の話と同様、わざと break していないのか忘れているだけなのかが将来読む人に伝わるようにということですね。

もっとも、わざと break させない switch 文を書くメリットがある例がいまいち思い浮かばないような気はします。もっと言えば、古いコードに出てくる switch 文は決まって何かしらの負債がたまってて、とても読めたものじゃなくなってたりするんですよね…。個人的には可変関数とかポリモーフィズムとかディスパッチテーブルを使うほうが好きです。

変数名は自由

この項目だけは PSR-2ではなく PSR-1からの引用です:

変数名は StudlyCaps や camelCase や under_score など、とくにどれかをおすすめすることはしません。

This guide intentionally avoids any recommendation regarding the use of $StudlyCaps, $camelCase, or $under_score property names.

ただ、クラスの中でとかメソッドの中でとか、適当な範囲でそろえておきましょうね。

Whatever naming convention is used SHOULD be applied consistently within a reasonable scope. That scope may be vendor-level, package-level, class-level, or method-level.

このあたりをどうするかは PHP に限らずコーディング規約では最初に議論の的になりそうな話題ですが、意外にも PSR では何も決めていません。ごちゃまぜにさえしなければどれでもいいんじゃない…という、ただそれだけです。

どれのほうが読みやすい・メンテしやすいとも一概に言えず、パフォーマンスにも影響しなさそうだし、議論したところで好みの問題とか宗教論争になっちゃいそうなのであえてこうした、ということでしょうか。

なお、クラス名は必ず StudlyCaps 、クラス定数名は必ずすべて大文字のアンダースコアつなぎ、メソッド名は必ず camelCase とそれぞれ定められています。

Class names MUST be declared in StudlyCaps.

Class constants MUST be declared in all upper case with underscore separators.

Method names MUST be declared in camelCase().

変数名はなんでもいいのに、こっちはどうして決まりがあるんでしょうね?

まとめ

PHP のコーディング規約 PSR-2の中から特に気になった項目と、実際にそれを守ってみて気がついたことをまとめました。

全体に、将来読む人にコードに意図を伝えたり、設計で考えるべきことを考えさせたり、良い習慣につながる規約としてできあがっていて、ただのスタイルの好みのすりあわせだけにとどまらない規約になっているという印象です。これまでとくにコーディング規約を定めてこなかったプロジェクトでも、導入するといろいろいいことがあるのではないでしょうか。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ