1

Suppose I have the following requirements:

  • We organize books by author first name, this might change in the future.
  • When ever an Author we carry at our store releases a new book, the Authors previous works are discounted at the managers discretion(i.e 10% 15%).
  • Storage is done in an SQLite database with the appropriate tables.

    Author - AuthorID, Authorfirstname, AuthorLastname

    Book - BookID, Title, Price

    BookswithAuthors - BookswithAuthorsID, BookID, AuthorID

From Effective Java:

Provide programmatic access to all the information contained in the value returned by the toString()

When are Getters and Setters Justified

For my examples, I'm using immutable classes, so any setters will return a new object reflecting the change.

public final class Author{

    private final String id;
    private final String firstname;
    private final String lastname;

    //Constructor 
}

ID is simply used to avoid conflicts where two authors share the same first and last name.

Given the advice in the above link, the accepted answer states:

Having getters and setters does not in itself break encapsulation. What does break encapsulation is having a getter and a setter for every data member (every field, in java lingo).

Problem 1: With all that in mind, what if, following Effect Java's advice, I have to expose all the fields with a getter because all the fields are in the toString()?

Given the above requirement about Book organization, I could eleminate the use of getters for the first and last name and do this:

public String printAuthorbylastname(){}
public String printAuthorbyfirstname(){}

However to store in my database, I have to call ID, first and last name individually.

To handle the rule about discounts, I can do this:

public final class Book{

    private String bookID;
    private final String title;
    private List<Authors> authorsList;
    private double price;
    //Constructor
}
//return a new Book reflecting the price change.
public Book updatePrice(double price){}

In keeping with the SRP, my Book and Author classes shouldn't be aware of the database backend, or any elements used to display(ex. textbox, or Jtable). This means providing getters(to all the fields in my case) to insert it into the database or display in a GUI.

From researching I've come to the following conclusions about what developers believe about Getters/Setters:

  • Avoid entirely
  • It's okay, as long as there is a justifiable reason.
  • For display purposes, its fine, don't use getters to gather data and perform a calculation outside of the class, when it should be done inside.

Problem 2: How do you balance the guidelines given that there vastly different?

Problem 3: Suppose you choose to avoid getters/setter entirely, how then would you display the data about an object in a GUI? If you were to pass a component used to display to anyone of the classes, doesn't this violate SRP?

  • 5
    It took me awhile to find a complete quote for the assertion that you should "provide programmatic access to all the information contained in the value returned by the toString() method. It says: "This removes the temptation of programmers who use your class to parse the result of toString to gain access to this information." Frankly, I don't find that statement compelling; adding getters so that programmers won't be tempted to do the wrong thing with ToString() does break encapsulation. – Robert Harvey Oct 8 '17 at 19:24
5

Encapsulation is a technique. Like any other software development technique, you use it when you need the benefits that it offers.

The purpose of a getter or setter is to get or set some state in a class; that should be self-evident. What is less clear is why you would provide "empty" getters or setters, methods that provide nothing more than bare access to a private member of the class. Why not just make the private member public instead?

There are several valid reasons:

  1. The class may be a "data only" class (i.e. a DTO), so there is no logic to encapsulate.
  2. The architecture might require getters and setters. Javabeans is like this.
  3. Getters and setters can act as placeholders, allowing access to the internal member while still allowing for future business logic to be added.
  4. Changing from a public member to a getter/setter pair (so that you can add business logic) is generally a binary breaking change. You can't do it without disrupting clients.

  5. You're using procedural programming (for example in C, where you don't have classes but merely data structures).

Encapsulation provides the best benefits when it shields both private state and internal logic. If a class is merely a data container, the benefits of encapsulation (if any) are less obvious, since the whole point of such a data container is to provide access to the data it contains.

If you're writing a class that implements behavior, you should provide public methods that expose behavior, not data. Tell, don't ask.

  • So if my classes are data only classes for example Author, or even Book, providing a getter for the first and last name(creating a getter for all fields) is justifiable in this case? – user285272 Oct 8 '17 at 19:45
  • Sure, if your software requirements necessitate it. – Robert Harvey Oct 8 '17 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy