Are modules in ruby only meant to be used when multiple objects require its functionality?
I've read that the main service provided by a module is to contain and group similar functions that are needed by several objects. But is 开发者_如何转开发it a good practice to create a module for something like a parser even if you are certain that only one object will ever require its services?
Modules serve two purposes. The first as you have noted is to allow functionality to be added to a diverse set of classes (diverse meaning outside the inheritance tree). The second an by far more common use is to organize the names space. When you see code like ActiveRecord::Base
or BSON::ObjectID
the authors of these gems have placed their functionality in a module, ActiveRecord
and BSON
respectively, that prevents their class names from conflicting with the applications they are included in or other libraries.
With the parser you mentioned, it sounds to me like you want to construct a singleton class rather then a module.
It can help for organization to create a module even if you are using it in one place. For example you might have a lot of methods that are all related, but not really related to the code you are including the module in. This is similar to the the organization that a class provides, except that a module isn't focused on an object.
main service provided by a module is to contain and group similar functions that are needed by several objects
I would re-word it to "group similar functions that might be needed by at least one object". It's very frequent that you don't know how many classes will end up including or extending a module (for example if you are writing a library)
Independently of that, I see two more "main purposes":
- They are a way to provide scopes (you can package several classes and other modules inside one module).
- They have a callback called
included
. This might seem trivial, but that callback is key in a lot of interesting meta-programming techniques.
I would go for a class (if you got not too much code). Place it under /lib
class Parse
def self.xml(xml_string)
...
end
end
Parse.xml("<xml></xml>")
- You can call it from anywhere.
- http://en.wikipedia.org/wiki/Separation_of_concerns
Modules are indeed a group of similar functions. If you got a lot of parsing code you could do:
class Xml
acts_as_parser
end
class Json
acts_as_parser
end
...
acts_as_parser will load the group of functions from the module.
But is it a good practice to create a module for something like a parser even if you are certain that only one object will ever require its services?
Yes.
In Ruby, modules help a whole lot with separation of concerns and are very good for doing "aspect-oriented" programming (i.e., fun with mixins).
# Basic Hierarchy
class X
def say ; 'X' end
end
class Y < X
def say ; super + 'Y' end
end
y = Y.new
y.say #=> 'XY'
# Throwing in an aspects/mixins
module A
def say ; super + 'A' end
end
class Y
include A
end
y.say #=> 'XAY'
# Throwing in another aspects/mixins
module B
def say ; super + 'B' end
end
class Y
include B
end
y.say #=> 'XABY'
When faced with an excessively large class, sometimes I split it up into a couple of modules based on its functionality, and have a virtually empty class just include those modules.
精彩评论