Forum: RSpec class << self considered harmful... really?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Matt W. (Guest)
on 2008-11-25 15:42
(Received via mailing list)
Sorry, I know this is off-topic, but I'd really like to know what the
revered ruby-hackers who read this list think.

See
http://ozmm.org/posts/class__self_is_harmful.html

I have adopted class << self, partly from reading RSpec and Cucumber's
code as I learn Ruby. I personally think of class methods (or 'static'
methods) as being in a kind of 'holding pen' waiting to be factored
off onto a proper class of their own, so I rather like the clear way
you can group them in a 'nameless' metaclass ready for the exit door.

I also really like the clarity of seeing the invisible metaclass for
what it is.

What do people think? How can this be harmful?

cheers,
Matt
Zach D. (Guest)
on 2008-11-25 16:39
(Received via mailing list)
On Tue, Nov 25, 2008 at 8:41 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:
> 'nameless' metaclass ready for the exit door.
>
> I also really like the clarity of seeing the invisible metaclass for what it
> is.
>
> What do people think? How can this be harmful?

I think the issue is that people are using class << self to access the
virtual class when they don't need it. I've seen code where you have
to scroll to see all of the methods implemented inside of class <<
self. Adding methods to a virtual class does make method dispatching
in ruby less efficient, but I don't think enough to render it
non-usable.

The virtual class of an object (class or instance alike) gives you the
ability to modify the object in ways that a simple class method
usually does not allow. For example, if you want to break down a class
method into a couple of methods, but you don't want to support all of
the methods as a public API. Here you can use class << self to
privately scope some of those helper methods that you just decomposed.

My rule of thumb is to use it when I can't easily achieve the same
result using other mechanisms, but not to use it just cause'.

--
Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com
Zach D. (Guest)
on 2008-11-25 16:39
(Received via mailing list)
On Tue, Nov 25, 2008 at 9:38 AM, Zach D. <removed_email_address@domain.invalid>
wrote:
>> class of their own, so I rather like the clear way you can group them in a
>> 'nameless' metaclass ready for the exit door.
>>
>> I also really like the clarity of seeing the invisible metaclass for what it
>> is.
>>
>> What do people think? How can this be harmful?

I forgot to add it is considered harmful because it can so easily be
abused and make readability of the code very difficult to understand.
Especially when doing meta-meta programming. :)

> usually does not allow. For example, if you want to break down a class
> http://www.mutuallyhuman.com
>



--
Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com
David C. (Guest)
on 2008-11-25 16:57
(Received via mailing list)
On Tue, Nov 25, 2008 at 8:39 AM, Zach D. <removed_email_address@domain.invalid>
wrote:
>>> as being in a kind of 'holding pen' waiting to be factored off onto a proper
> Especially when doing meta-meta programming. :)
>> ability to modify the object in ways that a simple class method
>> usually does not allow. For example, if you want to break down a class
>> method into a couple of methods, but you don't want to support all of
>> the methods as a public API. Here you can use class << self to
>> privately scope some of those helper methods that you just decomposed.
>>
>> My rule of thumb is to use it when I can't easily achieve the same
>> result using other mechanisms, but not to use it just cause'.

One thing Chris points out in his blog is that 'def self.method_name'
is perfectly fine, and that it makes refactoring easier. My experience
is different, because I'm often searching for methods with 'dev
method_name' - this is actually one of the reasons I have preferred
'class << self'.

That said, I'm all for speeding things up where we can, so I'll be
looking into this in rspec. I just found 22 uses of 'class << self' in
rspec. Sometime soon I'll see how many of them I feel I can get rid
of.

Cheers,
David
Shot (Piotr S.) (Guest)
on 2008-11-25 18:05
(Received via mailing list)
>> On Tue, Nov 25, 2008 at 9:38 AM, Zach
>> Dennis <removed_email_address@domain.invalid> wrote:

>>> The virtual class of an object (class or instance alike) gives you
>>> the ability to modify the object in ways that a simple class method
>>> usually does not allow.

In particular, when implementing a singleton this way, it’s possible to
access instance variables of the singleton (rather than having to work
on class variables).

>>> My rule of thumb is to use it when I can't easily achieve the
>>> same result using other mechanisms, but not to use it just cause'.

Ditto. I basically use it for singleton classes (Log, Config) only.

David C.:

> One thing Chris points out in his blog is that 'def self.method_name'
> is perfectly fine, and that it makes refactoring easier. My experience
> is different, because I'm often searching for methods with 'def
> method_name' - this is actually one of the reasons I have preferred
> 'class << self'.

PHP with its ‘function &returningAReference(…)’ syntax taught me to grep
for function.*name, so I now simply grep for def.*method_name in Ruby
(granted, it doesn’t work too well if you have other methods with
‘method_name’ inside their names).

-- Shot
Mark W. (Guest)
on 2008-11-25 18:08
(Received via mailing list)
On Tue, Nov 25, 2008 at 5:41 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:

> 'nameless' metaclass ready for the exit door.
>

The nature of class methods in Ruby (as instance methods of the class's
eigenclass) is for most purposes an implementation detail. It adds
nothing
to understanding to open the eigenclass inside the class's definition in
order to add class methods. It may save some typing, and it does help
when
searching (as David) says. Nevertheless, I regard the practice as a bit
of
an affection - 'look at me, ma, I'm opening the eigenclass!' - or as the
imitation of an affection. It confuses newbies to no purpose, and
confuses
everyone when 'class << self' has scrolled off the top of the screen.

It's recommended against in The Ruby P.ming Language (of course,
there
are exceptions to every rule).

///
Zach D. (Guest)
on 2008-11-25 18:34
(Received via mailing list)
On Tue, Nov 25, 2008 at 11:08 AM, Mark W. <removed_email_address@domain.invalid> 
wrote:
>> methods) as being in a kind of 'holding pen' waiting to be factored off onto
> everyone when 'class << self' has scrolled off the top of the screen.
A lot of things confuse newbies. I don't think that's a very good
point for why you don't do something. #each confuses newbies, should
we also refrain from using that? Of course not.

Educating people so they understand why and when it should be avoided
is better then raising a fire alarm (unless it's really a fire).
Contrary to your statement though, I don't use class << self to feel
special, and my ma could care less about how I code. ;)


--
Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com
Pat M. (Guest)
on 2008-11-25 18:49
(Received via mailing list)
"Zach D." <removed_email_address@domain.invalid> writes:

>>> code as I learn Ruby. I personally think of class methods (or 'static'
>> imitation of an affection. It confuses newbies to no purpose, and confuses
>> everyone when 'class << self' has scrolled off the top of the screen.
>
> A lot of things confuse newbies. I don't think that's a very good
> point for why you don't do something. #each confuses newbies, should
> we also refrain from using that? Of course not.
>
> Educating people so they understand why and when it should be avoided
> is better then raising a fire alarm (unless it's really a fire).
> Contrary to your statement though, I don't use class << self to feel
> special, and my ma could care less about how I code. ;)

I thought it was just that

class << self
  def method1; end
  def methdod2; end
  def methdod3 end
  def methdod4; end
end

becomes confusing as soon as those method definitions fill up a screen.
def self.method1 makes it instantly clear that it's a singleton method.
That's what I do and why I do it, anyway.

Pat

p.s. using class << self to show off is weak if you're just defining
class methods.  Use it on an instance and then send(:define_method) for
some real points!
Matt W. (Guest)
on 2008-11-25 18:55
(Received via mailing list)
On 25 Nov 2008, at 16:48, Pat M. wrote:

>>>>
>>>> can group
>>> searching (as David) says. Nevertheless, I regard the practice as
>> we also refrain from using that? Of course not.
>  def methdod2; end
>  def methdod3 end
>  def methdod4; end
> end
>
> becomes confusing as soon as those method definitions fill up a
> screen.
> def self.method1 makes it instantly clear that it's a singleton
> method.
> That's what I do and why I do it, anyway.

Surely, as soon as they scroll off the screen, it's time to factor
that code off into a module or class of its own though?

It seems to me like whenever you have a lot of class methods on a
class, you've got a new class dying to get out. It's like class <<
self is like a little incubator for that new type!

Or Is that just me?
Mark W. (Guest)
on 2008-11-25 19:52
(Received via mailing list)
On Tue, Nov 25, 2008 at 8:34 AM, Zach D. <removed_email_address@domain.invalid>
wrote:


> > Nevertheless, I regard the practice as a bit of
> > an affection - 'look at me, ma, I'm opening the eigenclass!' - or as the
> > imitation of an affection. It confuses newbies to no purpose, and
> confuses
> > everyone when 'class << self' has scrolled off the top of the screen.
>
> A lot of things confuse newbies. I don't think that's a very good
> point for why you don't do something.


I believe potential confusion is a good argument against something,
ceteris
paribus. However, as I indicated at the end of my message, ceteri are
not
always paribi. In other words, we all do things that would confuse
newbies,
but (like #each) they have obvious benefits. That's why we use them.

Educating people so they understand why and when it should be avoided


Well, sure, but I'm just talking about cutting some code, here, not
writing
a blog article.

is better then raising a fire alarm (unless it's really a fire).
> Contrary to your statement though, I don't use class << self to feel
> special, and my ma could care less about how I code. ;)
>

Sorry! I didn't mean to seem like I was addressing you personally, Zach.
In
fact, I was thinking of a blog entry I read the other day where a single
method was enclosed in 'class << self.' The only reason I could think of
for
that was 1) because it looked cool to the author, or 2) he thought it
would
look cool to others. It just looked like a couple of lines of wasted
space
to me.

I don't know about any fire alarms - I think the important thing to
consider
is what benefits the practice has. In most cases I've seen, there aren't
any, and it does have the disadvantages I mentioned.

///ark
Mark W. (Guest)
on 2008-11-25 19:55
(Received via mailing list)
On Tue, Nov 25, 2008 at 8:54 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:

>
> Surely, as soon as they scroll off the screen, it's time to factor that
> code off into a module or class of its own though?
>

That's assuming there are a lot of class methods. There might be only
one,
but if that 'class << self' is off the screen, there's the potential for
confusion (among noobs and gurus alike). In many if not most cases I've
seen, there were no counterbalancing benefits.

For more, see The Ruby P.ming Language for their take.

///ark
Avdi G. (Guest)
on 2008-11-25 20:02
(Received via mailing list)
On Tue, Nov 25, 2008 at 8:41 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:
> Sorry, I know this is off-topic, but I'd really like to know what the
> revered ruby-hackers who read this list think.
>
> See
> http://ozmm.org/posts/class__self_is_harmful.html

For the case of defining class methods I completely agree.  It's
unnecessary and it makes classes harder to read, because you have to
scroll back just to determine whether you're looking at class or
instance methods.  Just type "def self.foo()".  It's not that hard.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
Zach D. (Guest)
on 2008-11-25 20:04
(Received via mailing list)
On Tue, Nov 25, 2008 at 12:51 PM, Mark W. <removed_email_address@domain.invalid> 
wrote:
>> point for why you don't do something.
>
>> is better then raising a fire alarm (unless it's really a fire).
>> Contrary to your statement though, I don't use class << self to feel
>> special, and my ma could care less about how I code. ;)
>
> Sorry! I didn't mean to seem like I was addressing you personally, Zach.

I didn't think you were. Did my wink-smily not come through?

>
> ///ark
>



--
Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com
Matt W. (Guest)
on 2008-11-25 20:05
(Received via mailing list)
On 25 Nov 2008, at 17:54, Mark W. wrote:

> On Tue, Nov 25, 2008 at 8:54 AM, Matt W. <removed_email_address@domain.invalid>
> wrote:
>
> Surely, as soon as they scroll off the screen, it's time to factor
> that code off into a module or class of its own though?
>
> That's assuming there are a lot of class methods. There might be
> only one, but if that 'class << self' is off the screen, there's the
> potential for confusion (among noobs and gurus alike). In many if
> not most cases I've seen, there were no counterbalancing benefits.

I don't understand. If it's off the screen, it's off the screen,
whether it's defined using self.foo or class << self; def foo; end;

