Renumber Index Variable

An index variable starts at a non-standard value, causing confusion or requiring repetitive arithmetic.

Renumber the index variable to start at the standard value.

Before:

for (int i = 2; i < maxItems + 2; i++)
{
doSomething(i-2);
if (i < 10)
doSomethingElse(i-2);
println(i*i + 0.75 * i + 6);
}

After:

for (int i = 0; i < maxItems; i++)
{
doSomething(i);
if (i < 8)
doSomethingElse(i);
println(calcSomething(i+2);
}

Motivation:

Sometimes, the index of a loop is obviously not what it should be. Obvious signs are:

With this refactoring, you can quickly and safely change the index.

[Other refactorings should exist to handle changing an index passed into a method (RenumberIndexParameter), and changing the way a data structure is indexed (RenumberDataStructureIndex).]

Mechanics:

Example:

Before:

for (int i = 2; i < maxItems + 2; i++)
{
doSomething(i-2);
if (i < 10)
doSomethingElse(i-2);
println(i*i + 0.75 * i + 6);
}

During:

for (int i = 2; i < maxItems + 2; i++)
{
int j = i-2;
doSomething(j+2-2);
if (j+2 < 10)
doSomethingElse(j+2-2);
println((j+2)*(j+2) + 0.75 * (j+2) + 6);
}
for (int j+2 = 2; j+2 < maxItems + 2; j+2++)
{
doSomething(j+2-2);
if (j+2 < 10)
doSomethingElse(j+2-2);
println((j+2)*(j+2) + 0.75 * (j+2) + 6);
}

After:

int calcSomething(int i)
{
return (i+2)*(i+2) + 0.75 * (i+2) + 6;
}
...
for (int j = 0; j < maxItems; j++)
{
doSomething(j);
if (j < 8)
doSomethingElse(j);
println((j+2)*(j+2) + 0.75 * (j+2) + 6);
// ^^^ candidate for ExtractMethod: println(calcSomething(j+2));
}

All the examples above stayed with integer arithmetic, at least. This is what you must never do:

// Lousy trapezoidal rule implementation.
double delta = (b - a) / n;
double sum = 0.0;
for (double x = a; x <= b; x+= delta) {
coeff = ((x == a) || (x == b)) ? 1 : 2;
sum += f(x) * coeff;
}
return sum / (2.0 * n);

How many times will the loop be executed? Who knows? You cannot depend upon the values of x to be anything in particular. a + delta + delta + delta won't be the same as a + 3 * delta. Never use floating-point numbers to index a loop. Better is:

double delta = (b - a) / n;
double sum = f(a) + f(b); // Avoid figuring out coefficients.
for (int i = 1; i < n; ++i) {
x = a + i * delta;
sum += 2.0 * f(x);
}
return sum / (2.0 * n);

Perhaps you should use SimpsonsRule instead.


See also RefactorMatchLoopToUsage


CategoryRefactoring