Getting rid of self

Getting rid of self
Consider

···

def initialize(attributes = nil)

super attributes

self.step = 0

self.national_debt = 0

self.sum_of_income = 0

self.sum_of_taxes = 0

self.sum_of_happiness = 0

self.sum_of_investments = 0

self

end


Please focus on the repeated use of self.

Is there some way to set the, uh, environment so that “self” need not be repeated?

(Joke: Hmm, if you get rid of your self, do you commit suicide?)

Have you tried it like this?

···

---

def initialize(attributes = nil)

   super attributes

   step = 0

   national_debt = 0

   sum_of_income = 0

   sum_of_taxes = 0

   sum_of_happiness = 0

   sum_of_investments = 0

end

---

'self' is the default receiver inside a method

HTH

--
Andrea Dallera

Il 16/06/2010 11.31, Ralph Shnelvar ha scritto:

Consider

---

def initialize(attributes = nil)

  super attributes

  self.step = 0

  self.national_debt = 0

  self.sum_of_income = 0

  self.sum_of_taxes = 0

  self.sum_of_happiness = 0

  self.sum_of_investments = 0

  self

end

---

Please focus on the repeated use of self.

Is there some way to set the, uh, environment so that "self" need not be repeated?

(Joke: Hmm, if you get rid of your self, do you commit suicide?)

step.=(0)

But do you really want to do that?

The setters don't bother me so much. And I actually like seeing the
self sometimes b/c it gets highlighted by my editor. Aside however, I
really hate having to type 'self.class', I'd much prefer Ruby add an
alias #object_class along the lines of #object_id.

···

On Jun 16, 5:31 am, Ralph Shnelvar <ral...@dos32.com> wrote:

Consider

def initialize(attributes = nil)

super attributes

self.step = 0

Is there some way to set the, uh, environment so that "self" need not be
repeated?

Only by changing your paradigm and by defining setters like these

%w{ step taxes what }.each do | att_name |
   define_method att_name do | *args |
      return instance_variable_get( "@#{att_name}") if args.empty?
      instance_variable_set( "@#{att_name}", args.first)
   end
end

def tax *values
    return @tax if values.empty?
    @tax = valeus.first
end
....

HTH
R

(Joke: Hmm, if you get rid of your self, do you commit suicide?)

Depends on how many selves you got (cats have 7 IIRC).

···

On Wed, Jun 16, 2010 at 11:31 AM, Ralph Shnelvar <ralphs@dos32.com> wrote:

--
The best way to predict the future is to invent it.
-- Alan Kay

Consider

---

def initialize(attributes = nil)

  super attributes

  self.step = 0

  self.national_debt = 0

  self.sum_of_income = 0

  self.sum_of_taxes = 0

  self.sum_of_happiness = 0

  self.sum_of_investments = 0

  self

end

---

Please focus on the repeated use of self.

Is there some way to set the, uh, environment so that "self" need not be
repeated?

I don't think so, but if you wanted to dry it up a bit, you could
potentially do something like this.

class Example

  METHODS = [ :step, :national_debt, :sum_of_income, :sum_of_taxes,
:sum_of_happiness, :sum_of_investments ]
  DEFAULTS = [ 1 , 2 , [1,2,3,4,5] , 4 ,
5 , 6 ]

  attr_accessor( * METHODS - [:sum_of_income] )

  # just to whow that these need not be so simple as the 1:1 method
assignment to ivar that attr_accessor gives
  def sum_of_income=(incomes)
    summed = incomes.inject { |sum,income| sum + income }
    @calculated_sum_of_income = summed
  end

  def initialize
    METHODS.zip(DEFAULTS).each { |method,default| send "#{method}=" ,
default }
  end

end

Example.new # => #<Example:0x10019a770 @sum_of_taxes=4, @national_debt=2,
@sum_of_investments=6, @step=1, @calculated_sum_of_income=15,
@sum_of_happiness=5>

(note that I wouldn't mind better method param support built into core Ruby,
but doesn't quite apply to this, where it is legitimate to ask how you would
differentiate between setters local vars)

(Joke: Hmm, if you get rid of your self, do you commit suicide?)

Being a determinist, "I" have often argued that there is no self and there
never was. Of course, "I" don't let that stop "me" from being who "I" choose
to be. (English is cruel to existential commentary)

···

On Wed, Jun 16, 2010 at 4:31 AM, Ralph Shnelvar <ralphs@dos32.com> wrote:

On Wed, Jun 16, 2010 at 12:26 PM, Robert Dober <robert.dober@gmail.com>wrote:

Only by changing your paradigm and by defining setters like these

%w{ step taxes what }.each do | att_name |
  define_method att_name do | *args |
     return instance_variable_get( "@#{att_name}") if args.empty?
     instance_variable_set( "@#{att_name}", args.first)
  end
end

def tax *values
   return @tax if values.empty?
   @tax = valeus.first
end
....

This is the approach _why took in Dwemthy's Array.

http://mislav.uniqpath.com/poignant-guide/book/chapter-6.html#section3
(best read with the soundtrack

)

That won't work, because the parser sees this as local variable
assignments, and not method calls.
I don't know an easy way to remove that.

Jesus.

···

On Wed, Jun 16, 2010 at 11:37 AM, Andrea Dallera <andrea@andreadallera.com> wrote:

Have you tried it like this?

---

def initialize(attributes = nil)

super attributes

step = 0

national_debt = 0

sum_of_income = 0

sum_of_taxes = 0

sum_of_happiness = 0

sum_of_investments = 0

end

---

'self' is the default receiver inside a method

[Note: parts of this message were removed to make it a legal post.]

Consider

---

def initialize(attributes = nil)

super attributes

self.step = 0

self.national_debt = 0

self.sum_of_income = 0

self.sum_of_taxes = 0

self.sum_of_happiness = 0

self.sum_of_investments = 0

self

end

---

Please focus on the repeated use of self.

Is there some way to set the, uh, environment so that "self" need not be
repeated?

I don't think so, but if you wanted to dry it up a bit, you could
potentially do something like this.

class Example

  METHODS = [ :step, :national_debt, :sum_of_income, :sum_of_taxes,
:sum_of_happiness, :sum_of_investments ]
  DEFAULTS = [ 1 , 2 , [1,2,3,4,5] , 4 ,
5 , 6 ]

  attr_accessor( * METHODS - [:sum_of_income] )

  # just to whow that these need not be so simple as the 1:1 method
assignment to ivar that attr_accessor gives
  def sum_of_income=(incomes)
    summed = incomes.inject { |sum,income| sum + income }
    @calculated_sum_of_income = summed
  end

  def initialize
    METHODS.zip(DEFAULTS).each { |method,default| send "#{method}=" ,
default }
  end

end

Example.new # => #<Example:0x10019a770 @sum_of_taxes=4, @national_debt=2,
@sum_of_investments=6, @step=1, @calculated_sum_of_income=15,
@sum_of_happiness=5>

(note that I wouldn't mind better method param support built into core Ruby,
but doesn't quite apply to this, where it is legitimate to ask how you would
differentiate between setters local vars)

(Joke: Hmm, if you get rid of your self, do you commit suicide?)

Being a determinist, "I" have often argued that there is no self and there
never was. Of course, "I" don't let that stop "me" from being who "I" choose
to be. (English is cruel to existential commentary)

Only by changing your paradigm and by defining setters like these

%w{ step taxes what }.each do | att_name |
define_method att_name do | *args |
return instance_variable_get( "@#{att_name}") if args.empty?
instance_variable_set( "@#{att_name}", args.first)
end

def tax *values
return @tax if values.empty?
@tax = valeus.first
end
....

This is the approach _why took in Dwemthy's Array.

http://mislav.uniqpath.com/poignant-guide/book/chapter-6.html#section3
(best read with the soundtrack
http://s3.amazonaws.com/mislav.baconfile.com/poignant-guide%2Fchapter-6-downtown.mp3

)

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.

If you're going to use some sort of dynamic attr method that sets with an argument and gets without an argument, define an attr_*-like method and use it for each attribute so you can see what you're doing.

_why's code is full of metaprogramming where simpler alternatives exist. Case in point: Camping. I wonder if it isn't in part to blame for the current Ruby fetish with metaprogramming. That said, I do love me some chunky bacon.

···

On 2010-06-16 11:01:47 -0700, Josh Cheek said:

On Wed, Jun 16, 2010 at 4:31 AM, Ralph Shnelvar <ralphs@dos32.com> wrote:
On Wed, Jun 16, 2010 at 12:26 PM, Robert Dober <robert.dober@gmail.com>wrote:

--
Rein Henrichs

http://reinh.com

No a cat has 9 lives, not 9 selves.

Perhaps you were thinking of the Dr. Who has had more selves that a
cat has lives!

I'll leave it to the reader to decide if that was two sentences, or
one with a missing comma and pronoun. <G>

···

On Wed, Jun 16, 2010 at 1:26 PM, Robert Dober <robert.dober@gmail.com> wrote:

(Joke: Hmm, if you get rid of your self, do you commit suicide?)

Depends on how many selves you got (cats have 7 IIRC).

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

If they're ivars (attr_accessible), then just use the ivar itself. If they
are methods on the class, then you'll need the self for there reason you
mentioned:

def initialize(attributes = nil)

  super # If exact signature, don't need arguments

  @step = 0

  @national_debt = 0

  @sum_of_income = 0

  @sum_of_taxes = 0

  @sum_of_happiness = 0

  @sum_of_investments = 0
end

Oh, and you never need to return anything from #initialize.

Jason

···

2010/6/16 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>

On Wed, Jun 16, 2010 at 11:37 AM, Andrea Dallera > <andrea@andreadallera.com> wrote:
> Have you tried it like this?
>
>
> ---
>
> def initialize(attributes = nil)
>
> super attributes
>
> step = 0
>
> national_debt = 0
>
> sum_of_income = 0
>
> sum_of_taxes = 0
>
> sum_of_happiness = 0
>
> sum_of_investments = 0
>
> end
>
> ---
>
>
> 'self' is the default receiver inside a method

That won't work, because the parser sees this as local variable
assignments, and not method calls.
I don't know an easy way to remove that.

<snip> _why's code is full of metaprogramming where simpler alternatives exist.

Case in point: Camping. I wonder if it isn't in part to blame for the
current Ruby fetish with metaprogramming. That said, I do love me some
chunky bacon.

You sure know how to pick your victims, brave move!
That is all I will write on this.

I know writing this is probably not very smart, but it feels right.

Robert

···

On Wed, Jun 16, 2010 at 8:45 PM, Rein Henrichs <reinh@reinh.com> wrote:

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.

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.

···

On Wed, Jun 16, 2010 at 1:45 PM, Rein Henrichs <reinh@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.

Bad choice of victim (Camping, not _why), because the whole philosophy
of Camping
is to experiment with weird Ruby code:

    No, let's not have rules. I don't feel comfortable with having
    coding standards or any protocol on Camping. The point of Camping
    is to have very ugly, tricky code that goes against all the rules that
    people make for "beautiful" code these days. To show that ugly code
    can do beautiful things, maybe.

    I don't want to demonize anyone here, I just want to express the
    ideas that make Camping different. Camping's personality is 80x50.
    It is like the little gears of a watch that are all meshed together
    into a tight little mind-bending machine. The challenge of Camping
    isn't to figure out how to automate obfuscation. The challenge is
    to bring new tricks into the code that push Ruby's parser and make
    everyone look twice.

    Not all code needs to be a factory, some of it can just be origami.

    _why

// Magnus Holm

···

On Wed, Jun 16, 2010 at 20:45, Rein Henrichs <reinh@reinh.com> wrote:

_why's code is full of metaprogramming where simpler alternatives exist.
Case in point: Camping. I wonder if it isn't in part to blame for the
current Ruby fetish with metaprogramming. That said, I do love me some
chunky bacon.

Only if you assume that the setter methods only set the ivar. If
there's extra logic in the setter method, to call it you need the
self.

Jesus.

···

On Wed, Jun 16, 2010 at 1:28 PM, Jason Roelofs <jameskilton@gmail.com> wrote:

2010/6/16 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>

On Wed, Jun 16, 2010 at 11:37 AM, Andrea Dallera >> <andrea@andreadallera.com> wrote:
> Have you tried it like this?
>
>
> ---
>
> def initialize(attributes = nil)
>
> super attributes
>
> step = 0
>
> national_debt = 0
>
> sum_of_income = 0
>
> sum_of_taxes = 0
>
> sum_of_happiness = 0
>
> sum_of_investments = 0
>
> end
>
> ---
>
>
> 'self' is the default receiver inside a method