What have I missed?

>
>
> For more, see The Ruby P.ming Language for their take.

I didn't know about that book! Cheers for the recommendation :)
Mark W. (Guest)
on 2008-11-25 20:15
(Received via mailing list)
On Tue, Nov 25, 2008 at 10:04 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:

>> confusion (among noobs and gurus alike). In many if not most cases I've
>> seen, there were no counterbalancing benefits.
>>
>
> I don't understand. If it's off the screen, it's off the screen, whether
> it's defined using self.foo or class << self; def foo; end;
>

If the def line is off the screen, then you don't even know what method
you're in (at least with most editors). I wasn't talking about that.

Look, all I'm saying is that to understand the meaning of a chunk of
code,
you need to see more lines with 'class << self' that without it.
Personally,
I like relatively terse code, because it's easier to read - if for no
other
reason than that more fits on a single screen without losing clarity.

I'd be interested, however, in hearing about the benefits of opening the
eigenclass to define class methods (apart from ease in searching, which
may
be best handled with ctags).

///ark
Scott T. (Guest)
on 2008-11-25 20:17
(Received via mailing list)
On Nov 25, 2008, at 1:14 PM, Mark W. wrote:

>
> about that.
>
> Look, all I'm saying is that to understand the meaning of a chunk of
> code, you need to see more lines with 'class << self' that without
> it. Personally, I like relatively terse code, because it's easier to
> read - if for no other reason than that more fits on a single screen
> without losing clarity.
>
> I'd be interested, however, in hearing about the benefits of opening
> the eigenclass to define class methods (apart from ease in
> searching, which may be best handled with ctags).

Grouping and private methods.

You won't risk having a class methods scattered all over the file.

Scott
Wes G. (Guest)
on 2008-11-25 20:28
(Received via mailing list)
Scott T. wrote
>>
>> I'd be interested, however, in hearing about the benefits of opening
>> the eigenclass to define class methods (apart from ease in searching,
>> which may be best handled with ctags).
>
> Grouping and private methods.
Potentially dumb question:

As far as private class methods, could you do

private
  def self.blah
    ...
  end

to get private class methods, or does private not work on class methods
in this way?

Wes
Pat M. (Guest)
on 2008-11-25 20:32
(Received via mailing list)
Matt W. <removed_email_address@domain.invalid> writes:

>>>>> the
>>>>> factored off onto
>>>> order to add class methods. It may save some typing, and it does
>>> A lot of things confuse newbies. I don't think that's a very good
>> class << self
>> That's what I do and why I do it, anyway.
> _______________________________________________
> rspec-users mailing list
> removed_email_address@domain.invalid
> http://rubyforge.org/mailman/listinfo/rspec-users

Just you :)  Bad style is not an excuse for bad style.

Pat
Scott T. (Guest)
on 2008-11-25 20:40
(Received via mailing list)
On Nov 25, 2008, at 1:27 PM, Wes G. wrote:

>
> private
> def self.blah
>   ...
> end
>
> to get private class methods, or does private not work on class
> methods in this way?

You'll have to open the metaclass:

http://gist.github.com/29021

Scott
Mark W. (Guest)
on 2008-11-25 20:58
(Received via mailing list)
On Tue, Nov 25, 2008 at 10:27 AM, Wes G. <removed_email_address@domain.invalid> 
wrote:

>
You would do

 def self.blah
   #...
 end
 private_class_method :blah

///ark
Shot (Piotr S.) (Guest)
on 2008-11-26 15:18
(Received via mailing list)
Mark W.:

> I'd be interested, however, in hearing about the benefits of opening
> the eigenclass to define class methods (apart from ease in searching,
> which may be best handled with ctags).

Such methods have access to the eigenclass’s instance variables, and so
class << self works very nice when working with singletons (like Log or
Config).

If you don’t use class << self, you have to work on class variables and
you can’t use the attr_* shorthands to access the singleton’s variables.

-- Shot
Peter J. (Guest)
on 2008-11-26 16:39
(Received via mailing list)
On Wed, Nov 26, 2008 at 8:23 AM, Shot (Piotr S.) 
<removed_email_address@domain.invalid>
wrote:

> If you don't use class << self, you have to work on class variables and
> you can't use the attr_* shorthands to access the singleton's variables.

Actually, instance variables in a "def self.*" method still refer to
the singleton object.  The body of that method is treated just like a
method in "class << self".  You just don't get a chance, as you say,
to make accessors with "attr_*", since that goes outside your method
definitions.

Peter
Mark W. (Guest)
on 2008-11-26 16:47
(Received via mailing list)
On Wed, Nov 26, 2008 at 5:23 AM, Shot (Piotr S.)
<removed_email_address@domain.invalid>wrote:

>
> Such methods have access to the eigenclass's instance variables, and so
> class << self works very nice when working with singletons (like Log or
> Config).
>
> If you don't use class << self, you have to work on class variables and
> you can't use the attr_* shorthands to access the singleton's variables.
>

Right. I was talking about the difference between using "class << self"
and
"def self.foo" when other things were equal. I do understand there are
situations (like the one you mention) where it's handy to be actually in
the
eigenclass when defining methods.

///ark
Matt W. (Guest)
on 2008-11-26 16:52
(Received via mailing list)
On 26 Nov 2008, at 14:38, Peter J. wrote:

> method in "class << self".  You just don't get a chance, as you say,
> to make accessors with "attr_*", since that goes outside your method
> definitions.
>
> Peter

That's one of the things that attracted me to using class << self to
contain all these methods - it just seemed easier to me to visualise
what was going on.

I'd be really interested to know the nature of the criticisms made
about it in the Matz book Mark mentioned.

cheers
Matt
Mark W. (Guest)
on 2008-11-26 17:01
(Received via mailing list)
On Wed, Nov 26, 2008 at 6:51 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:

>
> That's one of the things that attracted me to using class << self to
> contain all these methods - it just seemed easier to me to visualise what
> was going on.
>

