コーディングポリシー
以下はBEAR.Sundayフレームワーク開発でのコーディング原則をまとめたものです。
ゴール
- クリーン
- ハイパフォーマンス
- No BC break
(柔軟性や拡張性、テスト可能性などは"クリーン"であれば自然に含まれます)
グローバル
- グローバル定数(
define
)の禁止 - スーパーグローバル変数の参照の禁止
- グローバルなサービスロケータの参照の禁止
- グローバルな設定の参照の禁止(prod/devモードなど)
- グローバルなプロパティ参照の禁止(スタティックプロパティ)
- グローバルなメソッド利用の禁止(スタティックメソッド)
依存
- 基本全てDIで
-
new
の禁止 (バリューオブジェクトを除く) - 実クラス名を使ったオブジェクトの取得(factoryメソッドなど)の禁止
- インターフェイスにないメソッドの利用の禁止
- 引数がオブジェクトでパブリックプロパティを使う場合、引数のタイプヒントはインターフェイス禁止。抽象クラスを使う。
-
include_path
依存の禁止 - 抽象クラス以外でのsetterインジェクションの原則禁止。
- composerで依存ライブラリの最小バージョンの指定のみを行う。特定のバージョンにロックしない。
継承
- 実クラスの継承の禁止 (
final
キーワード付加) - 子クラスから親クラスのメソッド利用の禁止
- 抽象クラス以外での
protected
プロパティの禁止。
トレイト
- 原則禁止
- アプリケーションでDIのセッターメソッドのみ
引数、返り値
- 引数の数は4つまで(4も例外的)
- 引数にbool値を使用することを禁止
- スカラー値よりバリューオブジェクトを好む
- 特定の構造を期待する連想配列を使わない
- 返り値の
mixed
を避ける -
null
のデフォルト引数を避ける - クロージャの引数を避ける
構造
- elseの禁止
- ネストのインデントは2つまで
シリアライズ
- オブジェクトはシリアライズ可能に
メトリクス
- 1つのクラスのメソッドの数は10以下
- 1つのクラスのプロパティの数は15以下
- 1メソッドの平均ライン数は10行以下
phpmdのデフォルトそのままです。
CI
- scrutinizer score 10.0
- travis test coverage 99.5%
- phpstan -l max src tests 双方 (CIに含める)
- php-cs-fixer, phpcs src tests 双方 (CIに含める)
OOP
- setter、getterを使わない
- デメテルの法則
- 小さなクラスを好む。
- 早期バリデーション、遅延評価
- サービスにオブジェクトを渡さない。オブジェクトにサービスを渡す。 (XXManagerクラスの禁止)
-
DRY
をあまり重視しすぎない。
原則
- 小さく。迷ったら簡素な方を。
- 言い訳はあとで。まずは取り組んでみる。
- 守るのが難しく見える時、そもそも取り組み方がそれでいいのか再考する。
- 速度を犠牲にする方向で解決することを避ける。
説明
いくつか解説します。
グローバルな設定の参照の禁止
ymlの設定ファイルを直接参照したり、Config(コンテナ)クラスを作ってその値をget
したりしません。必要な値は依存
として注入します。
$foo = Configure::read("foo") // NG
public function __construct($foo)
{
$this->foo = $foo; // OK
}
new
の禁止
バリューオブジェクトなどは除きます。主にサービスオブジェクトの場合です。
$email = new Email('exmaple@example.com'); // OK
$http = new AnnotationReader() // NG
スーパーグローバル変数の直接参照の禁止
Foo::createFromGlobals(); //NG
Foo::create($GLOBALS) // OK
内部でスーパーグローバル変数を直接参照するのではなく依存として渡します。
elseの禁止
コンディションがboolの場合でelse
の状態が1つに特定される場合は構いません。(=三項式はOK)
elseを文字通り「その他」として扱うようなelse
を外します。(しかしその場合はガード節を使ってelse
を簡単に外すことができます)
個別の意味をもたせた連想配列を引数で使わない
例えば引数にarray $location
と渡して$location['x']
、$location['y']
と使用するのではなく$x
, $y
のpublicプロパティを持ったLocation
クラスを用意します。
まとめ
様々なコーディングの原則は時に「現実的ではない」「PHP的ではない」と軽視されることがあります。しかし現在のPHPはこれらのOOP原則に従ったコーディングをする事は十分に可能です。クリーンなコードはむしろ簡素で、IDEやCIツールの利用で開発速度の犠牲も最初です。
クリーンなコードは開発速度やランタイムの実行速度とのトレードオフではないと考えます。
BEAR.Sundayが提供するのは、ライブラリの集合ではなく「フレームワーク」です。実装はその時その時に変化しますが、変わることのないHTTPアプリケーションの構造を継続的な進化と共に提供したいと考えています。ソフトウエアの設計原則に従う事はそのフレームワークを壊すことなく(後方互換性を犠牲にすることなく)進化を続けることを可能にするための土台です。
参考