I wonder if we had different syntax for those cases we'd have less of them.
But then, again, it's very convenient to be able to add a method to a class that was previously a dumb struct.
A simplistic example: account.deposit(100) may directly add 100 to the account's balance and a subsequent call to account.balance() may answer 100 more than when account.deposit(100) was called. But those details are up to that instance of the account not the sender of those messages. The sender should not be able to mutate account.balance directly, whether it be via direct access to the field or through the proxy of a setter.
I would say instead that an object shouldn't have setters or getters for any members unless really necessary. And by "necessary", I don't mean "it makes it easier to write code that treats the object as a struct". I mean "setting this field really is an action that this object has to expose to the external world in order to function properly". And not even "necessary" because I coded myself into a corner and that's the easiest way out I see. It needs to be necessary at the design level, not at the code level.
Abusing getters/setters is breaking encapsulation (I said abusing, light use is ok). If you're just going to expose all the innards of the class, why start with a Class?
The whole point of object orientation to put data and behavior together. That's probably the only thing that both the C++/Java and the Smalltalk camp agrees on.
Separating data and the behavior into two different classes breaks that. You're effectively making two classes, each with "half of a responsibility". I can argue that this breaks SRP and the Demeter principle in one go.
Another thing: Abuse of getters/setters is often a symptom of procedural code disguised as OOP code. If you're not going to use what is probably the single biggest advantages of OOP, why use it at all?
-
Here's an answer that elaborates on this that I like:
https://softwareengineering.stackexchange.com/questions/2180...
May I politely disagree based on my long-ago experience with dylan, which has multi-methods (<https://en.wikipedia.org/wiki/Multimethods>). This allowed the action on the data (the methods) to be defined separate from the data. I strongly feel that it was OO done right, and it felt right. You can read about it on the wiki link but it likely won't click until you play with it.
I'd like to give an example but it's too long ago and I don't have any to hand, sorry.
Now, if you want to argue that an object probably shouldn't be written in the way that such things are necessary, you're probably right. And if you want to argue that it should "just set the one field in spirit" (that is, that it should do what it has to to set the field, but not do unrelated things), I would definitely agree with you. But it's not quite as simple as "only ever just set the one field".
No, they don't, because “more or less” is not actually directly. Particularly, naive getters and setters can be (and often are) replaced with more complex behavior with no impact to consuming code because they are simply message handlers, and they abstract away the underlying state.
I disagree.
Consider a `Counter` class, intended to be used for counting something. The class has one field: `Counter.count`, which is an integer.
A setter/getter for this field would be like `Counter.setCount(i: Int)` and `Counter.getCount() -> Int`. There is no effective difference between using these methods and having direct access to the internal state of the object.
A more "true OOP" solution would be to use methods with semantic meaning, for example: `Counter.increment()`, `Counter.decrement()`, and `Counter.getCount() -> Int`. (Yes, the getter is here because this is a simple example.) These kinds of methods are not directly exposing the internal state of the object to be freely manipulated by the outside world.
If your getter/setter does something other than just get/set, then it's not really a getter/setter anymore — it's a normal method that happens to manipulate the state, which is fine. But using getters/setters (in the naive, one-line sense) is commonplace with certain people, and I feel that their use undermines the principles Kay was getting at.
This has always been my problem with getters and setters. It's a way of either pretending you are not or putting bandaids on the fact that you're messing with the objects internal state. For objects with dynamic state this is really bad. The result is racy or brittle.
If they do, that's your fault for letting them. I guess you mean when people chain stuff thus
company.programmers.WebDevs.employ('fred')
where .programmers and .WebDevs is an exposed internal of the company and programmers department respectively? (I've seen lots of this, and in much longer chains too. We all have). In which case please see the Principle of Demeter <https://en.wikipedia.org/wiki/Law_of_Demeter> which says don't do this. Wiki article is good.
I doubt any language can prevent this kind of 'exposing guts' malpractice, it's down to the humans.
I remember reading that Alan Kay said when he saw the Linda model (<https://en.wikipedia.org/wiki/Linda_(coordination_language)>) he said it was closer to what he wanted smalltalk to be.
Actually, true OOP languages do prevent this. Internal state is completely private and cannot be exposed externally. The only way to interact with an object's state is through its methods — which means the object itself is responsible for knowing how to manipulate its internal state.
Languages like Java are not "true" OOP in this sense, because they provide the programmer with mechanisms to allow external access to internal state.
Internal state should be kept internal. You shouldn't have a class `Foo` with a private internal `.bar` field and then provide public `Foo.getBar()` and `Foo.setBar()` methods, because you may as well just have made the `.bar` field public in that case.
Also, FWIW, I did not downvote you. I dunno why you were downvoted. Seems you had a legitimate point here, even if I disagree with it.
I'm not sure that's a proven model. It's a proposed model, for sure. Since you can't protect memory from runtime access, you can't really protect state, so it's a matter of convention which Python cleverly baked in (_privatevar access).
Getters/setters are technically message-passing methods, but they undermine the design goal because they more or less directly expose internal state to the public world.
But we see getters/setters used constantly. People don't use OO in the way Kay intended. Yes, methods are the implementation of the whole "message passing" thing Kay was talking about, but we see them used in ways he did not intend.