[英]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约束的情况下可能的最大值”,我们将获得从$index
到PHP_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.