4 ms·
Avoid setters?
by betenoire 9y ago
Avoid setters?
- lacampbell 9y agoNot parent, but I think setters destroy what's objecty about objects - that you send them high level messages and don't care what's inside of them. As Alan Kay puts it (paraphrasing): "setters turn an object back into a data structure"
- eropple 9y agoThis is one of the few things about Ruby idioms that drive me a bit nuts--improper use of `attr_accessor` when `attr_reader` creates better and cleaner code is one of the leading code smells in the library ecosystem.
- cagmz 9y agoIs this to say that `attr_accessor` is too "heavy handed" when just using `attr_reader` could have sufficed?
- eropple 9y agoIt's not about heavy-handedness, it's that `attr_accessor` breaks encapsulation of private state and code very rarely takes into account what actually updating that member variable does. It's used mostly because novice Rubyists are told that that's how you make a variable accessible, not that that's how you make it read-writable. In C#, on the other hand, when you create a property that's the moral equivalent, there's a lot more of a focus on creating getter-only properties that reveal state but don't let you munge it. Ruby is also pretty bad about using #freeze and #taint, but the latter is a lost cause.
- scarface74 9y agoWhat's the difference between a setter in languages like C# and any other method call? I agree that if you class Foo with a property: public string Bar {get; set; } and used as: foo.Bar = "baz" It does look like just another data structure. But what's the difference between that and having a method: public void setBar(string value) { _bar = value; } It is just as easy to add logic to the property later on: public string Bar{ get{ return _bar; }; set { ...some logic; _bar = value; } As it is: public void setBar(string value) { ..some logic; _bar = value; } In fact, they both compile to roughly the same thing.
- dllthomas 9y agoI'd call that "still a setter". I think the concern is that if bar is more about the representation of the object than the behavior, you're not operating at the right level of abstraction.
- scarface74 9y agoAnd the other alternative, because an object still usually needs some type of values would be: class Foo { Foo(string bar) { _bar = bar; } //Foo is the constructor } The benefit being that once an object is created, it is guaranteed to be in a valid state. But by classical OO an object represents state + behavior. So why not do both? Assign the value in the constructor to guarantee that the object is always in a valid state and use a property (if the object is an entity as opposed to a value object), when it needs to change?
- lacampbell 9y agoWhy is it changing? have the method name reflect that domain reason, not reflecting the mechanical details of which internal fields need to change.
- dragonwriter 9y agoThe thing is, in simple cases the implementation will trivially parallel the sensible interface. So setters are appropriate. The problem becomes using setters where that's not the case, often to support tooling that is dependent on constructing objects from serialized state (which often also involves the same kind of abuse of getters, to which exactly the same concerns apply.)
- dllthomas 9y agoTo be clear, I wasn't endorsing the concern, just attempting to clarify it. It doesn't surprise me that it can be over-applied.
- lacampbell 9y ago
- Ace17 9y agoObligatory Casey Muratory rant: https://www.youtube.com/watch?v=_xLgr6Ng4qQ https://www.youtube.com/watch?v=_xLgr6Ng4qQ