That won't work, because the parser sees this as local variable
assignments, and not method calls.
I don't know an easy way to remove that.

If they're ivars (attr_accessible), then just use the ivar itself. If they
are methods on the class, then you'll need the self for there reason you
mentioned:

def initialize(attributes = nil)

super # If exact signature, don't need arguments

@step = 0

@national_debt = 0

@sum_of_income = 0

@sum_of_taxes = 0

@sum_of_happiness = 0

@sum_of_investments = 0
end

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.

···

On Wed, Jun 16, 2010 at 3:23 PM, Josh Cheek <josh.cheek@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.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

[Note: parts of this message were removed to make it a legal post.]

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.

···

On 2010-06-16 12:23:40 -0700, Josh Cheek said:

On Wed, Jun 16, 2010 at 1:45 PM, Rein Henrichs <reinh@reinh.com> wrote:

--
Rein Henrichs

http://reinh.com

Not at all. This is exactly why I chose Camping. It more than adequately demonstrates _why's fetish for "tricky code". Such trickiness is also present in much of his other code, but not even _why can disagree with this example.

_why may know tradeoffs imposed by "very ugly, tricky code that goes against all the rules" but the people who look to _why for advice (like his Poignant Guide, aimed directly at Ruby newcomers) are incapable of making this critical distinction.

Also, the pronoun may have been ambiguous. I meant "I wonder if *_why's code* isn't in part to blame...", not specifically Camping.

···

On 2010-06-16 14:13:22 -0700, Magnus Holm said:

On Wed, Jun 16, 2010 at 20:45, Rein Henrichs <reinh@reinh.com> wrote:

_why's code is full of metaprogramming where simpler alternatives exist.
Case in point: Camping. I wonder if it isn't in part to blame for the
current Ruby fetish with metaprogramming. That said, I do love me some
chunky bacon.

Bad choice of victim (Camping, not _why), because the whole philosophy
of Camping
is to experiment with weird Ruby code:

    No, let's not have rules. I don't feel comfortable with having
    coding standards or any protocol on Camping. The point of Camping
    is to have very ugly, tricky code that goes against all the rules that
    people make for "beautiful" code these days. To show that ugly code
    can do beautiful things, maybe.

    I don't want to demonize anyone here, I just want to express the
    ideas that make Camping different. Camping's personality is 80x50.
    It is like the little gears of a watch that are all meshed together
    into a tight little mind-bending machine. The challenge of Camping
    isn't to figure out how to automate obfuscation. The challenge is
    to bring new tricks into the code that push Ruby's parser and make
    everyone look twice.

    Not all code needs to be a factory, some of it can just be origami.

    _why

// Magnus Holm

--
Rein Henrichs

http://reinh.com

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.

···

On Wed, Jun 16, 2010 at 2:56 PM, Rick DeNatale <rick.denatale@gmail.com>wrote:

On Wed, Jun 16, 2010 at 3:23 PM, Josh Cheek <josh.cheek@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: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

I wish more people would read Kent Beck. Smalltalk Best Practice Patterns is one of the best Ruby books ever written :wink:

···

On 2010-06-16 12:56:40 -0700, Rick DeNatale said:

On Wed, Jun 16, 2010 at 3:23 PM, Josh Cheek <josh.cheek@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.

--
Rein Henrichs

http://reinh.com

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

In "Refactoring - Ruby Edition" (with Kent Beck) the consensus seems
to be: choose whatever fits your needs and refactor when the
requirements change. (who would have guessed something like this from a
book with that title *g)
Chapter 8. Organizing Data > Self Encapsulate Field - Pg. 188

I highly recommended the book, especially for non Smalltalkers.

And while speaking about rewritten books for Ruby, i just finished
"Design Patterns in Ruby" and found it very enlightening, too.

Sry for OT'ing

Greets, Chris

···

On Thu, 17 Jun 2010 06:29:37 +0900 Josh Cheek <josh.cheek@gmail.com> wrote:

On Wed, Jun 16, 2010 at 2:56 PM, Rick DeNatale > <rick.denatale@gmail.com>wrote:

> On Wed, Jun 16, 2010 at 3:23 PM, Josh Cheek <josh.cheek@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: rubyredrick (Rick DeNatale) · GitHub
> 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.