オープン・クローズドの原則に則ってコードを書こうと思うとResolverクラスをよく使うことになると思います。
PHPerKaigi2018でベストトーク賞を受賞した @hidenorigoto の 「SOLIDの原則ってどんなふうに使うの?」 の最終形態である PHPカンファレンス関西2018で「続・SOLIDの原則ってどんなふうに使うの? オープン・クローズドの原則 センパイのコーディングノート編」 の発表中には IF文禁止ギブス なる言葉も飛び出しました
つまり、コードを書いていてIF分岐したくなった箇所はinterfaceに外出ししたうえで、Resolverで解決して使うことができるというわけです。
そのResolverクラスをPhpStormで楽に書くためのコードテンプレを作ったのでシェアします。
設定方法
Preferences
→ Editor
→ File and Code Templates
→ File
→ +
で新しいテンプレートを追加。
- Name: 任意。
PHP ResolverClass
とか - Extension:
.php
(さすがにイマドキ.inc
の人はいないと思いたいですが、いればそうしても良いかと)
テンプレートの内容
<?php
namespace ${NAMESPACE};
#set($TARGET=$NAME.replace('Resolver', ''))
#set($VARNAME_START = $TARGET.substring(0,1).toLowerCase())
#set($VARNAME_REST = $TARGET.substring(1))
#set($VARNAME=$VARNAME_START + $VARNAME_REST)
#set($PROPERTYNAME=$VARNAME + 's')
class ${NAME}
{
/**
* @var ${TARGET}Interface[]
*/
private ${DS}${PROPERTYNAME} = [];
public function add${TARGET}(${TARGET}Interface ${DS}${VARNAME})
{
${DS}this->${PROPERTYNAME}[] = ${DS}${VARNAME};
return ${DS}this;
}
public function resolve(${DS}target)
{
foreach (${DS}this->$PROPERTYNAME as ${DS}${VARNAME}) {
if (${DS}${VARNAME}->supports(${DS}target)) {
return ${DS}${VARNAME};
}
}
throw new \LogicException('No $TARGET defined');
}
}
OK を押します。
使い方
Resolverクラスを作りたいディレクトリのコンテキストメニューを開き、 New
→ PHP Class
を選びます。
いつもの新規クラス作成画面ですが、 Template
で先ほど追加した PHP ResolverClass
が選べるようになっているので、これを選びます。
Nameに Resolverクラス名 を指定してOKします。
テンプレからResolverクラスが自動で作られました。
あとは実際にFooInterfaceを書いて、FooInterface::supports() の引数に合わせてresolve($target)をちょちょっと調整すればResolverクラスが完成です。
楽ですね!