Just see the title, you would probably could answer this question very well. A module cannot be instantiated, is used to mixin, while a class can be instantiated, and so on. However, this blog post is not a tutorial at all. There is something else you could learn from it.
Last week, I paired with my boss, @jensendarren. He asked me a question about my code which I have never thought before. Why don’t you make
ListingConverter as a module and use it as a
mixin to the
Listing class? Actually, he asked me the right thing because sometimes I write a module, some other times I write a class and using
delegate. Here is my code.
1 2 3 4 5 6 7
He probably wants something like this.
1 2 3 4 5 6 7 8
At that time, I couldn’t answer him very well. I have read Rails Anti-Pattern book some months ago and I followed that book because it’s very convincing to me.
To be honest I never thought about using as a
module or a
class. I just understand that the author is trying to break responsibilities into multiple classes, Single Responsibilities Principle (SRP). Each class should have very specific use case and few reasons to change.
Thinking about SRP reminds me about blog post, SOLID Design Principles from Gregory Brown which I read it some months ago as well. For me, it’s an excellent blog post because it changes me quite a lot. I would recommend you go through it, at least SRP. My response will take it as a reference.
Actually, these two above code achieve the same result, but there is case where we should use one rather than the other. In this case, I would say a
class wins over a
module in terms of efficiency.
ListingConverter class contains only 1 public method,
#to_solr and almost 20 private methods. It is responsible for converting into solr json format.
ListingConverteris a module,
Listingwould contain unneccessary methods, and if we have 50 mixined into, the
Listinginstance would become bigger and bigger objects, 200 methods. Imagine this case, what if each module has name collision? Then, it might be difficult to track down the case and find out what’s wrong in those 50 mixins. Usually, a
Listinginstance would not use
to_solrmethod most of the time, but those additional methods from each module are always there which is not optimal at all. The thing will be worse when we load 5000
Listinginstance at a time to do reporting for example because the memory would go up steadily.
ListingConverteras a class is more about Single Responsibility. This class just does only one thing, convert
solr. It would be better to treat
Listingclass like a big entity contains many small entities. It should forward the message requested to its contained objects. Finally, use
Railsto make interaction a bit easier. What delegate does is that it defines methods that are passed in and forwards those methods to the
:toobject. You could do mannually as below.
1 2 3
It only instantiates
ListingConverter only when we call
#to_solr method which is more efficient. At the end of the day, the
Listing class contains only 1 additional public method.