Image

Imagetrajano wrote in Imagejava_dev

Move getter logic to constructor

public String getId() {
  return data.substring(0,4);
}

|
v

private final String id;
public DataAdapter(String data) {
  this.id = initId();
}
public String getId() {
  return id;
}


Motivation


Sometimes when one part of an object is accessed, it has to access everything. And sometimes the value does not change after it is calculated once.



Also construction of an object is generally synchronized, most languages do not allow any methods from accessing a new object while it is being constructed.



Mechanics

  1. Determine a getter that needs to be refactored.

  2. Create a new private final field in the class with the return type of the getter.

  3. Extract method from the getter into a new private initialization method. In delegating the logic in the getter method to another method. Do not just rename the method as it would impact existing classes that call the method.

  4. Test.
  5. In the constructor assign the new field with the result of the initialization method.

  6. Change the getter to return the new field rather than calling the initialization method.

  7. Test.



Example

Before refactoring.


public class DataAdapter {
  private final String data;
  public DataAdapter(String data) {
    this.data = data;
  }
  private String getId() {
    return data.substring(0,4);
  }
  private String getName() {
    return data.substring(5,10);
  }
}


After refactoring


public class DataAdapter {
  private final String data;
  private final String id;
  private final String name;
  public DataAdapter(String data) {
    this.data = data;
    this.id = initId();
    this.name = initName();
  }
  public String getId() {
    return id;
  }
  public String getName() {
    return name;
  }
  private String initId() {
    return data.substring(0,4);
  }
  private String initName() {
    return data.substring(5,10);
  }
}

Notes


You can perform lazy initialization rather than doing this method if not all the objects are normally needed. However, most lazy initialization algorithms are not threadsafe and putting synchronize blocks is too expensive at runtime. You can use the Adapter pattern to wrap objects including other adapters if you need to do heavy calculation.