Defining class methods

Discussion in 'Ruby' started by Tony Arcieri, Feb 16, 2011.

  1. Tony Arcieri

    Tony Arcieri Guest

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

    It seems there are 3 ways of defining class methods (at least in common
    usage):

    1) Defining a method on self:

    def self.method

    2) Opening up self and defining the methods directly:

    class << self
    def method
    ...
    end

    3) Placing class methods into a module, and extending a class with that:

    module ClassMethods
    def method
    ...
    end

    extend ClassMethods

    --

    Which of these do you use and which do you prefer? Do you use all three? Do
    you think class << self is fugly and confusing?

    I used to use class << self quite frequently and have been shifting to using
    modules when dealing with a large number of class methods. I can't really
    say I'm a huge fan.

    --
    Tony Arcieri
    Medioh! Kudelski
    Tony Arcieri, Feb 16, 2011
    #1
    1. Advertising

  2. On Thu, Feb 17, 2011 at 1:17 AM, Tony Arcieri <> wro=
    te:
    > It seems there are 3 ways of defining class methods (at least in common
    > usage):
    >
    > 1) Defining a method on self:
    >
    > def self.method
    >
    > 2) Opening up self and defining the methods directly:
    >
    > class << self
    > =A0def method
    > =A0...
    > end
    >
    > 3) Placing class methods into a module, and extending a class with that:
    >
    > module ClassMethods
    > =A0def method
    > =A0...
    > end
    >
    > extend ClassMethods
    >
    > --
    >
    > Which of these do you use and which do you prefer? Do you use all three? =

    Do
    > you think class << self is fugly and confusing?


    I use all three, depending on the situation. Generally, I use method 2
    (class << self), but if I have an idea that I will be needing only
    one, or two class methods (like Module.included) I use method 1 (def
    self.foo). If it makes sense to separate the class methods from the
    core definition of a class (like helper/utility functions), I define
    them in a module in a separate file.

    I do not find class << self to be ugly and confusing :).

    I picked up the following pattern going through DataMapper's code (or,
    was it Ruby Best Practices?).

    module Foo
    def instance_method; puts "im"; end

    module ClassMethods
    def class_method1; puts "cm" end
    end

    def self.included(klass)
    klass.extend(ClassMethods)
    end
    end

    class Moo
    include Foo
    end

    Foo.class_method #=3D> cm
    Foo.new.instance_method #=3D> im
    Foo.new.class_method #=3D> NoMethodError

    A use case of this pattern for me was defining a Helper module for
    Sinatra (modular) app where some helpers will be used in the
    request-response context, while some in the context of the class that
    inherits from Sinatra::Base.

    --=20
    Anurag Priyam
    http://about.me/yeban/
    Anurag Priyam, Feb 16, 2011
    #2
    1. Advertising

  3. Tony Arcieri

    Avdi Grimm Guest

    On Wed, Feb 16, 2011 at 4:37 PM, Anurag Priyam <> wrote:
    >> 1) Defining a method on self:
    >>
    >> def self.method


    This one. That way you can always tell simply by looking at the method
    definition that it is a class/module-level method.
    Avdi Grimm, Feb 17, 2011
    #3
  4. Tony Arcieri

    botp Guest

    On Thu, Feb 17, 2011 at 3:47 AM, Tony Arcieri <> wrote:
    > It seems there are 3 ways of defining class methods (at least in common
    > usage):
    >
    > 1) Defining a method on self:
    > 2) Opening up self and defining the methods directly:
    > 3) Placing class methods into a module, and extending a class with that:


    4) Explicit definition

    def C.m
    ...
    end

    i usually use this one since
    1 it's visibly specified. The definition matches the use.
    2 don't need to press pgup just to see who is self :)
    3 if i change class name, it self checks itself since i need to retype.
    4 less prone to self abuse :)

    best regards -botp


    best regards -botp
    botp, Feb 17, 2011
    #4
  5. Tony Arcieri

    Avdi Grimm Guest

    On Wed, Feb 16, 2011 at 9:55 PM, botp <> wrote:
    > 4) Explicit definition
    >
    > def C.m
    > ...
    > end


    I avoid this one because it makes class renames more of a chore.

    --
    Avdi Grimm
    Avdi Grimm, Feb 17, 2011
    #5
  6. Tony Arcieri

    botp Guest

    On Thu, Feb 17, 2011 at 11:14 AM, Avdi Grimm <> wrote:
    > I avoid this one because it makes class renames more of a chore.


    Indeed. and that's what i like i about it. makes me think more on the
    value of naming :)

    best regards -botp
    botp, Feb 17, 2011
    #6
  7. > It seems there are 3 ways of defining class methods (at least in common
    > usage):


    There's lots of ways to add a class method; Ruby is not a very
    prescriptive language. Two more interesting examples that are used:
    there's `instance_eval` on a Class instance:

    X = Class.new
    X.instance_eval do
    def foo; "calling #foo!"; end
    end

    X.foo
    # => "calling #foo!"

    or #class_eval on the class of your `Class` instance (which will be `Class`):

    X.class.class_eval do
    def bar; "calling #bar!"; end
    end

    X.bar
    # => "calling #bar!"

    It's not very complicated, but `class_eval` on a Class instance is
    typically used only in some rather advanced (and/or cryptic)
    metaprogramming, so you don't see it floating around a lot.

    ~ jf
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/



    On Wed, Feb 16, 2011 at 21:55, botp <> wrote:
    > On Thu, Feb 17, 2011 at 3:47 AM, Tony Arcieri <> wrote:
    >> It seems there are 3 ways of defining class methods (at least in common
    >> usage):
    >>
    >> 1) Defining a method on self:
    >> 2) Opening up self and defining the methods directly:
    >> 3) Placing class methods into a module, and extending a class with that:

    >
    > 4) Explicit definition
    >
    > def C.m
    > ...
    > end
    >
    > i usually use this one since
    > 1 it's visibly specified. The definition matches the use.
    > 2 don't need to press pgup just to see who is self :)
    > 3 if i change class name, it self checks itself since i need to retype.
    > 4 less prone to self abuse :)
    >
    > best regards -botp
    >
    >
    > best regards -botp
    >
    >
    John Feminella, Feb 17, 2011
    #7
  8. I don't mean it as a put-down; I suspect the only person I'm putting down is myself. But I don't find that class methods actually come up much in my Ruby coding; when I find myself coding one I tend to stop and think hard about whether I actually need it.

    And when I do use one it's always your type (1). Why would I want to define a class method anywhere else but in the class? I do understand that for DSLs, all the rest of this syntax is really useful. But -- showing my ignorance here -- is it really of any practical value elsewhere?

    --
    A boss with no humor is like a job that's no fun.
    Shadowfirebird, Feb 17, 2011
    #8
  9. Tony Arcieri

    Avdi Grimm Guest

    On Thu, Feb 17, 2011 at 4:41 AM, Shadowfirebird
    <> wrote:
    > I don't mean it as a put-down; I suspect the only person I'm putting down=

    is myself. =A0 But I don't find that class methods actually come up much i=
    n my Ruby coding; when I find myself coding one I tend to stop and think ha=
    rd about whether I actually need it.

    Indeed. Class methods in Ruby are a code smell: not always wrong, but
    you should always think about why you're choosing a class-level method
    instead of instance-level.

    I think most of the class/module-level methods I write are "macros" -
    e.g. methods along the lines of Ruby's #attr_accessor.

    --=20
    Avdi Grimm
    http://avdi.org
    Avdi Grimm, Feb 17, 2011
    #9
  10. > Indeed. Class methods in Ruby are a code smell: not always wrong, but
    > you should always think about why you're choosing a class-level method
    > instead of instance-level.


    I don't know if I'd go so far as to say they're a code smell. Without
    class methods a number of very useful Ruby DSLs wouldn't exist in
    their current form (RSpec, Cucumber, Rails, etc., just to name a few).
    I agree that they can be abused or misused, but that's true of pretty
    much any construct in any language, isn't it?

    I'd probably arrange my skepticism of a class method from lowest to
    highest in this way, depending on its features:

    * part of a DSL (`describe`, `Before`, `callback { ... }`, etc.)
    * repository pattern (Widget.find(...))
    * factory pattern (Widget.orange # =3D> <orange Widget instance>)
    * method takes more than a parameter or two
    * non-factory class method with variable args
    * instance of the class method's class is in the arguments/params
    list (often very questionable)

    ~ jf
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/



    On Thu, Feb 17, 2011 at 10:03, Avdi Grimm <> wrote:
    > On Thu, Feb 17, 2011 at 4:41 AM, Shadowfirebird
    > <> wrote:
    >> I don't mean it as a put-down; I suspect the only person I'm putting dow=

    n is myself. =C2=A0 But I don't find that class methods actually come up mu=
    ch in my Ruby coding; when I find myself coding one I tend to stop and thin=
    k hard about whether I actually need it.
    >
    > Indeed. Class methods in Ruby are a code smell: not always wrong, but
    > you should always think about why you're choosing a class-level method
    > instead of instance-level.
    >
    > I think most of the class/module-level methods I write are "macros" -
    > e.g. methods along the lines of Ruby's #attr_accessor.
    >
    > --
    > Avdi Grimm
    > http://avdi.org
    >
    >
    John Feminella, Feb 17, 2011
    #10
  11. Tony Arcieri

    Tony Arcieri Guest

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

    On Thu, Feb 17, 2011 at 2:41 AM, Shadowfirebird <>wrote:

    > And when I do use one it's always your type (1). Why would I want to define
    > a class method anywhere else but in the class? I do understand that for
    > DSLs, all the rest of this syntax is really useful. But -- showing my
    > ignorance here -- is it really of any practical value elsewhere?



    Well, more specific than DSLs: metaprogramming, and DSLs that generate code.

    Some of the more abject design patterns, such as the factory pattern, can
    often be avoid thanks to a combination of Ruby's dynamism and class methods.

    The class is also a great place to stick state shared by all instances of
    that class, such as the configuration details for accessing a particular
    network service.

    --
    Tony Arcieri
    Medioh! Kudelski
    Tony Arcieri, Feb 17, 2011
    #11
  12. On Wed, Feb 16, 2011 at 7:47 PM, Tony Arcieri <> wro=
    te:
    > It seems there are 3 ways of defining class methods (at least in common
    > usage):
    >
    > 1) Defining a method on self:
    >
    > def self.method
    >
    > 2) Opening up self and defining the methods directly:
    >
    > class << self
    > =A0def method
    > =A0...
    > end
    >
    > 3) Placing class methods into a module, and extending a class with that:
    >
    > module ClassMethods
    > =A0def method
    > =A0...
    > end
    >
    > extend ClassMethods
    >
    > --
    >
    > Which of these do you use and which do you prefer? Do you use all three? =

    Do
    > you think class << self is fugly and confusing?
    >
    > I used to use class << self quite frequently and have been shifting to us=

    ing
    > modules when dealing with a large number of class methods. I can't really
    > say I'm a huge fan.
    >
    > --
    > Tony Arcieri
    > Medioh! Kudelski
    >


    It depends on whether and how you want to allow methods to be
    overridden. Using #extend and 'def self.xxx' are not the same, viz:

    module A
    def run
    puts "A"
    end
    end

    class Foo
    extend A
    end

    class Bar
    extend A
    end

    Foo.run # =3D> "A"
    Bar.run # =3D> "A"

    module B
    def run
    puts "B"
    end
    end

    class Foo
    def self.run
    puts "foo"
    end
    end

    Foo.extend(B)
    Bar.extend(B)

    Foo.run # =3D> "foo" - extend does not
    override a def self.method
    Bar.run # =3D> "B" - but it does override a
    previously defined extension

    class Foo
    class << self
    def run
    puts "bar"
    end
    end
    end

    Foo.run # =3D> "bar" - using 'class << self;
    def method' ... same as 'def self.method'

    Personally, I've come to prefer using #extend.

    Regards,
    Sean
    Sean O'Halpin, Feb 17, 2011
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. johny smith
    Replies:
    8
    Views:
    395
    Peter Koch Larsen
    Jul 2, 2004
  2. Thomas Heller

    Defining *class* methods on C code

    Thomas Heller, Feb 5, 2004, in forum: Python
    Replies:
    12
    Views:
    511
    Michael Hudson
    Feb 9, 2004
  3. Lord Landon
    Replies:
    1
    Views:
    281
    Peter Otten
    May 4, 2006
  4. Tim Bates
    Replies:
    3
    Views:
    90
    Joel VanderWerf
    Feb 3, 2004
  5. Kenneth McDonald
    Replies:
    5
    Views:
    289
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page