Quantcast
Channel: Experiences Unlimited
Viewing all articles
Browse latest Browse all 168

Getting rid of Getters and Setters in your POJO

$
0
0

We all have read in Java books about encapsulation of fields in Java class and also when ever you code you are asked to take special care in encapsulating the fields and providing explicit Getters and Setters. And these are very strict instructions. Lets step back a bit and find out the reason behind encapsulating the fields. Its all done to have a control over the access and modification of the fields. One might want to allow the user of the class to access data from only few fields or control the update of data of the fields in the class and so on. And on other occassions the frameworks would need these getters and setters to populate your POJOs(Plain Old Java Objects).

Now the pain involved in adding these getters and setters is quite a bit and this pain has been reduced by the IDEs which allow you to generate the getters and setters for the fields. But these generated code make your class definition very verbose and hide the actual business logic, if any, which you might have it inside the class definition. There have been lot of ways by which you can get away with defining the getters and setters explicitly and I have even blogged about using Project Lombok to use annotations to declare the getters and setters. I have come across another approach to avoid defining the getters and setters and this approach doesn’t even auto generate the code or use annotations to define them. I am sure I have read this approach somewhere but unable to recall, so its something which has been used and I am trying to create an awareness among my readers about this approach via this blog post.

Let me first define the class with the getters and setters and then show how to get rid of them

class TaskWithGettersSetters {
  public TaskWithGettersSetters(String title, String notes,
      LocalDateTime deadline, String assignedTo) {
    this.title = title;
    this.notes = notes;
    this.addedOn = LocalDateTime.now();
    this.deadline = deadline;
    this.assignedTo = assignedTo;
  }

  public TaskWithGettersSetters() {
  }

  private String        title;
  private String        notes;
  private LocalDateTime addedOn;
  private LocalDateTime deadline;
  private String        assignedTo;

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public String getNotes() {
    return notes;
  }

  public void setNotes(String notes) {
    this.notes = notes;
  }

  public LocalDateTime getAddedOn() {
    return addedOn;
  }

  public void setAddedOn(LocalDateTime addedOn) {
    this.addedOn = addedOn;
  }

  public LocalDateTime getDeadline() {
    return deadline;
  }

  public void setDeadline(LocalDateTime deadline) {
    this.deadline = deadline;
  }

  public String getAssignedTo() {
    return assignedTo;
  }

  public void setAssignedTo(String assignedTo) {
    this.assignedTo = assignedTo;
  }

}

There is nothing to explain in the above code, pretty clear with fields being private and public getters and setters. The class definition is about 60 lines. Let see how we can define class without providing getters and setters:

class Task {

  public Task(String title, String notes, LocalDateTime deadline,
      String assignedTo) {
    this.title = title;
    this.notes = notes;
    this.addedOn = LocalDateTime.now();
    this.deadline = deadline;
    this.assignedTo = assignedTo;
  }

  public final String        title;
  public final String        notes;
  public final LocalDateTime addedOn;
  public final LocalDateTime deadline;
  public final String        assignedTo;

}

The above is what I call class definition on diet :) It is less verbose and is just 18 lines. You must be scared looking at the public modifiers for the fields and also confused looking at the final modifiers to the field. Let me explain the ideology behind this approach:

  1. As the fields are final they cannot be modified after initialized so we need not worry about the scare of data in the field getting modified. And we have to provide a constructor which will initialize these fields, otherwise compiler will shout at you for not understanding what final modifier is.
  2. The data in the fields can be accessed by using the fields directly and not via the getter methods.
  3. This approach enforces immutability of objects i.e if we have to update the field we have to create a new object with the updated value of the field.

Now having Immutable objects provides lots of advantages few of them being:

  • Writing concurrent code is quite easy because we need not worry about getting locks on the object as we are never going to modify the object, we can just read the object data and cannot modify due to the use of final.
  • Immutable objects leads to having lot of short lived objects which helps in reducing the GC overhead involved in managing long lived objects and objects with lot of live references.

We can even provide a factory method for creating instances of Task. Lets see the above class in action:

import java.time.LocalDateTime;

public class GettingRidOfGettersSettersDemo {
  public static void main(String[] args) {
    //One can make use of Factory method to initialize the data
    Task task1 = new Task("Task 1", "some notes", LocalDateTime.now().plusDays(5), "sana");
    //Very clean approach to access the field data - no getYYY() noise 
    System.out.println(task1.title + " assigned to " + task1.assignedTo);
    Task task2  = new Task("Task 2", "some notes", LocalDateTime.now().plusDays(6), "raj");
    System.out.println(task2.title + " assigned to " + task2.assignedTo);
  }
}

Viewing all articles
Browse latest Browse all 168

Trending Articles