Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class vs Module in designing Ruby API?

When I read more about Ruby metaprogramming, most of the time we found at least two solutions to solve a problem. Please look at two examples below:

class Base
  def self.has_many(*args)
    # ...
  end
end

class Student < Base
  has_many :books
end

Another style:

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

  module ClassMethods
    def has_many(*args)
      # ...
    end
  end
end

class Student
  include Base

  has_many :books
end

But when we design api, we have to decide which one to use, but I would like to ask your ideas and some of best practices that most people have already implemented in their libraries.

like image 474
Samnang Avatar asked Nov 02 '10 04:11

Samnang


3 Answers

If your API is providing the base functionality which will be extended by the client, then you should prefer inheritance.

If your API is going to extend various clients with their own base functionality, then you should go for composition.

like image 176
edgerunner Avatar answered Nov 03 '22 20:11

edgerunner


You've got a lot of theories around that question.

I tend to prefer composition because it makes behavior a lot more reusable that way but if you look at Rails, you'll have to subclass ActiveRecord::Base class every time you want to an object in your database. If you look at DataMapper, it's the opposite as they just required you to include DataMapper::Resource.

Inheritance vs Composition (via modules) is a big topic and the question you'll have to ask yourself will come down to: how can I achieve the greater decoupling between the components I provide and another user existing code base?

like image 30
Franck Verrot Avatar answered Nov 03 '22 20:11

Franck Verrot


Ruby supports single inheritance only. Therefore if API client must inherit your base class, they lose the ability to inherit other classes. Using module inclusion you make possible a code like:

class Student < Person
  include Base
  has_many :books
end

And thus you can "inherit" both Person and Base.

However, classical inheritance syntax looks more natural and less "magic"

like image 36
paradigmatic Avatar answered Nov 03 '22 18:11

paradigmatic