That makes sense. If you're doing things where being inside the
eigenclass
helps, then by all means open the eigenclass. I think I and others were
just
commenting on it being a default style for some programmers (and I went
on
to snarkily speculate on some of their motives).

I'd be really interested to know the nature of the criticisms made about
it
> in the Matz book Mark mentioned.
>

I'll have a peep when I get in to work today. Of course, it's hard to
tell
what are Matz's opinions and what are Flanagan's (who's not a major
light in
the Ruby world, by any means). Basically, I think his/their objections
were
the ones I've used: it's just not necessary in most cases. It's also
different from the way class methods are defined in C++, Java, and C#.
But
sometimes it's useful.

///ark
Avdi G. (Guest)
on 2008-11-26 18:40
(Received via mailing list)
On Wed, Nov 26, 2008 at 8:23 AM, Shot (Piotr S.) 
<removed_email_address@domain.invalid>
wrote:
> Such methods have access to the eigenclass's instance variables, and so
> class << self works very nice when working with singletons (like Log or
> Config).

I've never had trouble accessing class-level instance variables
(@variables) in class methods defined as "def self.foo".   In fact I
hardly ever use @@variables, and I never use class << self for
defining class methods.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
Avdi G. (Guest)
on 2008-11-26 18:48
(Received via mailing list)
On Wed, Nov 26, 2008 at 8:23 AM, Shot (Piotr S.) 
<removed_email_address@domain.invalid>
wrote:
> If you don't use class << self, you have to work on class variables and
> you can't use the attr_* shorthands to access the singleton's variables.

It's true you need to use class << self to use attr_* macros, but not
true that you can't use singleton instance variables otherwise:

  class Foo
    class << self
      attr_accessor :class_var
    end

    def self.hello
      puts "@class_var: #{@class_var}"
    end
  end

  Foo.class_var = 42
  Foo.hello

=> "@class_var: 42"

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
Mark W. (Guest)
on 2008-11-26 18:52
(Received via mailing list)
On Wed, Nov 26, 2008 at 8:39 AM, Avdi G. <removed_email_address@domain.invalid> 
wrote:


> In fact I hardly ever use @@variables


And class variables are problematic in Rails in development mode because
of
class reloading.

///ark
Mark W. (Guest)
on 2008-11-26 19:00
(Received via mailing list)
On Wed, Nov 26, 2008 at 8:47 AM, Avdi G. <removed_email_address@domain.invalid> 
wrote:


>    class << self
>      attr_accessor :class_var
>    end
>

Also, with Rails, you could do

 cattr_accessor :class_var

which has the same readability benefits as 'def self.foo'

///ark
Matt W. (Guest)
on 2008-11-26 19:20
(Received via mailing list)
On 26 Nov 2008, at 16:51, Mark W. wrote:

> On Wed, Nov 26, 2008 at 8:39 AM, Avdi G. <removed_email_address@domain.invalid> wrote:
>
> In fact I hardly ever use @@variables
>
> And class variables are problematic in Rails in development mode
> because of class reloading.

And more generally dangerous for threading reasons, right?

cheers,
Matt
Avdi G. (Guest)
on 2008-11-26 19:21
(Received via mailing list)
On Wed, Nov 26, 2008 at 12:17 PM, Matt W. <removed_email_address@domain.invalid> 
wrote:
>> And class variables are problematic in Rails in development mode because
>> of class reloading.
>
> And more generally dangerous for threading reasons, right?


All of the above.  My rule of thumb is: don't use them unless I have a
very, very good reason.  I can't think of the last time I had that
good a reason.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
Ben M. (Guest)
on 2008-11-27 08:21
(Received via mailing list)
Avdi G. wrote:
> very, very good reason.  I can't think of the last time I had that
> good a reason.
>
>

So.. you are saying that this is preferred:

class State < AR:Base

  def self.names
      @names ||= State.all.map{|s| s.name}
  end

end

to this:

class State < AR:Base

  def self.names
      @@names ||= State.all.map{|s| s.name}
  end

end

Is that correct?

How is using a class instance variable safer from a threading point of
view?  Do threads not share class instance variables the same way class
variables would be shared?

-Ben
Zach D. (Guest)
on 2008-11-27 18:39
(Received via mailing list)
On Wed, Nov 26, 2008 at 8:46 PM, Ben M. <removed_email_address@domain.invalid> 
wrote:
>>>
> class State < AR:Base
>
> would be shared?
>

AFAIK it isn't any safer from a threading point of view.

My biggest hate of class variables is that they are shared throughout
an entire inheritance hierarchy (and I do not find @@ aesthetically
pleasing). Class instance variables are not.

class A
   def self.foo
      @@foo
   end

   def self.foo=a
       @@foo = a
   end
end

class B < A ; end
class C < B ; end

A.foo = 1
A.foo # => 1

C.foo # => 1
C.foo = 10
C.foo # => 10
A.foo # => 10 -- surprise!

Class instance variables don't have this problem.

class A
   def self.foo
      @foo
   end

   def self.foo=a
       @foo = a
   end
end

class B < A ; end
class C < B ; end

A.foo = 1
A.foo # => 1

C.foo # => nil
C.foo = 10
C.foo # => 10
A.foo # => 1


--
Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com
Student J. (Guest)
on 2008-11-27 19:50
(Received via mailing list)
Everyone seems to agree on the basic issues, but are coming at it from
different viewpoints.

1) If you have a bunch of class methods, you have a problem.
(class#File:  I mean you!)
2) Maintainability is paramount.

The question, then, should be: which of these patterns (class << self
or self.method) encourages/discourages good behaviors?

As I've hinted, Ruby itself is a bad example.  So is Rails.  I'm
beginning to wonder, however, if this is not necessarily the case for
languages and large frameworks.

What class is this?  The detractors of class << self appear to me to
be ignoring the fact that many files have multiple classes defined
therein.  If I'm looking at a group of methods in a file, I NEVER know
which class I'm in until I search backwards for the "class" token.
(So keep the token "class" out of your comments & docs)  self.method
doesn't do much to help this.

But XP extremists argue that a class should never be bigger than a
couple of pages in the first place.  Maybe that is the real problem.

