Prev: unsubscribe
Next: Compare two objects
From: Josh Cheek on 16 Jun 2010 17:29 [Note: parts of this message were removed to make it a legal post.] On Wed, Jun 16, 2010 at 2:56 PM, Rick DeNatale <rick.denatale(a)gmail.com>wrote: > On Wed, Jun 16, 2010 at 3:23 PM, Josh Cheek <josh.cheek(a)gmail.com> wrote: > > Besides I think that is not something you should do, because it means you > > are accessing ivars all over the place, which couples implementation. If > you > > always use the setter, then you have a gate keeper to that var, and can > > easily change implementation later, without having to go hunt down all > the > > places you used the ivars. > > This is a teapot which holds a tempest which has been brewing for 30 > years or more among users of languages like Ruby. > > Kent Beck covers this pretty well in his book Smalltalk Best Practice > Patterns, the two patterns "direct variable access" and "indirect > variable access" are two of the patterns in the book which are most > applicable to Ruby. > > direct variable access as the name implies is accessing an instance > variable directly by name > indirect variable access is ALWAYS using getter and setter methods to > access a variable. > > Kent describes the two as a tradeoff between simplicity and > readability (direct) vs. flexibility. > > Kent describes an experiment where he compared some Smalltalk code he > had written for a client who insisted on indirect variable access with > code he wrote for himself using direct variable access. He found that > he could read the dva code much more fluently, because he found that > everytime he ran across code like > > a = self x > > He paused just a bit to recognize that x was "just a getter" and not > some other kind of method. > > In Smalltalk methods always need an explicit receiver so that you need > to use "self x" instead of just x. > > Ruby's support for implicit receivers in this case allows for 'bare' > getter invocations, which actually exacerbates this because now > > a = x > > Might be a method call, but x might just be a local variable. You need > to widen the context when reading such code to determine which case it > is. > > And the reason that in Ruby you can't call a setter with just > > x = 1 > > is because even the Ruby parser can't tell that x is a method, so if > it hasn't seen it before in the local context as a method call it > assumes it's a local and defines it so if needed. > > On the other hand Ruby's use of the @ sigil to mark instance variable > names makes it completely clear that you are accessing an instance > variable if you use direct access. > > The main argument for indirect variable access is that it makes it > easier on subclasses because they can change how the 'attribute' is > implemented and inherited methods will use the overrided > implementation. > > This is true, and when you are building subclasses, it can be useful, > HOWEVER, in the course of programming in dynamically typed languages > over nearly 30 years in my case, I've matured to the point where I > realize that subclassing is a powerful tool, which, like many powerful > tools can be dangerous if not wielded with care. In fact that's one > of the main reasons I dislike statically typed "OO" languages, because > they force you to use inheritance to describe a type hierarchy, rather > than applying it with care when it makes sense for implementaion. > > Kent basically advises using direct variable access UNLESS indirect > variable access is more appropriate, and in either case to use one or > the other consistently for a given class and its subclasses. > > -- > Rick DeNatale > > Blog: http://talklikeaduck.denhaven2.com/ > Github: http://github.com/rubyredrick > Twitter: @RickDeNatale > WWR: http://www.workingwithrails.com/person/9021-rick-denatale > LinkedIn: http://www.linkedin.com/in/rickdenatale > > Thanks for the explanation, Rick. I've thought about it a bit, and I think for me, that using indirect access is the better choice in most situations (there are some situations where I use direct access, such as setting state for a view in Rails). I certainly take Kent's advice very seriously, though I'm curious whether his opinion is the same for Ruby as it is for Smalltalk. I also agree with you regarding subclassing, I'm having a hard time thinking of a situation where a subclass works that a module doesn't.
From: Rein Henrichs on 16 Jun 2010 17:38 On 2010-06-16 12:23:40 -0700, Josh Cheek said: > [Note: parts of this message were removed to make it a legal post.] > > On Wed, Jun 16, 2010 at 1:45 PM, Rein Henrichs <reinh(a)reinh.com> wrote: > >> Just set the instance variables yourself. Stop replacing clear, explicit >> code with metaprogramming magic that you can't understand the day after you >> write it. >> > > The original post did not use instance variables, so there is no way to know > that the "self.step = 0" is the same as "@step = 0". Hence my explicit > decision to make sum_of_income a method which must perform calculations, and > accesses an ivar that is not named after the method. Good point. > > Besides I think that is not something you should do, because it means you > are accessing ivars all over the place, which couples implementation. If you > always use the setter, then you have a gate keeper to that var, and can > easily change implementation later, without having to go hunt down all the > places you used the ivars. Use of direct/indirect variable access is an important thing to think critically about. I think that settings ivars in initialize methods is perfectly acceptable. I share your concern with inconsistent use of getters / variables throughout the code. -- Rein Henrichs http://puppetlabs.com http://reinh.com
From: Rein Henrichs on 16 Jun 2010 17:48 On 2010-06-16 12:56:40 -0700, Rick DeNatale said: > On Wed, Jun 16, 2010 at 3:23 PM, Josh Cheek <josh.cheek(a)gmail.com> wrote: >> Besides I think that is not something you should do, because it means you >> are accessing ivars all over the place, which couples implementation. If you >> always use the setter, then you have a gate keeper to that var, and can >> easily change implementation later, without having to go hunt down all the >> places you used the ivars. > > This is a teapot which holds a tempest which has been brewing for 30 > years or more among users of languages like Ruby. > > Kent Beck covers this pretty well in his book Smalltalk Best Practice > Patterns, the two patterns "direct variable access" and "indirect > variable access" are two of the patterns in the book which are most > applicable to Ruby. > > direct variable access as the name implies is accessing an instance > variable directly by name > indirect variable access is ALWAYS using getter and setter methods to > access a variable. > > Kent describes the two as a tradeoff between simplicity and > readability (direct) vs. flexibility. > > Kent describes an experiment where he compared some Smalltalk code he > had written for a client who insisted on indirect variable access with > code he wrote for himself using direct variable access. He found that > he could read the dva code much more fluently, because he found that > everytime he ran across code like > > a = self x > > He paused just a bit to recognize that x was "just a getter" and not > some other kind of method. > > In Smalltalk methods always need an explicit receiver so that you need > to use "self x" instead of just x. > > Ruby's support for implicit receivers in this case allows for 'bare' > getter invocations, which actually exacerbates this because now > > a = x > > Might be a method call, but x might just be a local variable. You need > to widen the context when reading such code to determine which case it > is. > > And the reason that in Ruby you can't call a setter with just > > x = 1 > > is because even the Ruby parser can't tell that x is a method, so if > it hasn't seen it before in the local context as a method call it > assumes it's a local and defines it so if needed. > > On the other hand Ruby's use of the @ sigil to mark instance variable > names makes it completely clear that you are accessing an instance > variable if you use direct access. > > The main argument for indirect variable access is that it makes it > easier on subclasses because they can change how the 'attribute' is > implemented and inherited methods will use the overrided > implementation. > > This is true, and when you are building subclasses, it can be useful, > HOWEVER, in the course of programming in dynamically typed languages > over nearly 30 years in my case, I've matured to the point where I > realize that subclassing is a powerful tool, which, like many powerful > tools can be dangerous if not wielded with care. In fact that's one > of the main reasons I dislike statically typed "OO" languages, because > they force you to use inheritance to describe a type hierarchy, rather > than applying it with care when it makes sense for implementaion. > > Kent basically advises using direct variable access UNLESS indirect > variable access is more appropriate, and in either case to use one or > the other consistently for a given class and its subclasses. I wish more people would read Kent Beck. Smalltalk Best Practice Patterns is one of the best Ruby books ever written ;) -- Rein Henrichs http://puppetlabs.com http://reinh.com
From: Joel VanderWerf on 16 Jun 2010 18:03 One style that I find myself using is to use direct access only for writes (and try to confine writes to as few methods as possible), and use indirect access everywhere else. An example (probably way too simple): class C def counters @counters ||= {} end def clear_counters @counters = nil end def bump_for x counters[x] ||= 0 counters[x] += 1 end def count_for x counters[x] || 0 end end
From: Rick DeNatale on 19 Jun 2010 11:10
On Wed, Jun 16, 2010 at 5:29 PM, Josh Cheek <josh.cheek(a)gmail.com> wrote: > I'm curious whether his opinion is the same for Ruby as it is for Smalltalk. I asked him and got the answer I expected: "i don't see how the forces are any different in Ruby. e.g. C#'s properties makes the question moot because there's not cost to ind ref" I do think, and responded to him that there were subtle differences in the forces, like the use of the @ sigil to mark a direct iv access, but it was pretty much a wash. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale |