1

ジェネレーターを返す一連のクラス (php 5.5) を中心に小さなプロジェクトを作成することに着手しました。

この小さなプロジェクトの主な動機は、TDD の旅を拡張し、ジェネレーターをいじり、後で使用するために packagist に投げることができるパッケージを用意することでした。

「プロジェクト」全体の現状はGithubで確認できます

すべてのテストは緑色で、メソッドは私が望むことを行います。重複が多いので、リファクタリングしたいと思います。

    /**
    *   Returns a Generator with a even range.
    *
    *   getEven(10); // 10,12,14,16,18,20,22 ...
    *   getEven(null, 10); // 10,8,6,4,2,0,-2,-4 ...
    *   getEven(10, null, 2); // 10,6,2, -2 ...
    *   getEven(10,20); // 10,12,14,16,18,20
    *   getEven(20,10); // 20,18,16,14,12,10
    *   getEven(10,20,2); // 10,14,18
    *
    *   @param int|null $start
    *   @param int|null $end
    *   @param int $step
    *   @throws InvalidArgumentException|LogicException
    *   @return Generator
    */
    public function getEven( $start = null, $end = null, $step = 1 )
    {
        // Throws LogicException
        $this->throwExceptionIfAllNulls( [$start, $end] );
        $this->throwExceptionIfInvalidStep($step);

        // Throws InvalidArgumentException
        $this->throwExceptionIfNotNullOrInt( [$start, $end] );

        // infinite increase range
        if(is_int($start) && is_null($end))
        {
            // throw LogicException
            $this->throwExceptionIfOdd($start);

            $Generator = function() use ($start, $step)
            {
                for($i = $start; true; $i += $step * 2)
                {
                    yield $i;
                }
            };
        }
        // infinite decrease range
        elseif(is_int($end) && is_null($start))
        {
            // throws LogicException
            $this->throwExceptionIfUneven($end);

            $Generator =  function() use ($end, $step)
            {
                for($i = $end; true; $i -= $step * 2)
                {
                    yield $i;
                }
            };
        }
        // predetermined range
        else 
        {
            // throws LogicException
            $this->throwExceptionIfUneven($start);
            $this->throwExceptionIfUneven($end);

            // decrease
            if($start >= $end)
            {
                $Generator = function() use ($start, $end, $step)
                {
                    for($i = $start; $i >= $end; $i -= $step * 2)
                    {
                        yield $i;
                    }
                };
            }
            // increase
            else
            {
                $Generator = function() use ($start, $end, $step)
                {
                    for($i = $start; $i <= $end; $i += $step * 2)
                    {
                        yield $i;
                    }
                };
            }
        }

        return $Generator();
    }

このクラスには getOdd という名前のメソッドもあります (そして、そうです ;) )

主な重複はクロージャー$Generator = function() ...であり、違いは主+ - * /に for ループ内の and 引数などの演算子です。これは、クラスの残りの部分でも主に同じです。

PHP で動的比較演算子を読んだところ、次のようなネイティブ メソッドは存在しないという結論に達しました。compare(...)

比較のためにプライベート/保護されたメソッドを作成する必要があります。もしそうなら、私はこれのために新しいクラス/関数を作るべきですか? 私はそれが現在のクラスに属しているとは思わない。

これを適切な方法で乾燥させる方法がわかりません。

ところで。getEven を知っていますが、getRange With step 関数を取得したときの getOdd はちょっとばかげていますが、それはより一般的なリファクタリング/パターンの質問です。

@github を更新 して getEven と getOdd を削除しました...

4

1 に答える 1