私は社内/社外のメンバーに対してコードレビューをする立場にいます。
レビューではつい細かいところまで見てしまうタイプなので、社内ではちょっと怖がられているかもしれません😈
今日はレビューでしょっちゅう指摘している内容の中から、メソッドの引数・戻り値について紹介します。
例はPHPですが動的言語であれば概ね共通する筈です。
コード例
たとえばこんなコードがレビュー対象になったとします。
public function someMethod($date, $obj, $options)
{
// (略)
}
こういうコードには必ず型をつけろと指摘します。
PHPは手抜きして書きやすいという特徴があり(これは長所でもある)、PHP5までは型ヒントも貧弱でした。
そのため、PHPエンジニアは型を軽視する傾向があったと思います。
PHPは型の自動変換が効くため一見ゆるく見えますが、実際には内部で厳密な型が存在します。
つまり、型の管理をエンジニア自身が責任を持って行う必要があるのです。
こうしたPHPで型に関する情報がないとメソッドに何を渡せばよいか、何が返ってくるか作った本人以外は全く分からずコードを詳細に追っていかなければならないんですよね。
改善1 型を付ける
まずは型を付けましょう。
public function someMethod(\DateTimeInterface $date, Sample $obj, array $options): array
{
// (略)
}
ダメな型の付け方
なぜか型ヒントに object や mixed を使う人がいます。
public function someMethod($date, object $obj, mixed $options): array
{
// (略)
}
これを指定されても一体どんなものを渡せばよいのか分からず全くヒントになりません。
mixed なんて何も書いてないのと同じです。
大抵は具体的な型にできるはずです。
docコメント
当然docコメントも書いて欲しいわけですが・・・
/**
* @param \DateTimeInterface $date
* @param Sample $obj
* @param array $options
* @return array
*/
public function someMethod(\DateTimeInterface $date, Sample $obj, array $options): array
{
// (略)
}
型情報だけをdocコメントに書いても、メソッド定義と重複してしまいます。
さらに引数や戻り値を変更したとき、コメントの更新を忘れて実装と不一致になるとかえって混乱の元になります。
書くなら説明まで書きましょう。これなら書く価値があります。
/**
* @param \DateTimeInterface $date この日付以降を対象とする(時刻は無視する)
改善2 arrayの内容を明確に
PHPは配列が便利すぎます。このため配列でデータ構造を作りがちなのですが、引数・戻り値仕様に array とだけ書かれていてもどんな配列か分かりません。配列の内容が分かるようにしましょう。
/**
* @param array{'limit':int, 'page':int} $options
* @return HogeItem[]
*/
public function someMethod(\DateTimeInterface $date, Sample $obj, array $options): array
{
// (略)
}
ちなみにこのような連想配列の記法(array{'limit':int, 'page':int})は phpdoc のリファレンスには載っていませんが、 Psalm や PHPStan などの静的解析ツールがサポートしている形式です。
vscode など一部のエディタでは補完も効きます。
まとめ
引数や戻り値の型を明示するだけで、コードの読みやすさ・保守性は大きく向上します。
「何を渡せばいいのか」「何が返ってくるのか」がすぐに分かるだけで、実装もレビューも圧倒的にスムーズになります。
PHPは柔軟な言語だからこそ、型情報を積極的に書いて他人にも未来の自分にもやさしいコードを心がけましょう。