我着手围绕一组返回生成器的类(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 循环中的运算符+ - * /
和参数。这在其余班级中基本相同。
我阅读了 PHP 中的动态比较运算符,得出的结论是没有像这样的本地方法compare(...)
我是否应该使用私有/受保护的方法进行比较。如果是这样,我应该为此创建一个新的类/函数吗?我认为它不属于当前班级。
我还缺少其他东西吗,我不确定如何以适当的方式将其干燥?
顺便提一句。知道一个 getEven,当我得到一个带有 step 函数的 getRange 时,getOdd 有点傻,但这是一个更一般的重构/模式问题。
更新 @github,getEven 和 getOdd 现在已被删除...