繁体   English   中英

重构比较器/运算符块以提高DRY的性能并降低CRAP级别

[英]Refactoring comparision/operators blocks to DRY up and reduce C.R.A.P level

我开始围绕返回生成器的类(php 5.5)创建一个小项目。

这个小项目的主要动机是在我的TDD旅程中扩展,弄弄发电机,并准备一个可以放在包装上供以后使用的包装。

整个“项目”的当前状态可以在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循环中的参数。 这在其余的班级中基本上是相同的。

我阅读了PHP中的动态比较运算符 ,得出的结论是没有像compare(...)这样的本机方法compare(...)

我应该使用私有/受保护的方法进行比较吗? 如果是这样,我应该为此新建一个类/函数吗? 我认为它不属于当前班级。

我还缺少其他东西吗?我不确定如何以适当的方式将其干燥吗?

顺便说一句。 知道一个getEven,当我得到带有step函数的getRange时,getOdd有点傻,但这是一个更通用的重构/模式问题。

更新 @github的getEven和getOdd现在已被删除...

以下代码尚未经过测试或验证,但是我相信它,至少它显示了删除多个生成器功能的一种可能方法。

在声明自己时,要删除的重复项主要是在generator函数中。 如果您仔细研究一下,可以看到您拥有的每个生成器函数都可以这样编写:

function createGenerator($index, $limit, $step) {
    return function() use($index, $limit, $step) {
        $incrementing = $step > 0;
        for ($i = $index; true; $i += 2 * $step) {
            if (($incrementing && $i <= $limit) || (!$incrementing && $i >= $limit)) {
                yield $i;
            }else {
                break;
            }
        }
    };
}

为了利用这一点,您需要对输入参数做一些魔术,它有助于(至少使它漂亮)定义一些常量。 PHP已经准备好了一个PHP_INT_MAX常量,该常量持有一个整数可能的最大值,但是它没有一个PHP_INT_MIN 因此,我将其定义为一个常量。

define('PHP_INT_MIN', ~PHP_INT_MAX);

现在,让我们看一下函数中的四种情况。

1)无限增加范围

Infinte在这里是一个相当大胆的主张,如果将其更改为“在给定int约束的情况下可能的最大值”,我们将获得从$indexPHP_INT_MAX的有限范围,因此可以通过设置$limit = PHP_INT_MAX; 上述生成器功能将保持不变。

//$limit = PHP_INT_MAX;
createGenerator($index, PHP_INT_MAX, $step);

2)无限减少范围

这里可以再次使用与上述相同的参数,但是要加上负的$step并交换$index$limit

//$index = $limit;
//$limit = PHP_INT_MIN;
//$step *= -1;
createGenerator($limit, PHP_INT_MIN, -1 * $step);

3)预定的下降范围

交换并再次取反。

//$temp = $index;
//$index = $limit;
//$limit = $temp;
//$step *= -1;
createGenerator($limit, $index, -1 * $step);

4)预定范围

好吧,这只是默认情况,其中给出了所有参数。 不需要改变。

createGenerator($index, $limit, $step);

修改后的代码

public function getEven($index = null, $limit = null, $step = 1) {
    // Throws LogicException
    $this->throwExceptionIfAllNulls([$index, $limit]);
    $this->throwExceptionIfInvalidStep($step);

    // Throws InvalidArgumentException
    $this->throwExceptionIfNotNullOrInt([$index, $limit]);

    //Generator function
    function createGenerator($index, $limit, $step) {
        return function() use($index, $limit, $step) {
            $incrementing = $step > 0;
            for ($i = $index; true; $i += 2 * $step) {
                if (($incrementing && $i <= $limit) || (!$incrementing && $i >= $limit)) {
                    yield $i;
                }else {
                    break;
                }
            }
        };
    }
    // infinite increase range
    if (is_int($index) && is_null($limit)) {
        // throw LogicException
        $this->throwExceptionIfodd($index);
        return createGenerator($index, PHP_INT_MAX, $step);
    }
    // infinite decrease range
    elseif (is_int($limit) && is_null($index)) {
        // throws LogicException
        $this->throwExceptionIfodd($limit);
        return createGenerator($limit, PHP_INT_MIN, -1*$step);
    }
    // predetermined range
    else {
        // throws LogicException
        $this->throwExceptionIfodd($index);
        $this->throwExceptionIfodd($limit);

        // decrease
        if ($index >= $limit) {
            return createGenerator($limit, $index, -1 * $step);
        }
        return createGenerator($index, $limit, $step);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM