1

I was going through refactoring book and couldn't understand these two techniques.

https://refactoring.com/catalog/changeValueToReference.html

And

https://refactoring.com/catalog/changeReferenceToValue.html

Can you please help me understand with an example in Java?

user1298426
  • 3,467
  • 15
  • 50
  • 96
  • https://sourcemaking.com/refactoring/change-value-to-reference and https://sourcemaking.com/refactoring/change-reference-to-value explain why and how to refactor. – hamena314 Jan 12 '18 at 13:17

3 Answers3

3

In it's very simplest form it just means switching between the following two options:

class Order
{
    // constructor etc...
    private String customerName;
    public String getCustomerName() {return customerName;}
}

or

class Customer
{
    // constructor etc...
    private String name;
    public String getName() {return name;}
    public String setName(String name) {this.name = name;}
}

class Order
{
    // constructor etc...
    private Customer customer;
    public String getCustomerName() {return customer.getName();}
}

Now when a customer's name can change, the 2nd solution is prefered, because you don't need to update the customerName member in every order.

However if a customer's name never changes, the 1st solution might be prefered, because you don't need to manage Customer objects somewhere.

Which version you want to chose and if you need to refactor depends on your actual application.

Max Vollmer
  • 8,412
  • 9
  • 28
  • 43
3

Assume you have two Customer objects/instances, customer1 and customer2. They are actually the same customer, with same ID and name. However they were read at different moments from the database or such. A new Customer() was called twice.

Customer customer1 = new Customer(13L);

Customer customer2 = new Customer(13L);

The refactoring would involve a factory method:

Customer customer1 = customerRepository.findById(13L);

Customer customer2 = customerRepository.findById(13L);

Examples of the latter is for instance JPA, an O/R mapping.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
1

Strictly speaking, I'm not sure whether this conversion is possible in Java, since you don't have both references and values of objects in Java - all objects are references (which are passed by value).

However, one can consider this similar to the following example:

"Value":

class Order
{
   private int orderNum;
   private Customer customer;
   Order(int orderNum, String customerString)
   {
      this.orderNum = orderNum;
      this.customer = new Customer(customerString);
   }
}

// elsewhere:
Order order1 = new Order(1, "I am a customer");
Order order2 = new Order(2, "I am a customer");
Order order3 = new Order(3, "I am a customer");
Order order4 = new Order(4, "I am a customer");

Here each Order has it's own Customer object, even when all or most of those Customer objects are the same.

The above is, of course, just an example. Passing all parameters of another object into a constructor is not good design.

Reference:

class Order
{
   private int orderNum;
   private Customer customer;
   Order(int orderNum, Customer customer)
   {
      this.orderNum = orderNum;
      this.customer = customer;
   }
}

Customer customer = new Customer("I am a customer");
Order order1 = new Order(1, customer);
Order order2 = new Order(2, customer);
Order order3 = new Order(3, customer);
Order order4 = new Order(4, customer);

Here we can have a single Customer for many Orders (if we want).

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138