DEV Community

Burdette Lamar
Burdette Lamar

Posted on

Prefer Ruby Class Method or Mix-In Instance Method?

Assume that a certain functionality is available in Ruby both as a class method and as an instance method (via a module).

Class method:

require 'foo'  
Foo.foo()  
Enter fullscreen mode Exit fullscreen mode

Instance method (via module):

require 'bar'    
include Bar    
bar()    
Enter fullscreen mode Exit fullscreen mode

Assuming that the two methods behave identically, which would you prefer using, and why?

(Note that the question is not about which to implement, but instead about which to use if both available.)

Top comments (3)

Collapse
 
thorstenhirsch profile image
Thorsten Hirsch

A require 'foo' does not alter your class. It just gives you access to call Foo.foo(). There's nothing happening in terms of inheritance or composition. It's maybe the simplest form of dependency between your class and Foo. If you only want to call one method or another in Foo, then yes, that's the way to go.

But when calling include Bar there's a lot happening. You not only get access to bar(), but also to all other methods that are in Bar. And they are directly available in the namespace of your instance. And maybe even class methods have been defined, so the include might have also given you YourClass.baz(). You better know exactly what's in Bar, because your class might get cluttered with a lot of stuff... it's actually pretty similar to inheritance. So the actual question when it comes to include is: ruby inheritance vs. mixins. And I like this answer very much:

Modules are for sharing behavior, while classes are for modeling relationships between objects.

So back to your question - you should use include when you want your class to get (all) the behaviour the module gives you. And you should not use it if you just want to call a method.

Collapse
 
briankephart profile image
Brian Kephart

I would prefer the first, because calling Foo.foo clearly shows the receiver of the method, and I know that bar is probably defined in foo.rb.

In the second example, it's less clear where bar is defined. Ok, it's clear in your example, but in a situation where the names aren't so simple, bar might be defined in the current class, or bar.rb, or any other module that's mixed into the current class, or all three.

Collapse
 
michaelglass profile image
Michael Glass • Edited

I think the include is most useful as used in Enumerable, e.g. a base class implements a few simple methods, and then by including a module that leverages those simple methods, gets a lot of syntactic sugar on top.

class methods, (consider prefixing your module with module_function and all methods will be accessible as class methods) are a way of pushing Ruby to be more functional.

It's not one vs the other, but rather, two different tools wrapped in one name, module.

Generally, though, I agree with some of the other commenters that class methods are king. But also: if you're going to lean on class methods so much, it might make sense to try to use another language that enforces those patterns, e.g. most functional programming languages. Elixir? Elm?