Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

パラメーターの渡し方とコードの読みやすさ

確かにどうにかしたいですね。


 C++とかJavaで良く見るプログラミングスタイルだが、こうやってひたすら数字だけが並んでいるとやたらと読みにくい。三日後に見たらどのパラメーターが何なのかが思い出せなくて、コンストラクターソースコードを参照せねばならない。

PHPでフツーに(?)考えてみると、以下のような感じでしょうか。

<?php
final class Fish {
    private $properties;
    public function __construct($speed, $direction, $x, $y, $minDistance, $maxInfluence) {
        $this->properties = array();
        $this->properties['speed'] = $speed;
        $this->properties['direction'] = $direction;
        $this->properties['x'] = $x;
        $this->properties['y'] = $y;
        $this->properties['minDistance'] = $minDistance;
        $this->properties['maxInfluence'] = $maxInfluence;
    }
    public function __get($name) {
        if (isset($this->properties[$name])) {
            return $this->properties[$name];
        }
        throw new Exception('property "' . $name . '" dose not exist');
    }
    /**
     * immutable
     */
    public function __set($name, $value) { }

    /**
     * another methods
     */
}

$fish = new Fish(2, 180, 20, 20, 16, 40);

var_dump($fish->direction);

さすがに「4番目の20って何だっけ?」になりますね。あと、コンストラクタが凄いことになるので、こっちの方が面倒かも。。。:-p また、func_num_args/func_get_arg/func_get_argsが使った方が良い場面もありますね。
で、話を戻して、連想配列で渡すとなると、

<?php
final class Fish {
    private $properties;
    public function __construct($params) {
        if (!is_array($params)) {
            throw new Exception('parameter 1 to be array');
        }
        $this->properties = $params;
    }
    public function __get($name) {
        if (isset($this->properties[$name])) {
            return $this->properties[$name];
        }
        throw new Exception('property "' . $name . '" dose not exist');
    }
    /**
     * immutable
     */
    public function __set($name, $value) { }

    /**
     * another methods
     */
}

$fish = new Fish(array("speed" => 2, "direction" => 180, "x" => 20, "y" => 20, "minDistance" => 16, "maxInfluence" => 40));

var_dump($fish->direction);

こんな感じ。呼び出すときのコードが結構大変ですが、「読みやすさ」という見方をすると、結構良いんじゃないでしょうか。まあ、「array」を書く必要がありますが。。。
んじゃあ、JSONで書いたら?ということで書いてみました。動作確認はPHP5.2.2です。

<?php
final class Fish {
    private $properties;
    public function __construct($json) {
        $this->properties = json_decode($json);
        if (is_null($this->properties) || $this->properties === false) {
            throw new Exception('Invalid JSON format : ' . $json);
        }
    }
    public function __get($name) {
        if (isset($this->properties->$name)) {
            return $this->properties->$name;
        }
        throw new Exception('property "' . $name . '" dose not exist');
    }
    /**
     * immutable
     */
    public function __set($name, $value) { }

    /**
     * another methods
     */
}

$fish = new Fish('{"speed":2, "direction":180, "x":20, "y":20, "minDistance":16, "maxInfluence":40}');

var_dump($fish->direction);

んー。。。arrayと比べると「読みやすさ」「コード量」が若干改善されるのかなぁ。微妙だ。。。JSONデータでキー名の「"」を書かなくて良いなら、かなり良い感じなのに。

<?php
$fish = new Fish('{speed:2, direction:180, x:20, y:20, minDistance:16, maxInfluence:40}');

この辺は、PHPに付いてるJSONパーサ*1に依存してるんだろなぁ。コンストラクタのコードにその処理を入れても良いけど。。。
むぅ。「読みやすさ」と「コード量」を改善するうまい方法、他にないですかね?

*1:PHPJSONパーサはRFC4627準拠ではない、みたいな話がPHP-DEVで流れてた