Home:ALL Converter>How to avoid getters and setters

How to avoid getters and setters

Ask Time:2012-02-23T23:40:46         Author:Nageswaran

Json Formatter

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?

Author:Nageswaran,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/9416245/how-to-avoid-getters-and-setters
CurtainDog :

How to avoid getters and setters? Design classes that actually act upon the data they hold.\n\nGetters lie about the data anyway. In the Item.getPrice() example, I can see I'm getting an int. But is the price in dollars or cents? Does it include tax(es)? What if I want to know the price in a different country or state, can I still use getPrice()?\n\nYes, this might be beyond the scope of what the system is designed to do, and yes, you might just end up returning a variable's value from your method, but advertising that implementation detail by using a getter weakens your API.",
2013-03-09T00:06:07
dhimes :

'Evil' as .getAttention()\n\nThis has been discussed often, and even perhaps went a bit viral, as a result of the pejorative term \"Evil\" used in the dialog. There are times when you need them, of course. But the problem is using them correctly. You see, Professor Holub's rant isn't about what your code is doing now, but about boxing yourself in so that change in the future is painful and error prone.\n\nIn fact, all I have read by him carries this as its theme.\n\nHow does that theme apply to the class Item?\n\nA look at the future of Item\n\nHere is fictions's item class:\n\nclass Item{\n private double price;\n\n public void setPrice(final double price){\n if(isValidPrice(price))\n this.price = price;\n else throw new IllegalArgumentException(price+\" is not valid!\");\n }\n\n public double getPrice(){\n return this.price;\n }\n }\n\n\nThis is all well and good- but it is still 'Evil' in the sense that it could cause you a lot of grief in the future.\n\nThe grief is apt to come from the fact that one day 'price' may have to take different currencies into account (and perhaps even more complex barter schemes). By setting price to be a double, any code that is written between now and the 'apocalypse' (we're talking evil, after all) will be wiring price to a double.\n\nIt is much better (even Good, perhaps) to pass in a Price object instead of a double. By doing so you can easily implement changes to what you mean by 'price' without breaking the existing interfaces.\n\nThe takeaway on getters and setters\n\nIf you find yourself using getters and setters on simple types, make sure you consider possible future changes to the interface. There is a very good chance you shouldn't be. Are you using setName(String name)? You should consider setName(IdentityObject id) or even setIdentity(IdentityObject id) in case other identification models show up (avatars, keys, whatever). Sure you can always go around and setAvatar and setKey on everything, but by using an object in your method signature you make it easier to extend in the future to the objects that can use the new identity properties and not break the legacy objects.",
2014-10-02T21:11:56
GhostCat again on strike :

A different perspective that is missing here so far: getters and setters invite to violate the Tell Don't Ask principle!\n\nImagine you go shopping in the supermarket. In the end, the cashier wants money from you. The getter/setter approach is: you hand over your purse to the cashier, the cashier counts the money in your purse, takes the money you owe, and gives back the purse. \n\nIs that how you do things in reality? Not at all. In the real world, you typically don't care about the internal state of \"autonomous\" other \"objects\". The cashier tells you: \"your bill is 5,85 USD\". Then you pay. How you do that is up to you, the only thing the cashier wants/needs is he receives that amount of money from your side.\n\nThus: you avoid getters and setters by thinking in terms of behavior, not in terms of state. Getters/setters manipulate state, from the \"outside\" (by doing avail = purse.getAvailableMoney() and purse.setAvailableMoney(avail - 5.85). Instead, you want to call person.makePayment(5.85). ",
2019-03-14T09:45:01
Alex Bitek :

How to avoid getters and setters in Java?\nUse Project Lombok",
2012-02-24T16:28:23
Jonathan Fingland :

When should you use getters and setters?\nGetters and setters are great for configuring or determining the configuration of a class, or retrieving data from a model\nGetting 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.\nYou can also provide getters without setters. They do not have to come in pairs.\nWhen shouldn't you use getters and setters?\nSometimes 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.\nAlso, 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.\nSummary\nIf you have data that is for all intents and purposes public, but needs to be managed: use getters and setters.\nIf you have data that needs to be retrieved but under no circumstances should ever be changed: use a getter but not a setter.\nIf 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)\nIf you have something that is entirely internal and no other class needs to access it or change it directly, then use neither.\nDon'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.\nAlso note:\nAllen 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.\nEdit: Added summary\nEdit 2: spelling corrections",
2012-02-23T17:35:00
Joshua Adriel :

Cloudanger answer is is one, but you must also realize that the item list will likely contain many item objects with quantity ordered on it.\n\nSolution : create another class in between them that stores your item in the item list and the qty ordered for that item (Let's say the class is called OrderLine).\n\nOrderLine will have Item and qty as fields.\n\nAfter that, code something like calculateTotal(int qty) in Item which return price*qty.\nCreate a method in OrderLine that call calculateTotal(qtyOrdered)\n\nPass the return value to the itemList.\n\nThis way, you avoid getters.\nThe ItemList will only know the total price.\nYour code should live with your data.\nAsk the Object who has the data to calculate the totalPrice instead of asking that object for raw data to calculate your totalPrice.",
2014-09-23T23:40:02
Finglas :

It's a shame to see a small, vocal minority take a back lash against the whole \"Getters and Setters\" are evil debate. Firstly the article title is purposely provocative to draw you in, as should any blog post. I've in turn blogged about this before and several years later updated my opinions and ideas about this question. I'll summarise the best I can here.\n\n\nGetters and setters (accessors) are not evil\nThey are \"evil\" (unnecessary) most of the time however\nEncapsulation is not just adding accessors around private fields to control change, after all there is no benefit to added get/set methods that just modify a private field\nYou should write as much code as possible with the principle of \"Tell, Don't Ask\"\nYou need to use accessors for framework code, DTOs, serialisation and so forth. Don't try to fight this.\nYou want your core domain logic (business objects) to be as property free as possible however. You should tell objects to do stuff, not check their internal state at will.\n\n\nIf you have a load of accessors you essentially violate encapsulation. For example:\n\nclass Employee\n{\n public decimal Salary { get; set; }\n\n // Methods with behaviour...\n}\n\n\nThis is a crap domain object, because I can do this:\n\nme.Salary = 100000000.00;\n\n\nThis may be a simple example, but as anyone who works in a professional environment can attest to, if there is some code that is public people will make use of it. It would not be wrong for a developer to see this and start adding loads of checks around the codebase using the Salary to decide what do with the Employee.\n\nA better object would be:\n\nclass Employee\n{\n private decimal salary;\n\n public void GivePayRise()\n {\n // Should this employee get a pay rise.\n // Apply business logic - get value etc...\n // Give raise\n }\n\n // More methods with behaviour\n}\n\n\nNow we cannot rely on Salary being public knowledge. Anyone wanting to give a pay rise to employees must do this via this method. This is great because the business logic for this is contained in one place. We can change this one place and effect everywhere the Employee is used.",
2012-02-29T21:48:18
user961376 :

Really? \nI don't think that. on the contrary the getters and setters help you to protect the consistense of the variables. \n\nThe importance of getters and setters is to provide protection to private attributes so that they can not be accessed directly for this it is best that you create a class with the attribute item in which you include the corresponding get and set.",
2012-02-23T15:48:40
Kiril Kirilov :

The following sample is a brilliant example of boilerplate setters and getters.\n\nclass Item{\n private double price;\n\n public void setPrice(final double price){\n this.price = price;\n }\n public double getPrice(){\n return this.price;\n }\n}\n\n\nSome coders think that this is called encapsulation, but in fact this code is exact equivalent of\n\nclass Item{\n public double price;\n}\n\n\nIn both classes price is not protected or encapsulated, but the second class reads easier.\n\n class Item{\n private double price;\n\n public void setPrice(final double price){\n if(isValidPrice(price))\n this.price = price;\n else throw new IllegalArgumentException(price+\" is not valid!\");\n }\n\n public double getPrice(){\n return this.price;\n }\n }\n\n\nThis is a real encapsulation, the invariant of the class is guarded by the setPrice. My advice - don't write dummy getters and setters, use getters and setters only if they guard the invariant of your class",
2012-02-23T15:54:19
Cloudanger :

Use a helper class ShoppingCart. Item's method item.addTo(ShoppingCart cart) would add the price to the totalSum of the cart using shoppingCart.addItem(Item item, int price)\n\nDependency from Item to ShoppingCart isn't disadvantageous if the Items are meant to be items of ShoppingCarts.\n\nIn the case where Items live solely for the ShoppingCart and the Item class is small, I would more likely have the Item as an inner class of the ShoppingCart, so that the ShoppingCart would have access to the private variables of the items.\n\nOther thoughts\n\nIt would also be possible, although quite unintuitive design, to have the Item class count the sum (item.calculateSum(List<Item> items)), since it can access the private parts of other items without breaking encapsulation.\n\nTo others wondering why the getters are bad. Consider the given example where the getPrice() returns integer. If you would want to change that to something better like BigDecimal at least or a custom money type with currency, then it wouldn't be possible since the return type int exposes the internal type.",
2013-01-26T17:00:15
jason :

\n I have read in many places that \"getters and setters are evil\".\n\n\nReally? That sounds crazy to me. Many? Show us one. We'll tear it to shreds.\n\n\n And I understood why so.\n\n\nI don't. It seems crazy to me. Either your misunderstood but think you did understand, or the original source is just crazy.\n\n\n But I don't know how to avoid them completely. \n\n\nYou shouldn't.\n\n\n how to avoid getPrice? \n\n\nSee, why would you want to avoid that? How else are you suppose to get data out of your objects?\n\n\n how to avoid them???\n\n\nDon't. Stop reading crazy talk.",
2012-02-23T15:43:50
murungu :

Getters and setters are evil because they break encapsulation and can unnecessarily expose an objects internal state and allow it to be modified in way it should not be. The following article elaborates on this problem:\n\nhttp://programmer.97things.oreilly.com/wiki/index.php/Encapsulate_Behavior,_not_Just_State",
2017-03-14T15:02:40
Arnab Datta :

When someone tells you that getters and setters are evil, think about why they are saying that.\nGetters\nAre they evil? There is no such thing as evil in code. Code is code and is neither good nor bad. It's just a matter of how hard it is to read and debug.\nIn your case, I think it is perfectly fine to use a getter to calculate the final price.\nThe "evil"\nUsecase: you think you want the price of an item when buying something.\nPeople sometimes use getters like this:\nif(item.getPrice() <= my_balance) {\n myBank.buyItem(item);\n}\n\nThere is nothing wrong with this code, but it isn't as straight-forward as it could be. Look at this (more pragmatic approach):\nmyBank.buyItem(item); //throws NotEnoughBalanceException\n\nIt's not the buyers or the cashiers job to check the price of an item when buying something. It's the actually the bank's job. Imagine that customer A has a SimpleBank.java\npublic class SimpleBank implements Transaction {\n\n public void buyItem(Item item){\n if(getCustomer().getBalance() >= item.getPrice()){\n transactionId = doTransaction(item.getPrice());\n sendTransactionOK(transactionId);\n }\n }\n}\n\nThe first approach seems fine here. But what if customer B has a NewAndImprovedBank.java?\npublic class NewAndImprovedBank implements Transaction {\n\n public void buyItem(Item item){\n int difference = getCustomer().getBalance() - item.getPrice();\n if (difference >= 0) {\n transactionId = doTransaction(item.getPrice());\n sendTransactionOK(transactionId);\n } else if (difference <= getCustomer().getCreditLimit()){\n transactionId = doTransactionWithCredit(item.getPrice());\n sendTransactionOK(transactionId);\n }\n }\n}\n\nYou might think that you are being defensive when using the first approach, but actually you are limiting the capabilities of your system.\nConclusion\nDon't ask for permission aka item.getPrice() , ask for forgiveness aka NotEnoughBalanceException instead.",
2015-12-15T11:57:04
Wes :

getPrice() is accessing a private variable I'm assuming.\n\nTo answer your question directly, make the price variable public, and code something like (syntax may differ depending on language, use of pointers etc):\n\ntotal += item.price;\n\n\nHowever this is generally considered bad style. Class variables should generally remain private. \n\nPlease see my comment on the question.",
2012-02-23T15:49:59
yy