in oop solid object oriented programming design pattern programming refactor ~ read.

Setter and Getter are evil!

In this post we are going to talk about why getter and setter are bad and how to solve it.

What is Getter & Setter?

Getter & Setter are how you use to modify fields in your class. Let's have a look at the following example.

package com.oop;

class Employee {  
  private String name;
  private String address;

  public String getName() {
    return name;
  }

  public String setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public String setaddress(String address) {
    this.address = address;
  }
}

Why are Getter & Setter bad?

An object shouldn't expose its implementation details, here is the reason why. Getter & Setter are doing exactly that. So we have to modify the class itself each time we want to change something since it exposes its implementation details. Imagine somewhere else someone is using the getter and setter of this class, each changes of the class will certainly somehow break the code in other place, which is a violation of Open/Closed principle.

How to solve it then?

We are going to use Builder Patter to solve this problem. The basic idea of this pattern is to delegate the work of building an representation to another class entirely.

Let's have a look at the bad code that exposes itself.

package com.holub;  
import java.io.*;

public class Employee {  
  private String name;
  public Employee(String name) { this.name = name };

  public enum FORMAT {XML, JSON}
  public Employee(String source, FORMAT inputFormat) { /*...*/ }
  public Employee(java.sql.Connection con, int ID) { /*...*/ }

  public void exportAsJSON( Writer out) { /*...*/ }
  public void exportAsXML( Writer out) { /*...*/ }
  public void exportAsSQL( java.sql.Connection out) { /*...*/ }
}

The point of this class is it is so hard to maintain - If I need to add an extra format I need to modify Employee class each time. WE DON'T WANT TO DO THAT CAUSE WE ARE LAZY.

So how to solve this problem?

So we are going to delegate the creation of this object into another class.

Let's look at the modified code.

package com.holub;  
import java.io.*;

public class Employee {  
  private String name;
  public Employee(String name) { this.name = name };

  interface Importer { String fetchName(); }
  interface Exporter { void storeName(String name); }

  public Employee( Importer source){
    name = source.fetchName();
  }

  public void export( Exporter destination ){
    destination.storeName(name);
  }
}

Here we've created two interfaces within Employee class that will be used by the other class that will do the creation of the Employee object.

Let's see how to use it.

package com.holub;  
import java.io.*;

public class Employee {  
  private String name;
  public Employee(String name) { this.name = name };

  interface Importer { String fetchName(); }
  interface Exporter { void storeName(String name); }

  public Employee( Importer source){
    name = source.fetchName();
  }

  public void export( Exporter destination ){
    destination.storeName(name);
  }
}

class JsonImporter implements Employee.Importer {  
  private Reader in;
  public JsonImporter( Reader in){ this.in = in; }
  public String fetchName(){
    return "Well";
  }
}

class XMLImporter implements Employee.Importer {  
  private Reader in;
  public XMLImporter( Reader in ){ this.in = in; }
  public String fetchName(){
    return "Well";
  }
}

class JsonExporter implements Employee.Exporter {  
  private String name;
  public void storeName(String name){this.name = name;}
  @Override public String toString(){
    return "{ \"name\":"\"" + name + "\"}";
  }
}

class XMLExporter implements Employee.Exporter {  
  private String name;
  public void storeName(String name){this.name = name;}
  @Override public String toString(){
    return "<name value=\"" + name + "\">";
  }
}

Here we are using these two interfaces as a medium between Employee class and the delegated classes. The creation of Employee object has been delegated to the other classes. So each time if we want to add a new importer or exporter, we don't need to worry about changing Employee class anymore which is great.

End

Hope you guys have learnt something from this post, and if you have any opinions or ideas please leave it below, thanks!

comments powered by Disqus