Pau Chorro Pau Chorro - 2 months ago 9
C# Question

Refactoring: Replace Method with Method Object explanation

I was looking for refactoring a too length method. Searching I found this technique: Replace Method with Method Object but I don't understand at all.

If the method to refactor is:

public class Order {
//Method to refactor
public double price() {
double primaryBasePrice;
double secondaryBasePrice;
double tertiaryBasePrice;

//compute impl
}

//.....
}


With the web example the refactor Replace Method with Method Object would be as next:

public class Order {

//Method refactored
public double price() {
return new PriceCalculator(this).compute();
}
//.......
}

//Method object
public class PriceCalculator {
private double primaryBasePrice;
private double secondaryBasePrice;
private double tertiaryBasePrice;

public PriceCalculator(Order order) {
//??
}

public double compute() {
// impl
}
}


But how
PriceCalculator
gets
primaryBasePrice
,
secondaryBasePrice
,
tertiaryBasePrice
values to do the compute?

I only see it is possible passing the values in the constructor as next:

//Method object
public class PriceCalculator {
private double primaryBasePrice;
private double secondaryBasePrice;
private double tertiaryBasePrice;

public PriceCalculator(Order order, double primaryBasePrice,
double secondaryBasePrice, double tertiaryBasePrice) {
this.primaryBasePrice = primaryBasePrice;
this.secondaryBasePrice = secondaryBasePrice;
this.tertiaryBasePrice = tertiaryBasePrice;
}

public double compute() {
// impl
}
}


Otherwise, why pass in the constructor
order
instance reference? Why is needed?


  • Passing instance of
    order
    :

    return new PriceCalculator(this, primaryBasePrice, secondaryBasePrice, tertiaryBasePrice).compute();

  • Without
    order
    instance reference:

    return new PriceCalculator(primaryBasePrice, secondaryBasePrice, tertiaryBasePrice).compute();


Answer

But how PriceCalculator gets primaryBasePrice, secondaryBasePrice, tertiaryBasePrice values to do the compute?

The same way it was before refactoring.

If you look at the original code, primaryBasePrice, secondaryBasePrice and tertiaryBasePrice are local variables, whose values are being set somewhere in the //compute impl section.

  public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

     // compute impl
     // all base price variables are assigned somewhere in here
  }

After refactoring, the compute() method has a copy of the //compute impl code, and simply assigns the exact same values to the fields in PriceCalculator as it did to the local variables before refactoring.

We need to pass in a reference to the Order object in case those values are dependent on its methods or internal state.

For instance, if we previously had

public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

    // some of compute impl
    primaryBasePrice = getPrimary();
    secondaryBasePrice = getSecondary();
    tertiaryBasePrice = getTertiary();
    // the rest of compute impl
}

after refactoring, we would instead have something like

public double compute() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

    // some of compute impl
    primaryBasePrice = order.getPrimary();
    secondaryBasePrice = order.getSecondary();
    tertiaryBasePrice = order.getTertiary();
    // the rest of compute impl
}
Comments