How to avoid getters and setters

Nageswaran picture Nageswaran · Feb 23, 2012 · Viewed 15.5k times · Source

I have read in many places that "getters and setters are evil". And I understood why so. But I don't know how to avoid them completely. Say Item is a class that has information about item name, qty, price etc... and ItemList is a class, which has a list of Items. To find the grand total:

int grandTotal()
{
int total = 0;

for (Item item: itemList)
       total += item.getPrice();

return total;
}

In the above case, how does one avoid getPrice()? The Item class provides getName, setName, etc....

How do I avoid them?

Answer

Jonathan Fingland picture Jonathan Fingland · Feb 23, 2012

When should you use getters and setters?

Getters and setters are great for configuring or determining the configuration of a class, or retrieving data from a model

Getting the price of an item is an entirely reasonable use of a getter. That is data that needs to be available and may involve special considerations to protect the data by adding validation or sanitization to the setter.

You can also provide getters without setters. They do not have to come in pairs.

When shouldn't you use getters and setters?

Sometimes objects rely on internal properties that will never be exposed. For example, Iterators and internal collections. Exposing the internal collection could have dramatically negative and unexpected consequences.

Also, for example, let's say you are communicating via some HttpURLConnection. Exposing the setter for your HttpURLConnection means that you could end up with a very odd state should the connection be changed while waiting to receive data. This connection is something that should be created on instantiation or entirely managed internally.

Summary

If you have data that is for all intents and purposes public, but needs to be managed: use getters and setters.

If you have data that needs to be retrieved but under no circumstances should ever be changed: use a getter but not a setter.

If you have data that needs to be set for internal purposes and should never be publicly exposed (and cannot be set at instantiation): use a setter but not a getter (setter presumably prevents a second call affecting the internal property)

If you have something that is entirely internal and no other class needs to access it or change it directly, then use neither.

Don't forget that setters and getters can be private and even for internally managed properties, having a setter that manages the property may be desirable. For example, taking a connection string and passing it to the setter for HttpURLConnection.

Also note:

Allen Holub's article Why getter and setter methods are evil seems to be the source of OP's reasoning but, in my opinion, the article does a poor job of explaining its point.

Edit: Added summary
Edit 2: spelling corrections