Do I overuse class methods?

Hello,
I write in ruby for few weeks and I have noticed that in ruby I use class (static) methods more often than in "traditional" languages like java or c#. In java I use instance methods for two purposes - maintaining object state and to use polymorphic behaviour. In ruby polymorphism is available to class methods as well as for instance ones so I don't see need for using instance methods in stateless classes (for example typical application / domain services).

It is common for ruby programmers or maybe I have miss something?

Best Regards,
Michał

Classes are designed to instantiate objects. If you have classes that consist solely of class methods then they aren't functioning as classes at all but rather as convenient globally-available namespaces for singleton methods, which is a very procedural style of progrmaming. Procedural programming is not necessarily bad, but you are missing out on a great deal of the power and flexibility of an OOP langauge by writing procedural code.

Then again, if the system works for you and maintainability and other core values do not appear to suffer, who's to say you're doing it wrong? Even asking the question shows that you're thinking critically about the tradeoffs involved here, which is a good start.

···

On 2010-06-13 10:27:48 -0700, Michał Zając said:

Hello,
I write in ruby for few weeks and I have noticed that in ruby I use class (static) methods more often than in "traditional" languages like java or c#. In java I use instance methods for two purposes - maintaining object state and to use polymorphic behaviour. In ruby polymorphism is available to class methods as well as for instance ones so I don't see need for using instance methods in stateless classes (for example typical application / domain services).

It is common for ruby programmers or maybe I have miss something?

Best Regards,
Michał

--
Rein Henrichs

http://reinh.com

I write in ruby for few weeks and I have noticed that in ruby I use class
(static) methods more often than in "traditional" languages like java or c#.
In java I use instance methods for two purposes - maintaining object state
and to use polymorphic behaviour. In ruby polymorphism is available to class
methods as well as for instance ones so I don't see need for using instance
methods in stateless classes (for example typical application / domain
services).

It is common for ruby programmers or maybe I have miss something?

Classes are designed to instantiate objects. If you have classes that
consist solely of class methods then they aren't functioning as classes at
all but rather as convenient globally-available namespaces for singleton
methods, which is a very procedural style of progrmaming. Procedural
programming is not necessarily bad, but you are missing out on a great deal
of the power and flexibility of an OOP langauge by writing procedural code.

As a compromise Michael could use module Singleton and thus define
instance methods without the overhead of creating new instances all
the time.

irb(main):001:0> require 'singleton'
=> true
irb(main):002:0> class Foo;end
=> nil
irb(main):003:0> (1..3).map { Foo.new }
=> [#<Foo:0x1029b494>, #<Foo:0x1029b478>, #<Foo:0x1029b45c>]
irb(main):004:0> class Foo; include Singleton; end
=> Foo
irb(main):005:0> (1..3).map { Foo.new }
NoMethodError: private method `new' called for Foo:Class
        from (irb):5:in `block in irb_binding'
        from (irb):5:in `each'
        from (irb):5:in `map'
        from (irb):5
        from /opt/bin/irb19:12:in `<main>'
irb(main):006:0> (1..3).map { Foo.instance }
=> [#<Foo:0x10268b88>, #<Foo:0x10268b88>, #<Foo:0x10268b88>]
irb(main):007:0>

Singleton pattern allows for easier migration if at a later point in
time instances need state.

Then again, if the system works for you and maintainability and other core
values do not appear to suffer, who's to say you're doing it wrong? Even
asking the question shows that you're thinking critically about the
tradeoffs involved here, which is a good start.

Absolutely agree!

Kind regards

robert

···

2010/6/14 Rein Henrichs <reinh@reinh.com>:

On 2010-06-13 10:27:48 -0700, Michał Zając said:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

W dniu 2010-06-14 15:33, Robert Klemme pisze:

As a compromise Michael could use module Singleton and thus define
instance methods without the overhead of creating new instances all
the time.

I think this is interesting idea.
I have spent much time in Java / C# environments with heavy use of dependency injection pattern so maybe this is source of my aversion to stateless classes manual instantiation - usually something else has done it for me :smiley: Using Singleton pattern is more similar to Service Locator but it may be good alternative.

Thanks

Ruby's design patterns (in the Gang of Four sense) are extremely lightweight compared to their Java equivalents. Rick Olsen's Design Patterns in Ruby book shows good idiomatic Ruby implementations of the GoF patterns. That said, I don't think you want a Pattern at all. I think you want a more *object oriented* architecture.

IRT Singleton: I think that Singleton is just a way to cheat and get global state that looks like instances. I didn't present it as a solution because (imo) it's really just a restatement of the problem. I try to avoid it for the same reasons that I try to avoid the classes you're asking about. Let me put it this way: replace all of your pseudo-classes (these classes that don't instantiate and are used as singleton method holders) with this:

YourClass = Object.new

def YourClass.some_method
  ... do stuff ...
end

... more ...

This is functionally equivalent. Does this look like good Ruby code? Is this good OO design? If not, why not? The classes you're asking about aren't (functionally) classes at all: they're just objects like this one. You should object to them for the same reasons that you (may) object to the above.

Also, Ruby has far better mechanisms than dependency injection. So much so, in fact, that Rails core member and creator of two different Ruby dep. injection libraries, Jamis Buck, recently gave a great talk about why you don't need dependency injection in Ruby. Summary is here, and is a good read if you're coming from heavy, "enterprisey" languages like Java: http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming\.

Coming from a Java background, the best thing you can do is let go of the heavy pattern-driven architectures that are common in enterprise-land (the ServiceLocator, CachedTemplateFactoryProxyFactory, whatever) and enjoy the freedom of working with simple, lightweight classes and objects.

···

On 2010-06-14 10:35:10 -0700, Michał Zając said:

W dniu 2010-06-14 15:33, Robert Klemme pisze:

As a compromise Michael could use module Singleton and thus define
instance methods without the overhead of creating new instances all
the time.

I think this is interesting idea.
I have spent much time in Java / C# environments with heavy use of dependency injection pattern so maybe this is source of my aversion to stateless classes manual instantiation - usually something else has done it for me :smiley: Using Singleton pattern is more similar to Service Locator but it may be good alternative.

Thanks

--
Rein Henrichs

http://reinh.com

W dniu 2010-06-15 01:06, Rein Henrichs pisze:

Let me put it this way: replace all of your

pseudo-classes (these classes that don't instantiate and are used as
singleton method holders) with this:

YourClass = Object.new

def YourClass.some_method
... do stuff ...
end

... more ...

This is functionally equivalent. Does this look like good Ruby code? Is
this good OO design? If not, why not? The classes you're asking about
aren't (functionally) classes at all: they're just objects like this
one. You should object to them for the same reasons that you (may)
object to the above.

I can't agree that using such classes is _always_ bad design. In well designed systems there is a place for stateless classes too (of course they are in minority). They main responsibility is not to encapsulate data but encapsulate dependencies - for example AbstractSmtpClient which encapsulates (wrapes) concrete SMTP client implementation. In Java this kind of encapsulation is needed to unit test classes those use SMTP communication. But what is more important to me is responsibility separation (SRP) - actual business code doesn't have to create and configure SMTP client - it just gets ready for use AbstractSmtpClient object from outside (not necessary from heavy weight DI framework).

Back to your question - maybe it is _functionally_ equivalent of defining methods inline one by one but it is not eqivalent in terms of code readability (in my "psuedo-classes" I separated code that you have mixed in one class) in this way we can treat every program (even written in ruby) as "functionally equivalent" of assembler or I have misunderstood your example :smiley:

Also, Ruby has far better mechanisms than dependency injection. So much
so, in fact, that Rails core member and creator of two different Ruby
dep. injection libraries, Jamis Buck, recently gave a great talk about
why you don't need dependency injection in Ruby. Summary is here, and is
a good read if you're coming from heavy, "enterprisey" languages like
Java: http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming\.

I never treat DI and automatic DI frameworks as the same thing - and I repeat it to every programmer I am working with :slight_smile: Due to better language mechanisms (open classes) in ruby we can make dependency injection as described in article. What I like less is mixing business code and collaborators construction (new calls) in one physical code unit.

···

--
Best regards

I would prefer that you use modules for "stateless classes" that you don't initialize. Modules are semantically for use in both "mixins" and namespacing, and the namespacing here is an appropriate use. They also don't share the semantic baggage that classes do (initialization) for this use.

···

On 2010-06-16 11:48:32 -0700, Michał Zając said:

W dniu 2010-06-15 01:06, Rein Henrichs pisze:

Let me put it this way: replace all of your

pseudo-classes (these classes that don't instantiate and are used as
singleton method holders) with this:

YourClass = Object.new

def YourClass.some_method
... do stuff ...
end

... more ...

This is functionally equivalent. Does this look like good Ruby code? Is
this good OO design? If not, why not? The classes you're asking about
aren't (functionally) classes at all: they're just objects like this
one. You should object to them for the same reasons that you (may)
object to the above.

I can't agree that using such classes is _always_ bad design. In well designed systems there is a place for stateless classes too (of course they are in minority). They main responsibility is not to encapsulate data but encapsulate dependencies - for example AbstractSmtpClient which encapsulates (wrapes) concrete SMTP client implementation. In Java this kind of encapsulation is needed to unit test classes those use SMTP communication. But what is more important to me is responsibility separation (SRP) - actual business code doesn't have to create and configure SMTP client - it just gets ready for use AbstractSmtpClient object from outside (not necessary from heavy weight DI framework).

Back to your question - maybe it is _functionally_ equivalent of defining methods inline one by one but it is not eqivalent in terms of code readability (in my "psuedo-classes" I separated code that you have mixed in one class) in this way we can treat every program (even written in ruby) as "functionally equivalent" of assembler or I have misunderstood your example :smiley:

Also, Ruby has far better mechanisms than dependency injection. So much
so, in fact, that Rails core member and creator of two different Ruby
dep. injection libraries, Jamis Buck, recently gave a great talk about
why you don't need dependency injection in Ruby. Summary is here, and is
a good read if you're coming from heavy, "enterprisey" languages like
Java: http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming\.

I never treat DI and automatic DI frameworks as the same thing - and I repeat it to every programmer I am working with :slight_smile: Due to better language mechanisms (open classes) in ruby we can make dependency injection as described in article. What I like less is mixing business code and collaborators construction (new calls) in one physical code unit.

--
Rein Henrichs

http://reinh.com