名称未設定

[Tips] PHP それ、無名関数(クロージャー)を使った方がイケてるよ

#プログラミング , #tips , #php , #リファクタリング

この記事のきっかけ

Web言語を扱ってると下記のような記述をよく見かけます。

template/hoge.php

<html>
    <head>
    </head>
    <body>
        <div>
<?php
// hogehogeの時
if (GLOBAL_CONST_VALUE_1 === $value
        || GLOBAL_CONST_VALUE_2 === $value
        || GLOBAL_CONST_VALUE_3 === $value ) 
    echo 'hogehoge の時の出力' . PHP_EOL;
?>
        </div>

        <!-- そのたhtmlの記述 -->

        <div>
<?php
// hogehogeの時
if (GLOBAL_CONST_VALUE_1 === $value
        || GLOBAL_CONST_VALUE_2 === $value
        || GLOBAL_CONST_VALUE_3 === $value ) 
    echo 'hogehoge の時の出力' . PHP_EOL;
?>
        </div>
    </body>
</html>

実装者としては

・このテンプレートでしか発生しない分岐処理
・状態を判定するメソッドを作るまでもない or めんどくさい
・Helperを作るまでもない or めんどくさい
・関数定義すると名前空間を汚してしまう

などなどあるのでしょうけど、私は正直イケてないと感じます。

理想は、利用しているフレームワークにEntityクラスのようなものがあるなら、状態を判定するメソッド作りましょう。

Entityクラスを使った例

model/HogeEntity.php

<?php
class HogeEntity {
    private $__value;
    public function isHogehoge() {
        if (GLOBAL_CONST_VALUE_1 === $this->getValue()) 
            return true;

        if (GLOBAL_CONST_VALUE_2 === $this->getValue()) 
            return true;

        if (GLOBAL_CONST_VALUE_3 === $this->getValue()) 
            return true;

        return false;
    }

    public function getValue() {
        return $this->__value;
    }
}

template/hoge.php

<html>
    <head>
    </head>
    <body>
        <div>
<?php
if ($entity->isHogehoge()) 
    echo 'hogehoge の時の出力' . PHP_EOL;
?>
        </div>

        <!-- そのたhtmlの記述 -->

        <div>
<?php
if ($entity->isHogehoge()) 
    echo 'hogehoge の時の出力' . PHP_EOL;
?>
        </div>
    </body>
</html>

メソッド(もしくは関数)を定義するメリットは

・メソッド名(もしくは関数名)を見れば、おおよその機能を把握できる
・仕様変更・バグ対応などによる修正コストを低くできる
・可読性が上がる

などが挙げられます。

本題

とはいえ、再利用性が明らかに低く手っ取り早く作りたい気持ちもわかります。

そんな時は無名関数(クロージャー)を検討してみましょう。
PHPマニュアル:無名関数 

無名関数を使った例

template/hoge.php

<?php
$isHogehoge = function () use ($value) {
    if (GLOBAL_CONST_VALUE_1 === $value)
        return true;

    if (GLOBAL_CONST_VALUE_2 === $value)
        return true;

    if (GLOBAL_CONST_VALUE_3 === $value)
        return true;

    return false;
};
?>
<html>
    <head>
    </head>
    <body>
        <div>
<?php
if ($isHogehoge())
    echo 'hogehoge の時の出力' . PHP_EOL;
?>
        </div>

        <!-- そのたhtmlの記述 -->

        <div>
<?php
if ($isHogehoge())
    echo 'hogehoge の時の出力' . PHP_EOL;
?>
        </div>
    </body>
</html>

通常のユーザ定義関数ではなく無名関数を使うメリットは

・名前空間を汚さない
・スコープが限定される

などが挙げられます。

ただし、無名関数はテストコードを作りづらいというデメリットもあり、TDDを採用している現場では多用すると毛嫌いされるかもしれません。

なお、仕様変更により無名関数で定義した処理が他でも使われるようになった場合は、クラスへのメソッド定義やHelperへの実装を検討しましょう。

コード品質を意識した良いプログラミングライフを!


この記事が気に入ったらサポートをしてみませんか?