20 July 2011

Are class methods evil?

Nick Sutterer who is honorable citizen of my city
published a post Are class methods evil?
It’s really worth reading as he mentions couple of important aspects of Object Oriented approach and how they
are used by Rails community.

I’m more and more against using class methods. It often leads to procedural-like programming.

Why class methods?

I often hear “Why to create an object when I can just call a class method?”.
The reasoning behind that is quite obvious:

1) shorter code

2) less objects = less GC

3) stateless behavior and no need to initialization

1) and 2) are completely valid arguments. However in my opinion these arguments shouldn’t impose the architecture.
My main objection is assumption that given behavior is stateless thus doesn’t need to be encapsulated in object.

Stateless vs Stateful

Class methods are executed in context of their arguments

Instance methods, in addition to arguments, are executed in context of state of the object

Of course there are more differences but from my point of view that one is quite significant.

Using class methods means we can’t keep a state thus the state must be passed in method arguments.
If some module is designed around class methods we deal with procedural-like programming
passing arguments from one method to another.

Naturally the state may be kept in class variables but it’s introducing a global state
which as Nick remarks should be abandoned.

Initialization process and keeping a state isn’t useless even in such a
simple example.
At the first sight it may seem awkward to use an object when class
method can be used more easily.
Although it’s often a trap. The bigger codebase the more time needed
to maintain a procedural code.

I prefer to think in object oriented manner from the ground up.
It is like MVC a bit harder at the beginning but it quickly starts to pay for itself.

ActiveRecord

In his article Nick shows some examples of ActiveRecord usage.
It is hard to avoid class methods due to ActiveRecord design but
Andrzej Krzywda showed how to deal with it. I recommend
reading his article.

UPDATE

Everything is an object

Rubyists like to emphasize that in their favorite programming language everything is an object.
It’s not like C++ or JAVA which are “not fully object oriented”.
But that fact is often forgotten and misunderstood.
I think utility methods are a great example.

Is someting wrong with that code?

Math.sin(2)*Math::PI

In that case we don’t use the fact the number 2 is an object in Ruby.
It’s used like a primitive. This is how we do it in C++.

2.sin*Math::PI

Of course Fixnum doesn’t have sin method. But we can extend Fixnum to provide
it. Monkey patching Fixnum is harmful but there are plenty of other options