I prefer class << self as it seems to aid refactoring and looks
cleaner.

YMMV
Pat M. (Guest)
on 2008-11-27 20:26
(Received via mailing list)
Student <removed_email_address@domain.invalid> writes:

> therein.  If I'm looking at a group of methods in a file, I NEVER know
> which class I'm in until I search backwards for the "class" token.

You do if you use a good editor, like emacs

:)

Pat
Brian T. (Guest)
on 2008-11-27 23:59
(Received via mailing list)
On Tue, Nov 25, 2008 at 8:41 AM, Matt W. <removed_email_address@domain.invalid> 
wrote:
> 'nameless' metaclass ready for the exit door.
>
> I also really like the clarity of seeing the invisible metaclass for what it
> is.
>
> What do people think? How can this be harmful?
Its funny because I consider def self.foo harmful for a few reasons.

def self.method_name is often mixed with instance methods. This makes
reading the code confusing because there are two contexts that you
need to deal with.
Its too easy to confuse because it reads like its in the same instance,

def self.foobar
  @foobar
end

def foobar
  @foobar
end

Also, like you mentioned, using def self. obfuscates an object
extraction that needs to happen. With class << self, I can think about
refactoring an object, rather than refactoring class methods. class <<
self allows me to think of class/modules in a more object oriented
way.

class Foo
  def self.method_1(an_instance)
  end

  def method_1
  end

  def method_2
  end

  def method_3
  end

  def self.method_2(an_instance)
  end
end

I also like how all of the class << self methods are organized into a
single section. Yes, its difficult to read if it takes more than a
screenful, but I prefer it to having to track down all of the def
self.method_name methods spread all over the place.

Also, class << self is more powerful. It allows you to use one way to
use your convenience methods (attr_*, include) and parser instructions
(public, private, protected). Nothing is worse than having to use both
def self.method_name and class << self.
Mark W. (Guest)
on 2008-11-28 01:44
(Received via mailing list)
On Thu, Nov 27, 2008 at 1:59 PM, Brian T.
<removed_email_address@domain.invalid>wrote:

> Its funny because I consider def self.foo harmful for a few reasons.
>
> def self.method_name is often mixed with instance methods. This makes
> reading the code confusing because there are two contexts that you
> need to deal with.
>

Solution: Don't do that.

>
> Also, like you mentioned, using def self. obfuscates an object
> extraction that needs to happen. With class << self, I can think about
> refactoring an object, rather than refactoring class methods. class <<
> self allows me to think of class/modules in a more object oriented
> way.


In general, in OOP, I've found class methods to be far less numerous
than
instance methods. Class methods by their very nature are not OOP -
they're
not much different than global functions. In Ruby, this is not as true,
of
course, and class methods are just instance methods of a different kind
of
object. When you're using them as such, opening up that object with
class <<
self is a good idea. If you're not, then you shouldn't have very many of
them and wouldn't need to refactor them out.


> I also like how all of the class << self methods are organized into a
> single section. Yes, its difficult to read if it takes more than a
> screenful, but I prefer it to having to track down all of the def
> self.method_name methods spread all over the place.
>

This is just a question of coding style. You can gather all your def
self.foos in one place, and you can have multiple class << self sections
(the latter being bad and the former good)


> Also, class << self is more powerful. It allows you to use one way to
> use your convenience methods (attr_*, include) and parser instructions
> (public, private, protected). Nothing is worse than having to use both
> def self.method_name and class << self.
>

I agree with that. But I also believe in doing the simplest thing that
could
work, and using two extra lines of code when it's not necessary fails
that
test. If it is necessary, that's a different matter, of course.

When I get back into work on Tuesday, I'll dig up what Matz says in RPL
(unless someone else has a copy?)

///ark
Brian T. (Guest)
on 2008-11-28 02:40
(Received via mailing list)
On Thu, Nov 27, 2008 at 6:43 PM, Mark W. <removed_email_address@domain.invalid> 
wrote:
> On Thu, Nov 27, 2008 at 1:59 PM, Brian T. <removed_email_address@domain.invalid>
> wrote:
>>
>> Its funny because I consider def self.foo harmful for a few reasons.
>>
>> def self.method_name is often mixed with instance methods. This makes
>> reading the code confusing because there are two contexts that you
>> need to deal with.
>
> Solution: Don't do that.
When maintaining code, I often wish I could travel back in time and
tell the writer "Don't do that". :)
> course, and class methods are just instance methods of a different kind of
> object. When you're using them as such, opening up that object with class <<
> self is a good idea. If you're not, then you shouldn't have very many of
> them and wouldn't need to refactor them out.
I consider classes & modules to be objects and therefore subject to
the rules of OOP.  That one of the reasons why I love Ruby. The only
thing they have in common with global functions is that they are
easily accessible from anywhere in the process. Nonetheless, module
methods have encapsulated state.
Code evolves and things change. We usually don't set out to overload
one object with too much responsibility. It happens with incremental
changes.
I find that using class << self makes it easy to identify, even when
I'm not looking for, the opportunity to extract an object. Usually
this has to do with the same state being passed in as an argument.
>
>>
>> I also like how all of the class << self methods are organized into a
>> single section. Yes, its difficult to read if it takes more than a
>> screenful, but I prefer it to having to track down all of the def
>> self.method_name methods spread all over the place.
>
> This is just a question of coding style. You can gather all your def
> self.foos in one place, and you can have multiple class << self sections
> (the latter being bad and the former good)
Thats true in theory, but in practice, I often see def
self.method_name spread all over the place and class << self in one
place. I'm not sure why, but I can guess that it has to do with not
thinking about object responsibility.
>
>>
>> Also, class << self is more powerful. It allows you to use one way to
>> use your convenience methods (attr_*, include) and parser instructions
>> (public, private, protected). Nothing is worse than having to use both
>> def self.method_name and class << self.
>
> I agree with that. But I also believe in doing the simplest thing that could
> work, and using two extra lines of code when it's not necessary fails that
> test. If it is necessary, that's a different matter, of course.
Yes we all like YAGNI, but its a trade-off. We all have seen YAGNI
bite us in the ass too, especially when it means turning off the
brain. I don't think 2 extra filler lines of code make that strong of
an argument, when there is more than one class method (and even if
there is one class method IMO).
I think we also like how consistent conventions and delineation of
responsibility make code faster to read and understand.
>
> When I get back into work on Tuesday, I'll dig up what Matz says in RPL
> (unless someone else has a copy?)
Sounds good.
Mark W. (Guest)
on 2008-11-28 02:59
(Received via mailing list)
On Thu, Nov 27, 2008 at 4:40 PM, Brian T.
<removed_email_address@domain.invalid>wrote:


> When maintaining code, I often wish I could travel back in time and
> tell the writer "Don't do that". :)
>

I don't see how we can solve the problem of people not following style
guidelines by giving them another style guideline to follow. :)

module methods have encapsulated state.
>

Probably 99% of the (non-framework) class methods I've seen have no
state.

We all have seen YAGNI
> bite us in the ass too, especially when it means turning off the
> brain. I don't think 2 extra filler lines of code make that strong of
> an argument, when there is more than one class method (and even if
> there is one class method IMO).


If writing those two lines of code are unnecessary for any of the uses
you
and others have described, I would call that turning off the brain. :)


> I think we also like how consistent conventions and delineation of
> responsibility make code faster to read and understand.
>

Agreed, but I think this begs the question under discussion.

///ark

(For those who are tired of this non-RSpec-related discussion (but
apparently find themselves forced to read it), I really will try to wrap
up
my contribution. I don't have the time for the Ruby list, so this is the
only place I have to talk about fun stuff like this. ObRSpec: the
discussion
did illuminate a situation where tests can pass but the development app
can
fail - when using class variables in RoR.)
Brian T. (Guest)
on 2008-11-28 03:13
(Received via mailing list)
On Thu, Nov 27, 2008 at 7:58 PM, Mark W. <removed_email_address@domain.invalid> 
wrote:
> On Thu, Nov 27, 2008 at 4:40 PM, Brian T. <removed_email_address@domain.invalid>
> wrote:
>
>>
>> When maintaining code, I often wish I could travel back in time and
>> tell the writer "Don't do that". :)
>
> I don't see how we can solve the problem of people not following style
> guidelines by giving them another style guideline to follow. :)
Honestly, I'm not going to get my panties in a bunch if I see code
with def self.method_name in it. I don't care what you do with your
code, unless I need to maintain it.
If there are problems with the code, I'll consolidate these methods
into a class << self block so I can have a better understand over what
is going on.

I think that if we were going to follow a style guideline, class <<
self is more consistent. It leaves less decisions to the programmer,
less opportunity to make things messy, and is more powerful. Some
people have a harder time grasping nesting and some people have a
harder time with less consistent code. Choose your poison.
>
>> module methods have encapsulated state.
>
> Probably 99% of the (non-framework) class methods I've seen have no state.
Thats interesting. I can't give you a percentage, but I often either
see state, class methods referencing other class methods (which gets
very confusing with def self.method_name btw) and passing along the
same arguments.
>
>> We all have seen YAGNI
>> bite us in the ass too, especially when it means turning off the
>> brain. I don't think 2 extra filler lines of code make that strong of
>> an argument, when there is more than one class method (and even if
>> there is one class method IMO).
>
> If writing those two lines of code are unnecessary for any of the uses you
> and others have described, I would call that turning off the brain. :)
I just explained that its a trade-off, so you can choose to ignore the
trade-off. I'll let you think about that one.
I suppose that we can write our entire program with one LOC. I suppose
thats following YAGNI. Hell, why use do end? Its two extra lines of
code all over the place.
We can also remove lines of code by using ; everywhere. No more
newlines. Awesome :)
>
>>
>> I think we also like how consistent conventions and delineation of
>> responsibility make code faster to read and understand.
>
> Agreed, but I think this begs the question under discussion.
I don't follow. Can you clarify?
>
> ///ark
>
> (For those who are tired of this non-RSpec-related discussion (but
> apparently find themselves forced to read it), I really will try to wrap up
> my contribution. I don't have the time for the Ruby list, so this is the
> only place I have to talk about fun stuff like this. ObRSpec: the discussion
> did illuminate a situation where tests can pass but the development app can
> fail - when using class variables in RoR.)
Yeah, state in class
Mark W. (Guest)
on 2008-11-28 03:27
(Received via mailing list)
On Thu, Nov 27, 2008 at 5:12 PM, Brian T.
<removed_email_address@domain.invalid>wrote:


> I suppose that we can write our entire program with one LOC. I suppose
> thats following YAGNI. Hell, why use do end? Its two extra lines of
> code all over the place.


That's not YAGNI. :) We need clarity now - there's no 'gonna' about it.
I
was responding to the idea that we should always use class << self in
case
we need the construct later.


> >> I think we also like how consistent conventions and delineation of
> >> responsibility make code faster to read and understand.
> >
> > Agreed, but I think this begs the question under discussion.
> I don't follow. Can you clarify?
>

I just thought the statement above assumes the issues in contention in
order
to bolster its argument. It assumes that using def self.foo is not a
consistent convention and doesn't delineate responsibility. That's not a
given - it's one of the things we're discussing.

///ark
Brian T. (Guest)
on 2008-11-28 03:57
(Received via mailing list)
On Thu, Nov 27, 2008 at 8:27 PM, Mark W. <removed_email_address@domain.invalid> 
wrote:
> we need the construct later.
Great. That makes sense to me and I agree. Thanks for clarifying.
> consistent convention and doesn't delineate responsibility. That's not a
> given - it's one of the things we're discussing.
Ok, I think class << self is more consistent, because you can use the
same idioms as in class Foo. You cannot when using def
self.method_name.
I find that many of Ruby's class stuff (@@ variables,
private_class_method, etc) as having to learn more stuff which I don't
want to care about.

I'm wondering if this is a discussion about taste. I have my
experience with both approaches and you have yours. Just because
something works better for you does not mean its going to work better
for me and vice versa. I know that using class << self has been very
helpful in making my design better and it helps me to understand the
code vs the def self.method_name.
I see def self.method_name as a useful shortcut in irb or when there
are few (0 to many depending on the person and situation) simple
methods on the class. There is a point to where it, IMO, makes the
code more difficult to understand, though.
Mark W. (Guest)
on 2008-11-28 04:18
(Received via mailing list)
On Thu, Nov 27, 2008 at 5:57 PM, Brian T.
<removed_email_address@domain.invalid>wrote:

>
> I'm wondering if this is a discussion about taste.


I think you're right. I've been using the 'def self.foo' style in
various
languages for almost 20 years, so of course it feels more natural to me.
These languages (except for Smalltalk) had nowhere near the
metaprogramming
capability nor 'objects all the way down'-ness of Ruby, and 'class <<
self'
is one of those things.

///ark
Zach D. (Guest)
on 2008-11-28 13:13
(Received via mailing list)
On Thu, Nov 27, 2008 at 12:52 PM, Nathan Zook
<removed_email_address@domain.invalid> wrote:
> That's not a surprise, that's a feature. Know the difference between class
> variables and class instance variables.

Said the preacher to the choir.

But even features can cause surprises. It's a surprise when you're the
consumer of someone else's code. For example, this problem used to
exist in Rails:

   ActionMailer::Base.smtp_settings = { some_config_settings }

Then to give a particular mailer subclass different smtp settings,
this seemed like a logical thing to do:

   class MyMailer  < ActionMailer::Base ; end
   MyMailer.smtp_settings = { my_other_config }

I was a bit surprised when it overrode the smtp settings for every
single mailer, when I expected the change to just go to MyMailer's
smtp_settings. This and many others like it have since been fixed in
Rails, but Rails is not the only code I've seen do this.

Realistically it may take people using class variables incorrectly to
see they really wanted a class instance variable. Hopefully these
discussions help inform people before they have to make that mistake
in code they are writing,

Zach


>> class A
>> class C < B ; end
>>
>> class B < A ; end
>>
>>
>



--
Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com
David C. (Guest)
on 2008-11-28 18:54
(Received via mailing list)
On Thu, Nov 27, 2008 at 8:17 PM, Mark W. <removed_email_address@domain.invalid> 
wrote:
>
> ///ark

FWIW, the blog that led to this discussion suggested a performance
impact as well. As RSpec has gotten dinged for being slower than
alternatives, that interested me, so I did a little experiment def'ing
methods 10k times with def self.method and class << self; def method
....

def self.method ran an average of 10% faster.

Based on just that, I've all but eliminated class << self from rspec in
git.

Crazy?
Student J. (Guest)
on 2008-11-28 20:19
(Received via mailing list)
Performance is one of those nasty things that can go from being a non-
issue to THE issue (next to correctness) in the blink of an eye.  I am
curious, however.  How much total performance difference did this
change make?  I'm betting <1%.

Nathan

David C. wrote:
>> ///ark
>
> Crazy?
Scott T. (Guest)
on 2008-11-28 23:30
(Received via mailing list)
On Nov 28, 2008, at 11:52 AM, David C. wrote:

>> to me.
> alternatives, that interested me, so I did a little experiment def'ing
> methods 10k times with def self.method and class << self; def method
> ....
>

I'd be curious to see those benchmarks.

Also - re: performance: I've always wondered why RSpec (and other
ruby projects, for that matter) aren't using Kernel#autoload instead
of Kernel#require.   If we used autoload, we wouldn't have to load
the code for, say, a matcher which is never used in a project.

Scott
aslak hellesoy (Guest)
on 2008-11-28 23:59
(Received via mailing list)
On Fri, Nov 28, 2008 at 10:28 PM, Scott T. <
removed_email_address@domain.invalid> wrote:

>>>>
>>>
> Also - re: performance: I've always wondered why RSpec (and other ruby
> projects, for that matter) aren't using Kernel#autoload instead of
> Kernel#require.   If we used autoload, we wouldn't have to load the code
> for, say, a matcher which is never used in a project.
>

I didn't even know about that method. I don't think I've ever seen it
used.
I'll definitely try it out.

Cheers,
Aslak
Brian T. (Guest)
on 2008-11-29 21:21
(Received via mailing list)
On Fri, Nov 28, 2008 at 1:17 PM, Student <removed_email_address@domain.invalid>
wrote:
> Performance is one of those nasty things that can go from being a non-
> issue to THE issue (next to correctness) in the blink of an eye.  I am
> curious, however.  How much total performance difference did this
> change make?  I'm betting <1%.
Yeah, this seems like premature optimization, if this were the only
reason. Rspec does not call class << foo nearly 10000 times.
Even if rspec did use class << foo 10000 times (each of which can
define multiple methods), it would make 0.x seconds of a difference in
the worst case (each class << object block only defines one method)
and 0.0x seconds difference in the best case (one object with 10000
methods defined in it).

http://gist.github.com/30285

Here are my numbers where method is defined on a single object 10000
times:
http://gist.github.com/raw/30285/a1731a82a0a59ec12...

Heres another interesting benchmark where method is defined on 10000
objects 1 time:
http://gist.github.com/raw/30285/a99305dbeef2aed84...
Brian T. (Guest)
on 2008-11-29 21:30
(Received via mailing list)
On Fri, Nov 28, 2008 at 4:28 PM, Scott T.
<removed_email_address@domain.invalid> wrote:
>>> I think you're right. I've been using the 'def self.foo' style in various
>> impact as well. As RSpec has gotten dinged for being slower than
>> alternatives, that interested me, so I did a little experiment def'ing
>> methods 10k times with def self.method and class << self; def method
>> ....
>>
>
> I'd be curious to see those benchmarks.
Here are some benchmarks I did.
Brian T. (Guest)
on 2008-11-29 21:31
(Received via mailing list)
On Sat, Nov 29, 2008 at 2:28 PM, Brian T. <removed_email_address@domain.invalid>
wrote:
>>>>> I'm wondering if this is a discussion about taste.
>>>
>>> FWIW, the blog that led to this discussion suggested a performance
>>> impact as well. As RSpec has gotten dinged for being slower than
>>> alternatives, that interested me, so I did a little experiment def'ing
>>> methods 10k times with def self.method and class << self; def method
>>> ....
>>>
>>
>> I'd be curious to see those benchmarks.
> Here are some benchmarks I did.
Duh, I didn't paste the link;
http://gist.github.com/30285
Scott T. (Guest)
on 2008-11-29 21:56
(Received via mailing list)
On Nov 29, 2008, at 2:19 PM, Brian T. wrote:

> Even if rspec did use class << foo 10000 times (each of which can
> define multiple methods), it would make 0.x seconds of a difference in
> the worst case (each class << object block only defines one method)
> and 0.0x seconds difference in the best case (one object with 10000
> methods defined in it).

Most certainly.  Although there are certainly other performance
optimizations which would be easy to do, and it would be hard to
calculate how much time they actually cost.  For instance, using
"return" actually performs a C longjmp (and the ruby interpreter does
nothing to remove return from the last statement in a method), so
it's more efficient to avoid it - but how much could it really shave
off a user's test suite time?

In this respect, RSpec can be seen more as library then an end-user
program, and it's hard to anticipate *exactly* how the library is
going to be used.  For instance, maybe mocks are barely used, but
certain matchers are used heavily.  With a large enough test suite
and some good performance analysis these bottlenecks would become
clear, *BUT* the slowdown would be dependent on the *nature* of the
test suite.

Scott
Matt W. (Guest)
on 2008-11-30 23:33
(Received via mailing list)
On 28 Nov 2008, at 16:52, David C. wrote:

>> to me.
> alternatives, that interested me, so I did a little experiment def'ing
> methods 10k times with def self.method and class << self; def method
> ....
>
> def self.method ran an average of 10% faster.
>
> Based on just that, I've all but eliminated class << self from rspec
> in git.
>
> Crazy?

I think so.

I think Brian has argued eloquently that class << self leaves more
readable and maintainable code behind. I don't know the RSpec code
very well, but I'd be surprised if the number of class methods used
would be significant enough that speeding them up will cause a
noticeable increase in the performance of RSpec overall, and it might
make the project harder to hack on, which would be a shame.

We have just under 4000 examples in the songkick code, taking about 7
minutes to run. If I get a chance I'll try out both forks and see if I
can get you some stats.

Matt W.
removed_email_address@domain.invalid
Avdi G. (Guest)
on 2008-11-30 23:41
(Received via mailing list)
On Sun, Nov 30, 2008 at 4:30 PM, Matt W. <removed_email_address@domain.invalid> 
wrote:
> I think Brian has argued eloquently that class << self leaves more readable
> and maintainable code behind.

I don't think so.  Nothing that has been said here has changed my
feeling that using class << self for class methods is an overly-clever
hack that makes it impossible to tell whether you're looking at a
class or instance method in any class more than a page long.  There's
a reason Matz recommends against it, and a reason we recommend against
it in our codebase where I work.  This isn't just esthetics - I've
seen my own code comprehension speed noticeably diminished by files
where I had to keep scrolling up and down to keep track of what kind
of method I was looking at.  If you keep all your classes to under a
page in length, good for you; but most Ruby programmers don't have
that discipline in my experience.  I don't think it's a practice worth
promulgating.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
Avdi G. (Guest)
on 2008-11-30 23:46
(Received via mailing list)
On Sun, Nov 30, 2008 at 4:39 PM, Avdi G. <removed_email_address@domain.invalid> 
wrote:
>  I don't think it's a practice worth promulgating.

...not to mention that most noob Ruby programmers learned to use def
self.foo (or def ClassName.foo, if they are reading the 1st edition
pickaxe online), and coming across that class << self block is
confusing and gives them the (false) idea they have to understand
about singleton classes just to comprehend what's going on in the
code.  Keep it simple.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
Peter J. (Guest)
on 2008-12-01 05:14
(Received via mailing list)
On Wed, Nov 26, 2008 at 11:51 AM, Mark W. <removed_email_address@domain.invalid> 
wrote:

> And class variables are problematic in Rails in development mode because of
> class reloading.

Yes.  They are.

http://www.flickr.com/photos/peeja/3056849146/

Peter
Mark W. (Guest)
on 2008-12-03 00:33
(Received via mailing list)
Here's what The Ruby P.ming Language says about this:

"In general, it is clearer to define class methods as individual
singleton
methods without explicitly opening the eigenclass" (p. 258)

This is far from a blanket condemnation, and, as with the rest of the
book,
it's not obvious whether it's Matz or (non-Rubyist) Flanagan who's
talking.

I don't mean to "open" the discussion again. :)

///ark
Matt W. (Guest)
on 2008-12-03 13:25
(Received via mailing list)
On 2 Dec 2008, at 22:31, Mark W. wrote:

> Here's what The Ruby P.ming Language says about this:
>
> "In general, it is clearer to define class methods as individual
> singleton methods without explicitly opening the eigenclass" (p. 258)
>
> This is far from a blanket condemnation, and, as with the rest of
> the book, it's not obvious whether it's Matz or (non-Rubyist)
> Flanagan who's talking.
>
> I don't mean to "open" the discussion again. :)

Thanks for following up Mark.

I suggest that if there's any life left in this thread, it staggers
over here for a few more rounds:
http://blog.mattwynne.net/2008/12/01/in-defence-of-class/

Matt W.
http://blog.mattwynne.net
http://www.songkick.com
Pat M. (Guest)
on 2008-12-04 08:04
(Received via mailing list)
> 'look at me, ma, I'm opening the eigenclass!'

"Honey, if you're going to open your eigenclass, do it in your room."
Rick D. (Guest)
on 2008-12-04 21:20
(Received via mailing list)
On Thu, Dec 4, 2008 at 1:04 AM, Pat M. <removed_email_address@domain.invalid> 
wrote:

> > 'look at me, ma, I'm opening the eigenclass!'
>
> "Honey, if you're going to open your eigenclass, do it in your room."
>

And if you keep doing it, you'll go blind!

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RubyRedRick
This topic is locked and can not be replied to.