Monday, December 5, 2011

Reducing Extract Method on a Reduce Loop

Let's say you have code like this, wherein totalYs is being used for multiple purposes, including accumulate the Y values within the collection of Xs.


int totalYs = ...;
Collection<X> xs = ...;
... something that uses totalYs ...

for (X x : xs ) {
    totalYs += x.getY();

}
...
process(totalYs);


You can start isolating the Y accumulation (to extract to a method) by introducing a temporary variable.



int totalYs = ...; 

Collection<X> xs = ...;
...

int tmpTotalYs = 0;
for (X x : xs ) {
    totalYs += x.getY();

}
totalYs += tmpTotalYs;
...
process(totalYs);



Then, replace all instances of totalYs within the loop:




int totalYs = ...;
Collection<X> xs = ...;
...

int tmpTotalYs = 0;
for (X x : xs ) {
    tmpTotalYs += x.getY();
}

totalYs += tmpTotalYs;
...
process(totalYs);


Finally, you can extract your method easily, and inline the temporary variable:


int totalYs = ...; 

Collection<X> xs = ...;
...

totalYs += collectYs(xs);
...
process(totalYs);


Now, totalYs is much easier to manipulate. The lure of this transformation is that tests will pass at every step.

BTW, this will work for any associative operation with an identity value in place of addition.

Chris