This is a bit abstract to me. I don't tend to write mutable classes. And if I do mutate fields, it's for a "reason" (and I'll name the method after that reason).
If you feel like it, write out how you'd implement the class and why. I posted a fairly strong opinion, but I'm happy to have my mind changed.
sure, ok, if you only write immutable classes, by definition you never need setters, right?
i won't defend mutable classes (i won't decry them either), because i haven't personally thought tons about the benefits of immutability. i mean, i can see a lot of reasons why it's a good thing to shoot for, and i think it's a thing i often try to shoot for. but people often write mutable classes, or must maintain mutable classes written by their predecessors. in which case, setters can be nice.
or they can be annoying boiler plate. seems like a case by case thing to me. i think the getter/setter thing does often feel needlessly verbose, and so i upvoted your original parent comment. but "setters are always bad and i don't understand why anyone would ever use them" seems like a needlessly hard-line sentiment, IMO.
If you have a mutable class, and you're modifying its fields, you're doing it for a reason, right? Often it's part of a larger operation. So why not name the method that mutates the field after that reason. I got away from thinking about "I am altering the internal representation of this struct + vtable" to "I am sending a message to this opaque thing and I don't really care how it's done when I'm outside the black box".
> but "setters are always bad and i don't understand why anyone would ever use them" seems like a needlessly hard-line sentiment, IMO.
I have a strong opinion because I read some compelling arguments, thought about a lot, stopped using setters, and the quality of my code improved. I don't see a need to moderate my opinions on programming, especially when that's what I really think. Again, happy to be shown a great counter example and admit I was wrong.
> If you have a mutable class, and you're modifying its fields, you're doing it for a reason, right? Often it's part of a larger operation. So why not name the method that mutates the field after that reason. I got away from thinking about "I am altering the internal representation of this struct + vtable" to "I am sending a message to this opaque thing and I don't really care how it's done when I'm outside the black box".
> > but "setters are always bad and i don't understand why anyone would ever use them" seems like a needlessly hard-line sentiment, IMO.
> I have a strong opinion because I read some compelling arguments, thought about a lot, stopped using setters, and the quality of my code improved. I don't see a need to moderate my opinions on programming, especially when that's what I really think. Again, happy to be shown a great counter example and admit I was wrong.
that's all fair. i think we might actually agree more than disagree. all your arguments are compelling, and i could see myself holding a similar opinion after giving the matter more thought.
This seems to deny the fact that a lot of data exists to just be stored and displayed. Probably 85% of all software in the world has a "FirstName" field/property/column in it somewhere. What name you propose giving a method that changes that value?
I guess I'd call it "changeLastName". That's closer to the domain, we don't go to the Department of Births, Deaths and Marriage and tell the clerk we want to "set" our last name. But that is being too pedantic, even for me.
I'll concede defeat. That is a pretty good example. At the end of the day, "customer details" class is actually a big bag of fields that needs some access control and validation.
If you get married, you might "changeLastName" or maybe even "rename" yourself but if you're just moving that name from one place to another you'd "set" it.
You could probably come up with lots of different names but none of them will be more clear than "set" in this case.
Two things with that, you're assuming immutability but even a simple database entity object wouldn't be immutable. And secondly, anything over a handful of values and setting them via a constructor isn't pretty.
if there's more to the domain context, i'd call it rename(~). i think from the outside, it's better to articulate what you want in domain semantics, rather than implementation semantics.
i think from the outside, it's better to articulate what you want in domain semantics, rather than implementation semantics.
You've articulated here what I've actually been trying to communicate. I have no problem if a method does nothing but get/set a variable. I just think they should be named with domain semantics.
Sure, for a simple class like this I would make it immutable too.
But the example is just a demonstration of the concept - you should be able to change the implementation without changing the exposed interface. When you first write a class, it may look like a simple bag of fields. But when that inevitably changes, getters and setters allow you to do it without breaking the clients.
Even if we keep this immutable, your implementation is different in that it uses twice as much memory. Maybe it's irrelevant, or maybe it's worth the tradeoff to use more memory and have faster access to the kelvin representation.
But maybe not. If you had getters and setters, you could seamlessly try the other implementation without changing all of the client code.
But the example is just a demonstration of the concept - you should be able to change the implementation without changing the exposed interface.
My argument is that having getters and setters exposes your implementation. If you have "getFoo" and "setFoo" it exposes that your class contains a value called Foo. My argument is that you should either give your methods better names, or get rid of the pretense of encapsulation altogether and just make them public. Get/Set is just an awkward middle ground.
Even if we keep this immutable, your implementation is different in that it uses twice as much memory.
How can my implementation be different? No one else has written one (:
But maybe not. If you had getters and setters, you could seamlessly try the other implementation without changing all of the client code.
And if you had actual methods with names that didn't break encapsulation, you could do the same and divorce all your calling code from the burden of knowing about the internal structure. Again, the middling approach is the worst of both worlds to me.
> My argument is that having getters and setters exposes your implementation. If you have "getFoo" and "setFoo" it exposes that your class contains a value called Foo. My argument is that you should either give your methods better names, or get rid of the pretense of encapsulation altogether and just make them public. Get/Set is just an awkward middle ground.
this phrasing/perspective definitely brings me around more to your point.