I set out to make a small project around a bounch of classes that return generators (php 5.5).
The main motivation for the small project was to expand on my TDD journey, fiddle with generators and have a package I could throw on packagist for later use.
The current state of the whole "project" can be found at Github
All tests are green, the methods does what I want. Now I want to refactor as I there is lots of dublication.
/**
* 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();
}
The class also has a method named getOdd (and yes it looks alot like it ;) )
The main dublication is the closures $Generator = function() ...
and the difference is mostly operators such as + - * /
and arguments in the for loop. This is mainly the same in the rest of th class.
I read Dynamic Comparison Operators in PHP and come to the conclusion that there is no native method like compare(...)
Should I make a private/protected method for comparison. If so should I make a new class/function for this? I do not think it belongs in the current class.
Is it something else I am missing, I am unsure on how to DRY this up, in a proper way?
Btw. iknow a getEven, getOdd is kinda silly when i got a getRange With step function, but it is a more general refactoring / pattern question.
Update @github the getEven and getOdd are now removed...