PHPのinterface
を使う場合、__invoke
メソッドを使うことができます。これを使うとメリット・デメリットは何だろう?と~~(どうでもよさそうな)~~ことを考えたので書いてみます。
例えば、
interface DoItInterface {
public function __invoke(): DoneInterface;
}
とします。このinterfaceを実装したDoIt
クラスがあるとすると、こんな風に使えます。
$do = new DoIt();
$done = $do();
ほんのちょっとコードが減ります。便利なような、そうでもないような… メインのメソッドが一つしかない場合に、__invoke
を使うのはメリットはあるのでしょう?
TL;DR
いきなり結論を書くと、interfaceなどで__invoke
は使わないほうがいい、と考えます。
メリット
メソッドの名前を考えなくていい
すでにinterface名で体を表しているのであれば、メソッド名を考えなくてすみます。これは大きい。
callableとして使える
Closureなどと混ぜて使える。
デメリット
クラスのプロパティに使うと残念な感じになる
こういうコードになります。
class DoAll {
/**
* @var DoItInterface
*/
private $doIt;
public function do() {
// $this->doIt(); // <- そのまま呼べない!
$this->doIt->__invoke(); // <- なんか格好悪い!!
}
}
PHP7.2でも、まだ対応できてません。パーサー変えるとき、対応するという話を聞いた記憶がかすかにありますが、まだみたいです。結局__invoke
を使うことになるなら、普通にメソッド名をつけたくなります。
IDEで検索に引っかからない
IDEというか「PhpStorm 2019.1」での話ですが、DoItInterface::__invoke
を「Find Usage」で検索した場合、検索対象になりませんでした。このコードです。
$do(); // <- 検索で出てこない!
これはPHP自体の問題ではないですが、開発から見ると結構大きな問題と思います。リファクタリングするときに修正箇所を見落としたり、自動で修正できないことになります。
この一点だけですが、__invoke
を使わないことにしました。
メソッド名は?
では、メソッドの名前は何がいいのでしょう?
interface名と似た名前を使う
例えばSendMailInterface::send()
のように、インターフェース名と同じような名前を使うことです。インターフェースだけを見ると妙な感じがしますが、クラス名が正しくつけられていれば、問題ないはず… 例えば、$notifyUser->send()
であれば違和感はないです。
英語でよくある言葉を使う
こういうメソッドでよく使われてる動詞を使います。
handle
apply
invoke
-
execute
あるいはexec
do
PHPで「do」は見たことないかも…
ともあれ、インターフェースに合わせて、うまく動詞を選ぶ必要はありそう。
Filter
ならapply
とか。英語のセンスが必要ですね。